Как вы проигрываете или записываете аудио (в .WAV) в Linux на C ++? - PullRequest
7 голосов
/ 08 февраля 2011

Здравствуйте, я искал способ воспроизведения и записи звука в системе Linux (предпочтительно Ubuntu). В настоящее время я работаю над интерфейсом инструментария распознавания голоса , который автоматизирует несколько шагов, необходимых для адаптации модели голоса для PocketSphinx и Julius.

Предлагаются альтернативные способы ввода / вывода звука: welcome , а также исправление ошибки , показанной ниже .

Вот текущий код, который я использовал для воспроизведения файла .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 );
    }    
}

ПРИМЕЧАНИЕ. Если вы хотите, чтобы остальной код был добавлен в этот файл, вы можете загрузить его здесь непосредственно с панели запуска.

Обновление: я пытался использовать GStreamermm, и это не будет работать:

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

Ответы [ 2 ]

4 голосов
/ 08 февраля 2011

Приложение "Hello World" в документации GStreamer показывает, как воспроизводить файл Ogg / Vorbis.Чтобы это работало с файлами WAV, вы можете просто заменить «oggdemux» на «wavparse» и заменить «vorbisdec» на «identity» (плагин идентификации ничего не делает - это просто заполнитель).

Для установкиподдержка разработки для GStreamer (в Ubuntu) ...

sudo apt-get install libgstreamer0.10-dev

В командной строке gcc требуется следующее, чтобы включить использование библиотек GStreamer ...

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

ByКстати, вы можете найти полезным использовать «gst-launch» для создания прототипов конвейеров GStreamer перед написанием кода.

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

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

Особенность GStreamer, которая может быть полезна для распознавания голоса, заключается в том, что ее легковставьте фильтры качества звука в конвейер, чтобы вы могли, например, уменьшить шум, который в противном случае мог бы быть при записи.Указатель на список «хороших» плагинов GStreamer: здесь .

Также интересно, что «PocketSphinx» (который, похоже, связан с вашим проектом) уже имеет некоторую интеграцию с GStreamer.См. Использование PocketSphinx с GStreamer и Python

1 голос
/ 27 февраля 2011

GStreamer / Pulse / JACK - это здорово.Для простых и быстрых вещей вы можете использовать SoX http://sox.sourceforge.net/

...