希望你能帮助我:)
我正在尝试使用 PortAudio 库从多声道 ASIO 设备获取音频数据。一切正常:我设法将默认主机 API 设置为 ASIO,并且我还设法选择了 4 个特定 channel 作为输入。然后,我得到一个听起来正确的交错音频流,但我想分别获取每个 channel 数据。
PortAudio 允许进行非交错录音,但我不知道如何编写或修改我的 RecordCallBack 和多缓冲区指针(每个 channel 一个缓冲区)。当然我已经尝试过... :(
如果有人知道如何处理这个问题,那将对我有很大帮助。
原始的 RecordCallBack 函数取自一个众所周知的立体声示例(略微修改以管理 4 个 channel 而不是 2 个),但它管理单个交错缓冲区:
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
const short *rptr = (const short*)inputBuffer;
short *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS_I];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if( inputBuffer == NULL )
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = SAMPLE_SILENCE; /* ch1*/
if( NUM_CHANNELS_I == 4 ){
*wptr++ = SAMPLE_SILENCE;/* ch2*/
*wptr++ = SAMPLE_SILENCE;/* ch3*/
*wptr++ = SAMPLE_SILENCE;} /* ch4*/
}
}
else
{
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; /* ch1*/
if( NUM_CHANNELS_I == 4 ){
*wptr++ = *rptr++;/* ch2*/
*wptr++ = *rptr++;/* ch3*/
*wptr++ = *rptr++;} /* ch4*/
}
}
data->frameIndex += framesToCalc;
return finished;
}
*inputbuffer 指针声明为:
PaStream* stream;
然后调用 Open_Stream 函数:
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
playCallback,
&data );
最佳答案
Interleaved 只是意味着每个 channel 的字节都紧随其后,如:
aabbccddeeaabbccddeeaabbccddee (each character represents one byte)
其中此输入缓冲区包含 5 个 channel 中每个 channel 的两个字节(16 位):a、b、c、d 和 e,因为它在 channel 组中重复 3 次,相当于每个 channel 3 个样本 ...所以知道输入是交错的,它可以被提取到每个 channel 一个单独的输出 channel 缓冲区中,但是在你的代码中你只有一个输出缓冲区,正如你所说,这是由于必要的回调签名......一种方法是写每个输出 channel 进入单个输出缓冲区,每个 channel 由不同的偏移量分隔,因此输出将是
aaaaaabbbbbbccccccddddddeeeeee
然后在回调之外提取出每个 channel ,每个 channel 也使用相同的偏移量
首先,您需要获取给定输出缓冲区的大小,例如 X、 channel 数 Y 和每个样本每个 channel 的字节数 Z。因此全局 channel 偏移量为
size_offset = X / (Y * Z) # assure this is an integer
# if its a fraction then error in assumptions
因此,当在回调内部和外部寻址输出缓冲区时,我们使用这个偏移量和我们在哪个 channel 上的知识,W(值 0、1、2、3,...),以及哪个样本 K:
index_output_buffer = K + (W * size_offset) # 1st byte of sample pair
现在使用 index_output_buffer ... 然后计算后续索引:
index_output_buffer = K + (W * size_offset) + 1 # 2nd byte of sample pair
并使用它...您可以将给定样本的以上两个命令放入一个循环中,如果 Z 发生变化但以上假设样本是两个字节,则使用 Z 控制迭代次数
关于audio - 如何使用 PortAudio 将交错缓冲区解析为不同的多 channel 缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28637252/