2011-02-08 50 views
7

Hola, he estado buscando un modo de jugar y grabar audio en un sistema Linux (preferiblemente Ubuntu). Actualmente estoy trabajando en un front-end a un voice recognition toolkit que va a automatizar algunos pasos necesarios para adaptar un modelo de voz para PocketSphinx y Julius.¿Cómo se reproduce o graba audio (a .WAV) en Linux en C++?

Sugerencias de medios alternativos de audio de entrada/salida son bienvenidos, así como una solución a la error se muestra a continuación.

Aquí está el código actual que he usado hasta ahora para reproducir un archivo .WAV:

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); 
    }  
} 

NOTA: Si desea que el resto del código a este archivo, puede descargarlo directamente desde here Launchpad .

Actualización: He intentado utilizar GStreamermm, y esto no va a funcionar:

Glib::RefPtr<Pipeline> pipeline; 
    Glib::RefPtr<Element> sink, filter, source; 
    Glib::RefPtr<Gio::File> audioSrc = Gio::File::create_for_path(uri); 

    pipeline = Pipeline::create("audio-playback"); 
    source = ElementFactory::create_element("alsasrc","source"); 
    filter = ElementFactory::create_element("identity","filter"); 
    sink = ElementFactory::create_element("alsasink","sink"); 
    //sink->get_property("file",audioSrc); 
    if (!source || !filter || !sink){ 
     showErrorDialog("Houston!","We got a problem."); 
     return; 
    } 
    pipeline->add(source)->add(filter)->add(sink); 
    source->link(sink); 

    pipeline->set_state(Gst::STATE_PLAYING); 
    showInformation("Close this to stop recording"); 
    pipeline->set_state(Gst::STATE_PAUSED); 
+0

Esta sería una mejor pregunta para [stackoverflow] (http://stackoverflow.com/). –

+1

Consideraría la biblioteca gstreamer para reproducir y grabar. Pero supongo que Pulse también debería tener una opción de grabación. – Petriborg

+0

@Michael Lo publiqué en la programación, porque supuse que estaba relacionado con la programación. @Petriborg ¿Puedes demostrar un medio para hacerlo o un ** buen ** enlace sobre cómo hacerlo? GStreamer parece solo admitir OGG y CMUSphinx necesita archivos WAV. – jackyalcine

Respuesta

4

The "Hello World" application in the GStreamer documentation muestra cómo reproducir un archivo Ogg/Vorbis. Para que esto funcione con los archivos WAV, simplemente puede reemplazar "oggdemux" por "wavparse" y reemplazar "vorbisdec" por "identity" (el complemento de identidad no hace nada, es solo un marcador de posición).

instalar el soporte para el desarrollo de GStreamer (en Ubuntu) ...

sudo apt-get install libgstreamer0.10-dev 

Es necesario lo siguiente en la línea de comandos gcc para permitir el uso de bibliotecas GStreamer ...

$(pkg-config --cflags --libs gstreamer-0.10) 

Por cierto, puede que le resulte útil usar "gst-launch" para crear prototipos de tuberías GStreamer antes de escribir el código.

## recording 
gst-launch-0.10 autoaudiosrc ! wavenc ! filesink location=temp.wav 

## playback 
gst-launch-0.10 filesrc location=temp.wav ! wavparse ! autoaudiosink 

Una característica de GStreamer que puede ser útil para el reconocimiento de voz es que es fácil de insertar filtros de calidad de audio en una tubería - por lo que podría, por ejemplo, reducir el ruido que de otro modo podrían estar en la grabación. Un puntero a una lista de los complementos "buenos" de GStreamer es here.

También de interés, "PocketSphinx" (que parece estar relacionado con su proyecto) ya tiene una cierta integración de GStreamer. Ver Using PocketSphinx with GStreamer and Python

+0

No he usado Python para esta aplicación; es principalmente código en C++, ya que es el idioma que mejor conozco, pero has sido de gran ayuda y te responderé con mi estado. – jackyalcine

+0

Además, estoy intentando implementar una forma muy simple de adaptar modelos de voz para PocketSphinx/CMUSphinx. – jackyalcine

+0

@Jacky: ¡Buena suerte! – nobar

1

GStreamer/Pulso/JACK son grandes. Para cosas simples y rápidas, puede usar SoX http://sox.sourceforge.net/

+0

¿Tienen una API? No puedo usar la línea de comando; Necesito poder controlar el volumen también. – jackyalcine

+1

@Jacky Alcine: libsox es una biblioteca de lectores/escritores de formato de archivo de muestra de sonido y procesadores de efectos de sonido. Está desarrollado principalmente para ser utilizado por SoX pero es útil para cualquier aplicación de sonido. Sí, SoX también se puede usar como lib - solo llok en el archivo para obtener más detalles –

Cuestiones relacionadas