Ash*_*h K 3 c portaudio boost-thread circular-buffer data-structures
我正在使用PortAudio来实现实时音频处理。
我的主要任务是连续从麦克风获取数据,并提供100个要处理的样本(each FRAME = 100 samples at a time)
到其他处理线程。
这是我的回调,每次连续收集100个样本-
static int paStreamCallback( const void* input, void* output,
unsigned long samplesPerFrame,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData ) {
paTestData *data = (paTestData*) userData;
const SAMPLE *readPtr = (const SAMPLE*)input; // Casting input read to valid input type SAMPLE (float)
unsigned long totalSamples = TOTAL_NUM_OF_SAMPLES ; // totalSamples = 100 here
(void) output;
(void) timeInfo;
(void) statusFlags;
static int count = 1;
if(data->sampleIndex < count * samplesPerFrame){
data->recordedSample[data->sampleIndex] = *readPtr;
data->sampleIndex++;
}
else if(data->sampleIndex == count * samplesPerFrame){
processSampleFrame(data->recordedSample);
count++;
finished = paContinue;
}
return finished;
}
Run Code Online (Sandbox Code Playgroud)
我的主要功能-
int main(void){
// Some Code here
data.sampleIndex = 0;
data.frameIndex = 1;
numBytes = TOTAL_NUM_OF_SAMPLES * sizeof(SAMPLE);
data.recordedSample = (SAMPLE*)malloc(numBytes);
for(i=0; i < TOTAL_NUM_OF_SAMPLES; i++)
data.recordedSample[i] = 0;
// Open Stream Initialization
err = Pa_StartStream(stream);
/* Recording audio here..Speak into the MIC */
printf("\nRecording...\n");
fflush(stdout);
while((err = Pa_IsStreamActive(stream)) == 1)
Pa_Sleep(10);
if(err < 0)
goto done;
err = Pa_CloseStream(stream);
// Some more code here
}
Run Code Online (Sandbox Code Playgroud)
将100个样本的每个帧发送到processSampleFrame。
void processSampleFrame(SAMPLE *singleFrame){
// Free buffer of this frame
// Processing sample frame here
}
Run Code Online (Sandbox Code Playgroud)
挑战在于,我需要实现一种时间processSampleFrame
来处理样本的方式,我callBack
应该保持活动状态并继续获取下一个样本Frame of 100 samples
(可能更多地取决于的处理时间processSampleFrame
)。
缓冲区还应该能够将自身释放到帧,以便它尽快传递到processSampleFrame
。
编辑2:
我试图实施PaUtilRingBuffer
该PortAudio
规定。这是我的回叫。
printf("Inside callback\n");
paTestData *data = (paTestData*) userData;
ring_buffer_size_t elementsWritable = PaUtil_GetRingBufferWriteAvailable(&data->ringBuffer);
ring_buffer_size_t elementsToWrite = rbs_min(elementsWritable, (ring_buffer_size_t)(samplesPerFrame * numChannels));
const SAMPLE *readPtr = (const SAMPLE*)input;
printf("Sample ReadPtr = %.8f\n", *readPtr);
(void) output; // Preventing unused variable warnings
(void) timeInfo;
(void) statusFlags;
data->frameIndex += PaUtil_WriteRingBuffer(&data->ringBuffer, readPtr, elementsToWrite);
return paContinue;
Run Code Online (Sandbox Code Playgroud)
和主要:
int main(void){
paTestData data; // Object of paTestData structure
fflush(stdout);
data.frameIndex = 1;
long numBytes = TOTAL_NUM_OF_SAMPLES * LIMIT;
data.ringBufferData = (SAMPLE*)PaUtil_AllocateMemory(numBytes);
if(PaUtil_InitializeRingBuffer(&data.ringBuffer, sizeof(SAMPLE), ELEMENTS_TO_WRITE, data.ringBufferData) < 0){
printf("Failed to initialise Ring Buffer.\n");
goto done;
err = Pa_StartStream(stream);
/* Recording audio here..Speak into the MIC */
printf("\nRecording samples\n");
fflush(stdout);
while((err = Pa_IsStreamActive(stream)) == 1)
Pa_Sleep(10);
if(err < 0)
goto done;
err = Pa_CloseStream(stream);
// Error Handling here
}
Run Code Online (Sandbox Code Playgroud)
PaTestData
结构体 :
typedef struct{
SAMPLE *ringBufferData;
PaUtilRingBuffer ringBuffer;
unsigned int frameIndex;
}
paTestData;
Run Code Online (Sandbox Code Playgroud)
成功获取分配的空间后,由于无法使用文档中建议的任何内容free
,我面临着相同的段故障问题。callback
PortAudio
我在哪里可以释放分配给处理线程的已分配帧的缓冲区。可能是获得线程同步的一种方法,在这里确实很有用。感谢您的帮助。
处理音频输入的示例代码:
#define FRAME_SIZE 1024
#define CIRCULAR_BUFFER_SIZE (FRAME_SIZE * 4)
float buffer[CIRCULAR_BUFFER_SIZE];
typedef struct {
int read, write;
float vol;
} paData;
static int paStreamCallback(const void* input, void* output,
unsigned long samplesPerFrame,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData) {
paData *data = (paData *)userData;
// Write input buffer to our buffer: (memcpy function is fine, just a for loop of writing data
memcpy(&buffer[write], input, samplesPerFrame); // Assuming samplesPerFrame = FRAME_SIZE
// Increment write/wraparound
write = (write + FRAME_SIZE) % CIRCULAR_BUFFER_SIZE;
// dummy algorithm for processing blocks:
processAlgorithm(&buffer[read]);
// Write output
float *dummy_buffer = &buffer[read]; // just for easy increment
for (int i = 0; i < samplesPerFrame; i++) {
// Mix audio input and processed input; 50% mix
output[i] = input[i] * 0.5 + dummy_buffer[i] * 0.5;
}
// Increment read/wraparound
read = (read + FRAME_SIZE) % CIRCULAR_BUFFER_SIZE;
return paContinue;
}
int main(void) {
// Initialize code here; any memory allocation needs to be done here! default buffers to 0 (silence)
// initialize paData too; write = 0, read = 3072
// read is 3072 because I'm thinking about this like a delay system.
}
Run Code Online (Sandbox Code Playgroud)
把它和一粒盐一起吃; 显然,这样做的更好方法,但是可以用作起点。