low latency player
This commit is contained in:
parent
f5a8801b7d
commit
80be88b612
|
@ -46,7 +46,9 @@ width="32" height="32" border="0" /></a></td>
|
|||
<tr><td class="memItemLeft" nowrap align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#95e8927cc6986fe71853faae4b440852">eof</a> ()</td></tr>
|
||||
|
||||
<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#da64cba9622acf00e9f835be71191421">QxtAVFile</a> (QString filename, int fliplen, QObject *parent=0)</td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#fc7c8f10ac9e4adf3fbd2fec3d1a494f">QxtAVFile</a> (QString filename, int fliplen, int flags=0, QObject *parent=0)</td></tr>
|
||||
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#cac3319a183995c8c7f25d6156833ab9">QxtAVFile</a> (QString filename, <a class="el" href="classQxtAudioPlayer.html">QxtAudioPlayer</a> *, int flags=0, QObject *parent=0)</td></tr>
|
||||
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">int </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#9a2f34df148cced0108370e82310dcdd">flip</a> (float *)</td></tr>
|
||||
|
||||
|
@ -64,6 +66,10 @@ double </td><td class="memItemRight" valign="bottom"><a class="el" href="cl
|
|||
double </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#fd56df1972ba3b6da0522dfc0c719061">length</a> ()</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">playback length of the file in seconds. <br></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7a1d2b1184eee20305f2107aaeed972d"></a><!-- doxytag: member="QxtAVFile::reset" ref="7a1d2b1184eee20305f2107aaeed972d" args="()" -->
|
||||
void </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAVFile.html#7a1d2b1184eee20305f2107aaeed972d">reset</a> ()</td></tr>
|
||||
|
||||
<tr><td class="mdescLeft"> </td><td class="mdescRight">reset <br></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
AV decoder.
|
||||
|
@ -76,7 +82,7 @@ the buffer is interleaved (alternating right/left) and always stereo. the fliple
|
|||
|
||||
<p>
|
||||
<hr><h2>Constructor & Destructor Documentation</h2>
|
||||
<a class="anchor" name="da64cba9622acf00e9f835be71191421"></a><!-- doxytag: member="QxtAVFile::QxtAVFile" ref="da64cba9622acf00e9f835be71191421" args="(QString filename, int fliplen, QObject *parent=0)" -->
|
||||
<a class="anchor" name="fc7c8f10ac9e4adf3fbd2fec3d1a494f"></a><!-- doxytag: member="QxtAVFile::QxtAVFile" ref="fc7c8f10ac9e4adf3fbd2fec3d1a494f" args="(QString filename, int fliplen, int flags=0, QObject *parent=0)" -->
|
||||
<div class="memitem">
|
||||
<div class="memproto">
|
||||
<table class="memname">
|
||||
|
@ -92,6 +98,12 @@ the buffer is interleaved (alternating right/left) and always stereo. the fliple
|
|||
<td class="paramtype">int </td>
|
||||
<td class="paramname"> <em>fliplen</em>, </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="paramkey"></td>
|
||||
<td></td>
|
||||
<td class="paramtype">int </td>
|
||||
<td class="paramname"> <em>flags</em> = <code>0</code>, </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="paramkey"></td>
|
||||
<td></td>
|
||||
|
@ -111,6 +123,47 @@ the buffer is interleaved (alternating right/left) and always stereo. the fliple
|
|||
default constructor. pass filename and fliplen.
|
||||
</div>
|
||||
</div><p>
|
||||
<a class="anchor" name="cac3319a183995c8c7f25d6156833ab9"></a><!-- doxytag: member="QxtAVFile::QxtAVFile" ref="cac3319a183995c8c7f25d6156833ab9" args="(QString filename, QxtAudioPlayer *, int flags=0, QObject *parent=0)" -->
|
||||
<div class="memitem">
|
||||
<div class="memproto">
|
||||
<table class="memname">
|
||||
<tr>
|
||||
<td class="memname">QxtAVFile::QxtAVFile </td>
|
||||
<td>(</td>
|
||||
<td class="paramtype">QString </td>
|
||||
<td class="paramname"> <em>filename</em>, </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="paramkey"></td>
|
||||
<td></td>
|
||||
<td class="paramtype"><a class="el" href="classQxtAudioPlayer.html">QxtAudioPlayer</a> * </td>
|
||||
<td class="paramname">, </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="paramkey"></td>
|
||||
<td></td>
|
||||
<td class="paramtype">int </td>
|
||||
<td class="paramname"> <em>flags</em> = <code>0</code>, </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="paramkey"></td>
|
||||
<td></td>
|
||||
<td class="paramtype">QObject * </td>
|
||||
<td class="paramname"> <em>parent</em> = <code>0</code></td><td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>)</td>
|
||||
<td></td><td></td><td width="100%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="memdoc">
|
||||
|
||||
<p>
|
||||
default constructor. if you just use <a class="el" href="classQxtAVFile.html">QxtAVFile</a> for playback with <a class="el" href="classQxtAudioPlayer.html">QxtAudioPlayer</a>, use this ctor to use the default fliplen
|
||||
</div>
|
||||
</div><p>
|
||||
<hr><h2>Member Function Documentation</h2>
|
||||
<a class="anchor" name="9a2f34df148cced0108370e82310dcdd"></a><!-- doxytag: member="QxtAVFile::flip" ref="9a2f34df148cced0108370e82310dcdd" args="(float *)" -->
|
||||
<div class="memitem">
|
||||
|
@ -169,7 +222,7 @@ Set it to indicate you want the output to be resampled to a specific samplerate.
|
|||
<div class="memdoc">
|
||||
|
||||
<p>
|
||||
End of File Signal. There is still data available in the pipe, this is just to inform you the file has been fully read
|
||||
End of File Signal.
|
||||
</div>
|
||||
</div><p>
|
||||
<address><hr />
|
||||
|
|
|
@ -43,7 +43,8 @@ width="32" height="32" border="0" /></a></td>
|
|||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr><td></td></tr>
|
||||
<tr><td colspan="2"><br><h2>Public Slots</h2></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="classQxtAudioPlayer.html#29a6ab8036a27218930caf460dd28b1a">play</a> (QString url)</td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7eb277952135e05f564372163e44f935"></a><!-- doxytag: member="QxtAudioPlayer::play" ref="7eb277952135e05f564372163e44f935" args="(QxtAVFile *file)" -->
|
||||
void </td><td class="memItemRight" valign="bottom"><b>play</b> (<a class="el" href="classQxtAVFile.html">QxtAVFile</a> *file)</td></tr>
|
||||
|
||||
<tr><td colspan="2"><br><h2>Public Member Functions</h2></td></tr>
|
||||
<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7b74eb59ec3dc3d192257bd9bf664e25"></a><!-- doxytag: member="QxtAudioPlayer::QxtAudioPlayer" ref="7b74eb59ec3dc3d192257bd9bf664e25" args="(QObject *parent=0)" -->
|
||||
|
@ -53,32 +54,12 @@ width="32" height="32" border="0" /></a></td>
|
|||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
simple player using the <a class="el" href="classQxtAVFile.html">QxtAVFile</a> and portaudio
|
||||
<p>
|
||||
sometimes you just want to play a sound in your application. this is not meant to be a full blown media player and does not provide any functions for it.
|
||||
sometimes you just want to play a sound in your application. this is not meant to be a full blown media player and does not provide any functions for it.<p>
|
||||
example: <div class="fragment"><pre class="fragment"><a class="code" href="classQxtAudioPlayer.html">QxtAudioPlayer</a> player;
|
||||
<a class="code" href="classQxtAVFile.html">QxtAVFile</a> file(<span class="stringliteral">"test.wav"</span>,&player,Qxt::preload);
|
||||
player.<a class="code" href="classQxtAudioPlayer.html#7eb277952135e05f564372163e44f935">play</a>(&file);
|
||||
</pre></div>
|
||||
<p>
|
||||
<hr><h2>Member Function Documentation</h2>
|
||||
<a class="anchor" name="29a6ab8036a27218930caf460dd28b1a"></a><!-- doxytag: member="QxtAudioPlayer::play" ref="29a6ab8036a27218930caf460dd28b1a" args="(QString url)" -->
|
||||
<div class="memitem">
|
||||
<div class="memproto">
|
||||
<table class="memname">
|
||||
<tr>
|
||||
<td class="memname">void QxtAudioPlayer::play </td>
|
||||
<td>(</td>
|
||||
<td class="paramtype">QString </td>
|
||||
<td class="paramname"> <em>url</em> </td>
|
||||
<td> ) </td>
|
||||
<td width="100%"><code> [static, slot]</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="memdoc">
|
||||
|
||||
<p>
|
||||
usage:<p>
|
||||
<div class="fragment"><pre class="fragment"> <a class="code" href="classQxtAudioPlayer.html#29a6ab8036a27218930caf460dd28b1a">QxtAudioPlayer::play</a>(<span class="stringliteral">"sound/ding.wav"</span>);
|
||||
</pre></div> obviously you do not need to construct an object<p>
|
||||
calling this slot while another file is playing will interupt the current playback
|
||||
</div>
|
||||
</div><p>
|
||||
<address><hr />
|
||||
|
||||
<div align="center">
|
||||
|
|
|
@ -160,8 +160,6 @@ Here is a list of all documented struct and union fields with links to the struc
|
|||
: <a class="el" href="classQxtRPCPeer.html#e3fd8e63aceea84eef2a70a8fa50418d">QxtRPCPeer</a>
|
||||
<li>peerError()
|
||||
: <a class="el" href="classQxtRPCPeer.html#cd89d8b304d38cfff4fef3e0c513e1da">QxtRPCPeer</a>
|
||||
<li>play()
|
||||
: <a class="el" href="classQxtAudioPlayer.html#29a6ab8036a27218930caf460dd28b1a">QxtAudioPlayer</a>
|
||||
</ul>
|
||||
<h3><a class="anchor" name="index_q">- q -</a></h3><ul>
|
||||
<li>qMakeTripple
|
||||
|
@ -185,7 +183,7 @@ Here is a list of all documented struct and union fields with links to the struc
|
|||
<li>Qxt9Tuple
|
||||
: <a class="el" href="classQxtTuple.html#17446ec67b52e60a1ca648fa863fe240">QxtTuple< TYPELIST ></a>
|
||||
<li>QxtAVFile()
|
||||
: <a class="el" href="classQxtAVFile.html#da64cba9622acf00e9f835be71191421">QxtAVFile</a>
|
||||
: <a class="el" href="classQxtAVFile.html#cac3319a183995c8c7f25d6156833ab9">QxtAVFile</a>
|
||||
<li>QxtLongTuple
|
||||
: <a class="el" href="classQxtTuple.html#8e0bb5049828a909bfd4935bdf9221f9">QxtTuple< TYPELIST ></a>
|
||||
<li>qxtNull
|
||||
|
@ -205,6 +203,8 @@ Here is a list of all documented struct and union fields with links to the struc
|
|||
, <a class="el" href="classQxtTrippleList.html#9cac4c23fec929ba15809689c166b830">QxtTrippleList< T, K, L ></a>
|
||||
<li>resample()
|
||||
: <a class="el" href="classQxtAVFile.html#6212b0878e52ce9af097a65aa46df076">QxtAVFile</a>
|
||||
<li>reset()
|
||||
: <a class="el" href="classQxtAVFile.html#7a1d2b1184eee20305f2107aaeed972d">QxtAVFile</a>
|
||||
<li>rowCount()
|
||||
: <a class="el" href="classQxtSqlPackageModel.html#f9be109f83c28eb658f5cd21e32b8081">QxtSqlPackageModel</a>
|
||||
<li>rpcType()
|
||||
|
|
|
@ -158,12 +158,10 @@ width="32" height="32" border="0" /></a></td>
|
|||
: <a class="el" href="classQxtRPCPeer.html#e3fd8e63aceea84eef2a70a8fa50418d">QxtRPCPeer</a>
|
||||
<li>peerError()
|
||||
: <a class="el" href="classQxtRPCPeer.html#cd89d8b304d38cfff4fef3e0c513e1da">QxtRPCPeer</a>
|
||||
<li>play()
|
||||
: <a class="el" href="classQxtAudioPlayer.html#29a6ab8036a27218930caf460dd28b1a">QxtAudioPlayer</a>
|
||||
</ul>
|
||||
<h3><a class="anchor" name="index_q">- q -</a></h3><ul>
|
||||
<li>QxtAVFile()
|
||||
: <a class="el" href="classQxtAVFile.html#da64cba9622acf00e9f835be71191421">QxtAVFile</a>
|
||||
: <a class="el" href="classQxtAVFile.html#fc7c8f10ac9e4adf3fbd2fec3d1a494f">QxtAVFile</a>
|
||||
<li>QxtRPCPeer()
|
||||
: <a class="el" href="classQxtRPCPeer.html#2ca9ef835583cbbb61dae031effea560">QxtRPCPeer</a>
|
||||
<li>QxtSignalWaiter()
|
||||
|
@ -179,6 +177,8 @@ width="32" height="32" border="0" /></a></td>
|
|||
, <a class="el" href="classQxtTrippleList.html#9cac4c23fec929ba15809689c166b830">QxtTrippleList< T, K, L ></a>
|
||||
<li>resample()
|
||||
: <a class="el" href="classQxtAVFile.html#6212b0878e52ce9af097a65aa46df076">QxtAVFile</a>
|
||||
<li>reset()
|
||||
: <a class="el" href="classQxtAVFile.html#7a1d2b1184eee20305f2107aaeed972d">QxtAVFile</a>
|
||||
<li>rowCount()
|
||||
: <a class="el" href="classQxtSqlPackageModel.html#f9be109f83c28eb658f5cd21e32b8081">QxtSqlPackageModel</a>
|
||||
<li>rpcType()
|
||||
|
|
|
@ -41,9 +41,13 @@ static soundtouch::SoundTouch resampler;
|
|||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
QxtAVFile::QxtAVFile(QString filename,QxtAudioPlayer*,int flags,QObject *parent)
|
||||
{
|
||||
QxtAVFile::QxtAVFile(filename,2048,flags,parent);
|
||||
}
|
||||
|
||||
|
||||
QxtAVFile::QxtAVFile(QString filename,int fliplen,QObject *parent):QThread(parent)
|
||||
QxtAVFile::QxtAVFile(QString filename,int fliplen,int flags,QObject *parent):QThread(parent)
|
||||
{
|
||||
///defaults
|
||||
AORatio=1.0;
|
||||
|
@ -54,7 +58,8 @@ QxtAVFile::QxtAVFile(QString filename,int fliplen,QObject *parent):QThread(paren
|
|||
resample_m=0;
|
||||
playbacktime=0.0;
|
||||
eof_f=false;
|
||||
|
||||
flags_d=flags;
|
||||
blocked =false;
|
||||
/// \bug buffsize must be at least 2048
|
||||
assert(fliplen>=2048);
|
||||
assert(!filename.isEmpty());
|
||||
|
@ -92,11 +97,19 @@ QxtAVFile::QxtAVFile(QString filename,int fliplen,QObject *parent):QThread(paren
|
|||
OUT1= new float[fliplen_m+MINIMAL_SRC_LEN];
|
||||
OUT2= new float[fliplen_m+MINIMAL_SRC_LEN];
|
||||
|
||||
for (unsigned int i=0;i<fliplen_m;i++)
|
||||
if (flags & Qxt::preload)
|
||||
{
|
||||
refill(OUT1);
|
||||
refill(OUT2);
|
||||
}
|
||||
else
|
||||
{
|
||||
OUT1[i]=0;
|
||||
OUT2[i]=0;
|
||||
|
||||
for (unsigned int i=0;i<fliplen_m;i++)
|
||||
{
|
||||
OUT1[i]=0;
|
||||
OUT2[i]=0;
|
||||
}
|
||||
}
|
||||
DSRC=new float[fliplen_m*8];
|
||||
|
||||
|
@ -180,6 +193,12 @@ double QxtAVFile::length()
|
|||
//-------------------------------------------------------------
|
||||
int QxtAVFile::flip(float* out)
|
||||
{
|
||||
if (blocked)
|
||||
{
|
||||
for (unsigned int i=0;i<fliplen_m;i++)
|
||||
*out++=0.0f;
|
||||
return fliplen_m;
|
||||
}
|
||||
|
||||
if (eof_f && HF==WF){emit(eof());qWarning("called flip after eof, doing nothing.");return -1;}
|
||||
|
||||
|
@ -190,7 +209,6 @@ int QxtAVFile::flip(float* out)
|
|||
{
|
||||
decoderlock_b=OUT2;
|
||||
memcpy(out,OUT1,fliplen_m*sizeof(float));
|
||||
|
||||
WF=false;
|
||||
}
|
||||
else
|
||||
|
@ -288,12 +306,12 @@ void QxtAVFile::run()
|
|||
{
|
||||
forever
|
||||
{
|
||||
if (eof_f)return;
|
||||
if (decoderlock_b==NULL)
|
||||
{msleep(10);continue;}
|
||||
HF=(decoderlock_b==OUT2);
|
||||
refill(decoderlock_b);
|
||||
decoderlock_b=NULL;
|
||||
if (eof_f)return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,8 +401,47 @@ void QxtAVFile::refill(float * WRITE)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
||||
void QxtAVFile::reset()
|
||||
{
|
||||
blocked=true;
|
||||
eof_f=true;
|
||||
decoderlock_b=NULL;
|
||||
|
||||
wait();
|
||||
|
||||
resampler.clear();
|
||||
seek(0.0);
|
||||
playbacktime=0.0;
|
||||
DSRC_LEN=0;
|
||||
|
||||
if (flags_d & Qxt::preload)
|
||||
{
|
||||
refill(OUT1);
|
||||
refill(OUT2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (unsigned int i=0;i<fliplen_m;i++)
|
||||
{
|
||||
OUT1[i]=0;
|
||||
OUT2[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WF=false;
|
||||
HF=true;
|
||||
|
||||
eof_f=false;
|
||||
decoderlock_b=NULL;
|
||||
start();
|
||||
|
||||
blocked=false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,18 @@ the fliplean is NOT meant as per channel. it is the amount of data for all chann
|
|||
\bug currently fliplen must be minimal 1024*2 in order to get the decoder working.
|
||||
|
||||
*/
|
||||
namespace Qxt
|
||||
{
|
||||
enum QxtAVFileFlags
|
||||
{
|
||||
preload,
|
||||
fullLoad
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
class QxtAudioPlayer;
|
||||
class QxtAVFile : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -45,7 +54,12 @@ class QxtAVFile : public QThread
|
|||
/**default constructor.
|
||||
pass filename and fliplen.
|
||||
*/
|
||||
QxtAVFile(QString filename,int fliplen,QObject *parent=0);
|
||||
QxtAVFile(QString filename,int fliplen,int flags=0,QObject *parent=0);
|
||||
/**default constructor.
|
||||
if you just use QxtAVFile for playback with QxtAudioPlayer, use this ctor to use the default fliplen
|
||||
*/
|
||||
QxtAVFile(QString filename,QxtAudioPlayer*, int flags=0,QObject *parent=0);
|
||||
|
||||
~QxtAVFile();
|
||||
|
||||
|
||||
|
@ -77,6 +91,10 @@ class QxtAVFile : public QThread
|
|||
///playback length of the file in seconds.
|
||||
double length();
|
||||
|
||||
///reset
|
||||
void reset();
|
||||
|
||||
|
||||
signals:
|
||||
/**
|
||||
End of File Signal.
|
||||
|
@ -131,6 +149,11 @@ class QxtAVFile : public QThread
|
|||
///indicate that the next buffer is the last
|
||||
bool eof_f;///flip
|
||||
|
||||
|
||||
int flags_d;
|
||||
|
||||
///canot call flip
|
||||
bool blocked;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ released under the Terms of LGPL (see the LICENSE file)
|
|||
|
||||
#define FRAMES_PER_BUFFER 1024
|
||||
|
||||
|
||||
static QxtAVFile * avfile=NULL;
|
||||
|
||||
|
||||
|
@ -40,114 +39,63 @@ static int PortaudioCallback(const void *, void *outputBuffer,unsigned long fram
|
|||
|
||||
|
||||
|
||||
|
||||
class AUDIOOUT
|
||||
{
|
||||
public:
|
||||
AUDIOOUT()
|
||||
{
|
||||
///init portaudio
|
||||
Q_ASSERT(Pa_Initialize()==paNoError);
|
||||
|
||||
/// make sure the default audio out is available.for the sake of simplicity we do not check for other outputs then oss on unix
|
||||
Q_ASSERT(Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice()));
|
||||
|
||||
///open the default stream
|
||||
Q_ASSERT(Pa_OpenDefaultStream (
|
||||
&stream,
|
||||
0, ///no input channels
|
||||
2, ///stereo output
|
||||
paFloat32, ///32 bit floating output
|
||||
Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice() )->defaultSampleRate,
|
||||
FRAMES_PER_BUFFER,
|
||||
PortaudioCallback,
|
||||
&avfile
|
||||
)==paNoError);
|
||||
|
||||
///start playback
|
||||
Q_ASSERT(Pa_StartStream( stream )==paNoError);
|
||||
}
|
||||
|
||||
~AUDIOOUT()
|
||||
{
|
||||
///cleanup
|
||||
Pa_StopStream( stream );
|
||||
Pa_CloseStream( stream );
|
||||
Pa_Terminate();
|
||||
}
|
||||
|
||||
PaStream *stream;
|
||||
static PaStream *stream;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
static AUDIOOUT * audiout=NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static QxtAudioPlayerStaticEofObjectHolder * eofo=NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
QxtAudioPlayer::QxtAudioPlayer(QObject * parent):QObject(parent){}
|
||||
|
||||
|
||||
void QxtAudioPlayer::play(QString url)
|
||||
QxtAudioPlayer::QxtAudioPlayer(QObject * parent):QObject(parent)
|
||||
{
|
||||
if (!eofo)
|
||||
eofo=new QxtAudioPlayerStaticEofObjectHolder();
|
||||
|
||||
|
||||
if (!audiout)
|
||||
audiout = new AUDIOOUT();
|
||||
|
||||
if (avfile)
|
||||
{
|
||||
///set null before delete to avoid crash of callback
|
||||
QxtAVFile * B=avfile;
|
||||
avfile=NULL;
|
||||
delete (B);
|
||||
}
|
||||
|
||||
///intialise QxtAVFile. take care of the *2 QxtAVFile wants the amount of samples to push whereas portaudio means the amount per channel
|
||||
avfile = new QxtAVFile(url,FRAMES_PER_BUFFER*2);
|
||||
|
||||
connect(avfile,SIGNAL(eof()),eofo,SLOT(f__eof()));
|
||||
|
||||
|
||||
///tell avfile to resample its output to the soundcards samplerate
|
||||
avfile->resample((int)Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice() )->defaultSampleRate);
|
||||
///init portaudio
|
||||
Q_ASSERT(Pa_Initialize()==paNoError);
|
||||
|
||||
/// make sure the default audio out is available.for the sake of simplicity we do not check for other outputs then oss on unix
|
||||
Q_ASSERT(Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice()));
|
||||
|
||||
///open the default stream
|
||||
Q_ASSERT(Pa_OpenDefaultStream (
|
||||
&stream,
|
||||
0, ///no input channels
|
||||
2, ///stereo output
|
||||
paFloat32, ///32 bit floating output
|
||||
Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice() )->defaultSampleRate,
|
||||
FRAMES_PER_BUFFER,
|
||||
PortaudioCallback,
|
||||
&avfile
|
||||
)==paNoError);
|
||||
|
||||
///start playback
|
||||
Q_ASSERT(Pa_StartStream( stream )==paNoError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QxtAudioPlayerStaticEofObjectHolder::f__eof()
|
||||
{
|
||||
Pa_StopStream(audiout->stream );
|
||||
QxtAVFile * B=avfile;
|
||||
avfile=NULL;
|
||||
if (B) delete (B);
|
||||
}
|
||||
|
||||
|
||||
void QxtAudioPlayer::close()
|
||||
{
|
||||
if (audiout) delete(audiout);
|
||||
if (avfile) delete(avfile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QxtAudioPlayer::~QxtAudioPlayer()
|
||||
{
|
||||
if (eofo) delete(eofo);
|
||||
if (audiout) delete(audiout);
|
||||
if (avfile) delete(avfile);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void QxtAudioPlayer::play(QxtAVFile * file)
|
||||
{
|
||||
if(avfile)avfile->reset();
|
||||
avfile=NULL;
|
||||
|
||||
connect(file,SIGNAL(eof()),this,SLOT(feof()));
|
||||
|
||||
///tell avfile to resample its output to the soundcards samplerate
|
||||
file->resample((int)Pa_GetDeviceInfo( Pa_GetDefaultOutputDevice() )->defaultSampleRate);
|
||||
|
||||
avfile=file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QxtAudioPlayer::feof()
|
||||
{
|
||||
// if(!(QxtAVFile* )sender())return;
|
||||
if(avfile)avfile->reset();
|
||||
avfile=NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ released under the Terms of LGPL (see the LICENSE file)
|
|||
*******************************************************************/
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QxtAVFile.h>
|
||||
|
||||
|
||||
/**
|
||||
|
@ -16,18 +17,17 @@ released under the Terms of LGPL (see the LICENSE file)
|
|||
|
||||
sometimes you just want to play a sound in your application.
|
||||
this is not meant to be a full blown media player and does not provide any functions for it.
|
||||
|
||||
|
||||
example:
|
||||
\code
|
||||
QxtAudioPlayer player;
|
||||
QxtAVFile file("test.wav",&player,Qxt::preload);
|
||||
player.play(&file);
|
||||
\endcode
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class QxtAudioPlayerStaticEofObjectHolder: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void f__eof();
|
||||
};
|
||||
|
||||
|
||||
class QxtAVFile;
|
||||
|
||||
class QxtAudioPlayer : public QObject
|
||||
{
|
||||
|
@ -38,27 +38,18 @@ class QxtAudioPlayer : public QObject
|
|||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
usage:
|
||||
|
||||
\code
|
||||
QxtAudioPlayer::play("sound/ding.wav");
|
||||
\endcode
|
||||
obviously you do not need to construct an object
|
||||
|
||||
calling this slot while another file is playing will interupt the current playback
|
||||
*/
|
||||
|
||||
static void play(QString url);
|
||||
|
||||
|
||||
/**
|
||||
if you do not need sound a longer time, you should close the sound out.
|
||||
It will automaticly be reopened the next play();
|
||||
|
||||
*/
|
||||
static void close();
|
||||
|
||||
void play(QxtAVFile * file);
|
||||
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
void feof();
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user