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