2016-05-26 2 views
0

Я делаю приложение обработки данных в реальном времени (анализатор спектра с использованием fftw3 lib) с использованием C и Linux. В настоящее время мои входящие данные берутся из h/w аудиоввода. Я использую библиотеки PortAudio для общения с h/w. (I не использовать PortAudio обратные вызовы). Я выбираю Portaudio, из-за того, что для него существует множество примеров аудиозаписи. RtAudio, хотя может предложить более низкие задержки, к сожалению, написанные на CPP, а не C (поэтому у меня много проблем с переносимостью). (Должен ли я попробовать другую оболочку? Есть ли прямой способ захвата звукового буфера с примерами?).Запись звука с использованием PortAudio: Pa_GetStreamReadAvailable не работает?

У меня прекрасная рабочая настройка, если расчеты DFT не занимают больше времени, чем достаточно для заполнения буфера аудиоданных новыми данными. Таким образом, данные остаются и накапливаются где-то в системе, и задержка между аудиовходом и изображением происходит и увеличивается. В спектральном анализе невозможно «выбросить» часть данных. Поэтому я могу только предупредить пользователя о низкой мощности процессора. Но здесь у меня проблема.

Существует Pa_GetStreamReadAvailable Функция существует, чтобы показать, сколько еще не прочитанных данных. Но для меня это вообще не работает. Я готовлю простой пример, в основном на основе файла www.kfr.co.il/files/speed_photo/complete.c

#include <sys/ioctl.h> 
#include <linux/parport.h> 
#include <linux/ppdev.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <portaudio.h> 

/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */ 
#define SAMPLE_RATE (44100) 
#define FRAMES_PER_BUFFER (1024) 
#define NUM_SECONDS  (5) 
#define NUM_CHANNELS (2) 
/* #define DITHER_FLAG  (paDitherOff) */ 
#define DITHER_FLAG  (0) /**/ 

/* Select sample format. */ 
#if 1 
#define PA_SAMPLE_TYPE paFloat32 
typedef float SAMPLE; 
#define SAMPLE_SILENCE (0.0f) 
#define PRINTF_S_FORMAT "%.8f" 
#elif 1 
#define PA_SAMPLE_TYPE paInt16 
typedef short SAMPLE; 
#define SAMPLE_SILENCE (0) 
#define PRINTF_S_FORMAT "%d" 
#elif 0 
#define PA_SAMPLE_TYPE paInt8 
typedef char SAMPLE; 
#define SAMPLE_SILENCE (0) 
#define PRINTF_S_FORMAT "%d" 
#else 
#define PA_SAMPLE_TYPE paUInt8 
typedef unsigned char SAMPLE; 
#define SAMPLE_SILENCE (128) 
#define PRINTF_S_FORMAT "%d" 
#endif 

int running = 1; 

void signalHandler(int sig) 
{ 
    running = 0; 
} 


