audio - 如何使用 PortAudio 将交错缓冲区解析为不同的多 channel 缓冲区

标签 audio portaudio asio

希望你能帮助我:)

我正在尝试使用 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/

相关文章:

audio - avcodec_decode_audio4() 中的缓冲区错误

android - Android-从Url下载后,由于数据源错误,无法播放音频。如何解决呢?

c++ - Visual Studio 2010,PortAudio DLL 编译和链接问题,C++

c++ - 为什么 ASIO 套接字 open() 会失败?

c++ - Portaudio + Opus 编码/解码音频输入

c# - 如何使用C#多选对话框中的特定文件?

python - 使用Python的pyaudio(portaudio绑定(bind))列出所有音频设备

c++ - 哪些实时 C++ 音频库适用于 Xcode 4?

sockets - Boost Asio tcp::iostream构造每秒钟使用都会引发访问冲突异常

c++ - 如何避免触发已经销毁的 boost::asio::deadline_timer