Hello, I've been looking for a way to play and record audio on a Linux (preferably Ubuntu) system. I'm currently working on a front-end to a voice recognition toolkit that'll automate a few steps required to adapt a voice model for PocketSphinx and Julius.
Suggestions of alternative means of audio input/output are welcome, as well as a fix to the bug shown below.
Here is the current code I've used so far to play a .WAV file:
void Engine::sayText ( const string OutputText ) {
string audioUri = "temp.wav";
string requestUri = this->getRequestUri( OPENMARY_PROCESS , OutputText.c_str( ) );
int error , audioStream;
pa_simple *pulseConnection;
pa_sample_spec simpleSpecs;
simpleSpecs.format = PA_SAMPLE_S16LE;
simpleSpecs.rate = 44100;
simpleSpecs.channels = 2;
eprintf( E_MESSAGE , "Generating audio for '%s' from '%s'..." , OutputText.c_str( ) , requestUri.c_str( ) );
FILE* audio = this->getHttpFile( requestUri , audioUri );
fclose(audio);
eprintf( E_MESSAGE , "Generated audio.");
if ( ( audioStream = open( audioUri.c_str( ) , O_RDONLY ) ) < 0 ) {
fprintf( stderr , __FILE__": open() failed: %s\n" , strerror( errno ) );
goto finish;
}
if ( dup2( audioStream , STDIN_FILENO ) < 0 ) {
fprintf( stderr , __FILE__": dup2() failed: %s\n" , strerror( errno ) );
goto finish;
}
close( audioStream );
pulseConnection = pa_simple_new( NULL , "AudioPush" , PA_STREAM_PLAYBACK , NULL , "openMary C++" , &simpleSpecs , NULL , NULL , &error );
for (int i = 0;;i++ ) {
const int bufferSize = 1024;
uint8_t audioBuffer[bufferSize];
ssize_t r;
eprintf( E_MESSAGE , "Buffering %d..",i);
/* Read some data ... */
if ( ( r = read( STDIN_FILENO , audioBuffer , sizeof (audioBuffer ) ) ) <= 0 ) {
if ( r == 0 ) /* EOF */
break;
eprintf( E_ERROR , __FILE__": read() failed: %s\n" , strerror( errno ) );
if ( pulseConnection )
pa_simple_free( pulseConnection );
}
/* ... and play it */
if ( pa_simple_write( pulseConnection , audioBuffer , ( size_t ) r , &error ) < 0 ) {
fprintf( stderr , __FILE__": pa_simple_write() failed: %s\n" , pa_strerror( error ) );
if ( pulseConnection )
pa_simple_free( pulseConnection );
}
usleep(2);
}
/* Make sure that every single sample was played */
if ( pa_simple_drain( pulseConnection , &error ) < 0 ) {
fprintf( stderr , __FILE__": pa_simple_drain() failed: %s\n" , pa_strerror( error ) );
if ( pulseConnection )
pa_simple_free( pulseConnection );
}
}
NOTE: If you want the rest of the code to this file, you can download it here directly from Launchpad.