/*******************************************************************/ 
int main(void); 
int main(void) 
{ 
    printf("Initializing PortAudio...\n"); 
    PaStreamParameters inputParameters, outputParameters; 
    PaStream *stream; 
    PaError err; 
    SAMPLE *recordedSamples; 
    int i; 
    int maxFrames; 
    int numSamples; 
    int numBytes; 
    SAMPLE max, average, val; 

    // Set ctrl-c handler 
    signal(SIGINT, signalHandler); 

    //totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */ 
    maxFrames = SAMPLE_RATE*1; 
    numSamples = maxFrames * NUM_CHANNELS; 

    numBytes = numSamples * sizeof(SAMPLE); 
    recordedSamples = (SAMPLE *) malloc(numBytes); 
    if(recordedSamples == NULL) 
    { 
     printf("Could not allocate record array.\n"); 
     exit(1); 
    } 
    for(i=0; i<numSamples; i++) recordedSamples[i] = 0; 

    err = Pa_Initialize(); 
    if(err != paNoError) goto error; 

    inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ 
    if (inputParameters.device == paNoDevice) { 
     fprintf(stderr,"Error: No default input device.\n"); 
     goto error; 
    } 
    inputParameters.channelCount = NUM_CHANNELS; 
    inputParameters.sampleFormat = PA_SAMPLE_TYPE; 
    inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; 
    inputParameters.hostApiSpecificStreamInfo = NULL; 

    /* Record some audio. -------------------------------------------- */ 
    err = Pa_OpenStream(
       &stream, 
       &inputParameters, 
       NULL,     /* &outputParameters, */ 
       SAMPLE_RATE, 
       FRAMES_PER_BUFFER, 
       paClipOff,  /* we won't output out of range samples so don't bother clipping them */ 
       NULL, /* no callback, use blocking API */ 
       NULL); /* no callback, so no callback userData */ 
    if(err != paNoError) goto error; 

    printf("Starting!\n\n"); 

    printf("Numbers should increasing:\n"); 

    err = Pa_StartStream(stream); 
    if(err != paNoError) goto error; 

    Pa_ReadStream(stream, recordedSamples, maxFrames); 
    i = 1; 
    while (i<8) 
    { 
     long toRead = Pa_GetStreamReadAvailable(stream); 
     printf("%ld %d\n", toRead, maxFrames); 
     if (toRead > maxFrames) 
      toRead = maxFrames; 
     err = Pa_ReadStream(stream, recordedSamples, toRead); 
     if(err != paNoError) goto error; 

     // Here is place for heavy calculations, 
     // they can be longer than time needed for filling one buffer. 
     // (So data, awaiting for processing, should be (and really is) 
     // accumulated somewhere in system/OS buffer.) 
     // Emulate big delays: 
     usleep(i*1000000); 
     i++; 
    } 

    printf("Stopping PortAudio...\n"); 
    err = Pa_CloseStream(stream); 
    if(err != paNoError) goto error; 

    free(recordedSamples); 

    Pa_Terminate(); 
    return 0; 

error: 
    Pa_Terminate(); 
    fprintf(stderr, "An error occured while using the portaudio stream\n"); 
    fprintf(stderr, "Error number: %d\n", err); 
    fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 
    return -1; 
} 

Я ожидаю, что все большее число в распечатке, но мои результаты явно не так:

598 44100 
3071 44100 
3071 44100 
3071 44100 
3071 44100 
3071 44100 
3071 44100 

Использование «Pa_OpenDefaultStream» вместо «Pa_OpenStream» дает другое неправильные числа (8191). Где я ошибаюсь?

Или это ошибка в PA, но, конечно, я предпочитаю сначала спросить, прежде чем файл будет опубликован. Спасибо.

P.S. Регрессия PA libs к предыдущей версии (для тестов) невозможна, я не могу скомпилировать этот пример в современном Ubuntu с ней.

+0

Попробуйте увеличить входные параметры. вы указали низкую задержку, которая, вероятно, будет меньше 3071 образцов. Другими словами, вы не просили PA создать достаточно большой промежуточный буфер. Вы всегда будете иметь возможность собирать данные до переполнения буфера PA. Нет гарантии, что PA поддерживает 1-секундный буфер. –

ответ

0

Непонятно, что здесь есть ошибка (кроме того, что вы делаете БПФ, который слишком долго на вашей коробке).

Обычно звуковая подсистема имеет небольшое количество буферов (похоже, что 3 в вашем случае 3072 - это 3 * 1024, который вы устанавливаете как FRAMES_PER_BUFFER, 2 - другое общее значение), и если вы не в состоянии поддерживать его, оно просто отбрасывает данные из в самом последнем заполненном буфере, нет никакого растущего буфера аудио.

Вы несете ответственность за то, чтобы копировать данные из этих буферов вовремя и буферизировать в ram или на диске, что вам нужно сделать для вашего приложения.

Я несколько удивлен, что у современной машины есть проблемы с 1024-битным FFT при скорости звука.

С уважением, Дэн.

 Смежные вопросы

  • Нет связанных вопросов^_^