2016-05-26 26 views
0

我使用C和Linux製作實時數據處理應用程序(使用fftw3 lib的頻譜分析儀)。我的輸入數據當前是從音頻/視頻線路輸入中獲取的。我使用PortAudio庫與h/w進行通話。 (我不要使用PortAudio的當前回調)。我選擇Portaudio,因爲它存在許多音頻記錄示例。 RtAudio雖然可能會提供較低的延遲,不幸的是寫在CPP上,而不是C(所以我有多種可移植性麻煩)。 (我應該嘗試其他包裝嗎?有沒有直接的方法來捕捉聲音緩衝區,用例子?)。使用PortAudio進行錄音:Pa_GetStreamReadAvailable無效?

我有良好的工作設置,除非DFT計算花費的時間超過了用新數據填充音頻緩衝區的時間。所以數據在系統中停留並積累,音頻輸入和圖像之間的延遲發生並增加。在頻譜分析中,不可能「扔掉」一塊數據。所以只有我能做的是警告用戶CPU低功率。但在這裏我有問題。

還有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_OpenStream」使用「Pa_OpenDefaultStream」給其他錯誤的數字(8191)。 我在哪裏錯了?

或者這是PA中的錯誤,但可以肯定的是,我更願意先問問題,然後再提交bugreport。 謝謝。

P.S.將PA庫迴歸到以前的版本(用於測試)是不可能的,我不能在現代Ubuntu中用它編譯這個例子。

+0

嘗試增加inputParameters.suggestedLatency。您已經指定了低延遲,可能比3071個樣本更短。換句話說,您並沒有要求PA創建足夠大的中間緩衝區。在PA的緩衝區溢出之前,您總是必須收集數據。不能保證PA也支持1秒的緩衝區。 –

回答

0

我不清楚這裏有一個錯誤(除了你做的FFT在你的盒子上花的時間太長)。

通常音頻子系統有少量緩衝區(在您的情況下,看起來像3是3 * 1024,您設置爲FRAMES_PER_BUFFER,2是另一個常見值),如果您無法跟上它,只是丟棄數據最近最少填充的緩衝區,沒有增長的音頻緩衝區。

您有責任及時將數據從這些緩衝區中複製出來,並在RAM或磁盤上進行緩衝,這就是您需要爲應用程序執行的操作。

我有點驚訝現代機器在音頻速率下有1024點FFT的問題。

問候,丹。

相關問題