2011-02-08 6 views
7

Ciao, ho cercato un modo per gioco e registrare audio su un sistema Linux (preferibilmente Ubuntu). Attualmente sto lavorando a un front-end su un voice recognition toolkit che automatizzerà alcuni passaggi necessari per adattare un modello vocale per PocketSphinx e Julius.Come si suona o si registra audio (su .WAV) su Linux in C++?

Suggerimenti di mezzi alternativi di ingresso/uscita audio sono ammessi , oltre che una correzione al bug mostrato sotto.

Ecco il codice corrente che ho usato finora per riprodurre un file .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: Se si desidera che il resto del codice a questo file, è possibile scaricarlo direttamente da here Launchpad .

Aggiornamento: Ho provato ad utilizzare GStreamermm, e questo non funzionerà:

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

Questa sarebbe una domanda migliore per [StackOverflow] (http://stackoverflow.com/). –

+1

Considererei la libreria gstreamer per la riproduzione e la registrazione. Ma suppongo che Pulse dovrebbe avere anche opzioni di registrazione? – Petriborg

+0

@ Michael l'ho postato su quello di programmazione, perché ho pensato che fosse relativo alla programmazione. @Petriborg Puoi dimostrare un mezzo per farlo o un ** buon ** link su come farlo? GStreamer sembra supportare solo OGG e CMUSphinx ha bisogno di file WAV. – jackyalcine

risposta

4

The "Hello World" application in the GStreamer documentation mostra come riprodurre un file Ogg/Vorbis. Per farlo funzionare con i file WAV, puoi semplicemente sostituire "oggdemux" con "wavparse" e sostituire "vorbisdec" con "identity" (il plugin di identità non fa nulla - è solo un segnaposto).

di installare il supporto di sviluppo per GStreamer (su Ubuntu) ...

sudo apt-get install libgstreamer0.10-dev 

È necessario il seguente sulla gcc-riga di comando per consentire l'uso di librerie GStreamer ...

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

A proposito, potresti trovare utile utilizzare "gst-launch" per la prototipazione delle pipeline di GStreamer prima di scrivere il codice.

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

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

Una caratteristica di GStreamer che possono essere utili per il riconoscimento vocale è che è facile da inserire filtri di qualità audio in una pipeline - così si potrebbe, ad esempio, ridurre il rumore che altrimenti potrebbero essere nella registrazione. Un puntatore a un elenco dei plugin "validi" di GStreamer è here.

Anche di interesse, "PocketSphinx" (che sembra essere correlato al progetto) ha già qualche integrazione con GStreamer. Vedi Using PocketSphinx with GStreamer and Python

+0

Non ho usato Python per questa applicazione; è principalmente il codice in C++, in quanto è la lingua che conosco meglio, ma sei stato di grande aiuto e ti risponderò con il mio stato. – jackyalcine

+0

Inoltre, sto tentando di implementare un modo super semplice per adattare i modelli vocali per PocketSphinx/CMUSphinx. – jackyalcine

+0

@Jacky: buona fortuna! – nobar

1

GStreamer/Pulse/JACK sono fantastici. per le cose semplici e veloci si potrebbe utilizzare SoX http://sox.sourceforge.net/

+0

Hanno un'API? Non posso usare la riga di comando; Devo essere in grado di controllare anche il volume. – jackyalcine

+1

@Jacky Alcine: libsox è una libreria di lettori/scrittori di formati di file audio di esempio e processori di effetti sonori. È principalmente sviluppato per essere utilizzato da SoX ma è utile per qualsiasi applicazione audio. Sì, SoX può essere utilizzato come un lib troppo - solo llok in archivio per i dettagli –