@ -51,52 +51,6 @@
@@ -51,52 +51,6 @@
} while ( 0 )
# endif
/**
@ class AudioPlayer
@ brief Non - blocking audio player .
The audio data is played from start to finish ( no streaming ) .
*/
class AudioPlayer : public QThread
{
public :
AudioPlayer ( ALuint source , const QByteArray & data )
: mSource ( source )
{
alGenBuffers ( 1 , & mBuffer ) ;
alBufferData ( mBuffer , AL_FORMAT_MONO16 , data . constData ( ) , data . size ( ) , 44100 ) ;
alSourcei ( mSource , AL_BUFFER , mBuffer ) ;
connect ( this , & AudioPlayer : : finished , this , & AudioPlayer : : deleteLater ) ;
}
private :
void run ( ) override final
{
alSourceRewind ( mSource ) ;
alSourcePlay ( mSource ) ;
QMutexLocker locker ( & playLock ) ;
ALint state = AL_PLAYING ;
while ( state = = AL_PLAYING ) {
alGetSourcei ( mSource , AL_SOURCE_STATE , & state ) ;
waitPlaying . wait ( & playLock , 2000 ) ;
}
alSourceStop ( mSource ) ;
alDeleteBuffers ( 1 , & mBuffer ) ;
}
public :
QMutex playLock ;
QWaitCondition waitPlaying ;
private :
ALuint mBuffer ;
ALuint mSource ;
} ;
/**
Returns the singleton instance .
*/
@ -114,6 +68,7 @@ Audio::Audio()
@@ -114,6 +68,7 @@ Audio::Audio()
, alOutDev ( nullptr )
, alOutContext ( nullptr )
, alMainSource ( 0 )
, alMainBuffer ( 0 )
, outputInitialized ( false )
{
audioThread - > setObjectName ( " qTox Audio " ) ;
@ -129,6 +84,8 @@ Audio::Audio()
@@ -129,6 +84,8 @@ Audio::Audio()
captureTimer . setInterval ( AUDIO_FRAME_DURATION / 2 ) ;
captureTimer . setSingleShot ( false ) ;
captureTimer . start ( ) ;
connect ( & playMono16Timer , & QTimer : : timeout , this , & Audio : : playMono16SoundCleanup ) ;
playMono16Timer . setSingleShot ( true ) ;
if ( ! audioThread - > isRunning ( ) )
audioThread - > start ( ) ;
@ -360,6 +317,16 @@ bool Audio::initOutput(QString outDevDescr)
@@ -360,6 +317,16 @@ bool Audio::initOutput(QString outDevDescr)
return true ;
}
/**
Play a 44100 Hz mono 16 bit PCM sound from a file
*/
void Audio : : playMono16Sound ( const QString & path )
{
QFile sndFile ( path ) ;
sndFile . open ( QIODevice : : ReadOnly ) ;
playMono16Sound ( QByteArray ( sndFile . readAll ( ) ) ) ;
}
/**
Play a 44100 Hz mono 16 bit PCM sound
*/
@ -370,27 +337,23 @@ void Audio::playMono16Sound(const QByteArray& data)
@@ -370,27 +337,23 @@ void Audio::playMono16Sound(const QByteArray& data)
if ( ! autoInitOutput ( ) )
return ;
AudioPlayer * player = new AudioPlayer ( alMainSource , data ) ;
connect ( player , & AudioPlayer : : finished , [ = ] ( ) {
QMutexLocker locker ( & audioLock ) ;
if ( ! alMainBuffer )
alGenBuffers ( 1 , & alMainBuffer ) ;
if ( outSources . isEmpty ( ) )
cleanupOutput ( ) ;
else
qDebug ( " Audio output not closed -> there are pending subscriptions. " ) ;
} ) ;
ALint state ;
alGetSourcei ( alMainSource , AL_SOURCE_STATE , & state ) ;
if ( state = = AL_PLAYING )
{
alSourceStop ( alMainSource ) ;
alSourcei ( alMainSource , AL_BUFFER , AL_NONE ) ;
}
player - > start ( ) ;
}
alBufferData ( alMainBuffer , AL_FORMAT_MONO16 , data . constData ( ) , data . size ( ) , 44100 ) ;
alSourcei ( alMainSource , AL_BUFFER , static_cast < ALint > ( alMainBuffer ) ) ;
alSourcePlay ( alMainSource ) ;
/**
Play a 44100 Hz mono 16 bit PCM sound from a file
*/
void Audio : : playMono16Sound ( const QString & path )
{
QFile sndFile ( path ) ;
sndFile . open ( QIODevice : : ReadOnly ) ;
playMono16Sound ( QByteArray ( sndFile . readAll ( ) ) ) ;
int durationMs = data . size ( ) * 1000 / 2 / 44100 ;
playMono16Timer . start ( durationMs + 50 ) ;
}
/**
@ -479,6 +442,12 @@ void Audio::cleanupOutput()
@@ -479,6 +442,12 @@ void Audio::cleanupOutput()
alSourceStop ( alMainSource ) ;
alDeleteSources ( 1 , & alMainSource ) ;
if ( alMainBuffer )
{
alDeleteBuffers ( 1 , & alMainBuffer ) ;
alMainBuffer = 0 ;
}
if ( ! alcMakeContextCurrent ( nullptr ) )
qWarning ( " Failed to clear audio context. " ) ;
@ -493,6 +462,20 @@ void Audio::cleanupOutput()
@@ -493,6 +462,20 @@ void Audio::cleanupOutput()
}
}
void Audio : : playMono16SoundCleanup ( )
{
QMutexLocker locker ( & audioLock ) ;
ALint state ;
alGetSourcei ( alMainSource , AL_SOURCE_STATE , & state ) ;
if ( state = = AL_STOPPED )
{
alSourcei ( alMainSource , AL_BUFFER , AL_NONE ) ;
alDeleteBuffers ( 1 , & alMainBuffer ) ;
alMainBuffer = 0 ;
}
}
void Audio : : doCapture ( )
{
QMutexLocker lock ( & audioLock ) ;