iOS LPCM非交错音频输入与2个通道:不可能吗?

4
aurioTouch示例应用程序中,RemoteIO音频单元以8.24固定点格式配置为2通道非交错LPCM。这是iOS平台上的首选格式,我认为这就是硬件ADC发出的格式。他们甚至对此进行了评论(source)。
// set our required format - Canonical AU format: LPCM non-interleaved 8.24 fixed point
outFormat.SetAUCanonical(2, false);

因此,我期望当应用程序稍后接收到音频缓冲区时,它将在其mData成员中以某种顺序打包两个通道的数据。类似于这样:

mData = [L1, L2, L3, L4, R1, R2, R3, R4];

在这里,L和R代表立体声麦克风左右通道的数据。但似乎并非如此,因为SetAUCannonical()没有设置足够的内存来容纳额外的通道:

void    SetAUCanonical(UInt32 nChannels, bool interleaved)
{
    mFormatID = kAudioFormatLinearPCM;
#if CA_PREFER_FIXED_POINT
    mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
#else
    mFormatFlags = kAudioFormatFlagsCanonical;
#endif
    mChannelsPerFrame = nChannels;
    mFramesPerPacket = 1;
    mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
    if (interleaved)
        mBytesPerPacket = mBytesPerFrame = nChannels * sizeof(AudioUnitSampleType);
    else {
        mBytesPerPacket = mBytesPerFrame = sizeof(AudioUnitSampleType);
        mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
    }
}

如果“interleaved”为false,则不会将'mBytesPerPacket'和'mBytesPerFrame'乘以通道数。帧中没有足够的位来存储额外的通道。
因此,当示例代码要求2个通道时,它是否有些误导?既然无论如何都只会返回1个通道,那么它应该只要求1个通道吗?
outFormat.SetAUCanonical(1, false);

我能否这样简单地“修复” SetAUCannonical 以使事情更清晰?

mChannelsPerFrame = nChannels;
if (!interleaved) {
    mChannelsPerFrame = 1
    mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
mFramesPerPacket = 1;
mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
mBytesPerPacket = mBytesPerFrame = nChannels * sizeof(AudioUnitSampleType);     

或者你是因为其他原因才需要2个通道?我甚至认为麦克风并不是立体声麦克风。

3个回答

2

内置麦克风和耳机麦克风输入都是单声道。

相机连接套件可能允许一些USB麦克风在运行某些旧版本iOS设备的情况下提供立体声音频输入,但我没有看到任何关于当前操作系统版本能够支持此功能的报告。

此外,请检查非交错格式的2通道(立体声)是否会返回2个缓冲区到RemoteIO回调中,而不是在1个缓冲区中连接数据。


我今晚会调查这个。 - Gareth Farrington
那是我的经验。我没有为交错状态指定任何内容。模拟器默认在IO回调中要求单个交错缓冲区,但设备默认要求2个单通道缓冲区。 - Hari Honor

2

我认为你混淆了"交错"和"非交错"以及CoreAudio如何在ABLs中提供这些数据。SetAUCanonical()正在做正确的事情。在非交错情况下,ABL具有变量缓冲区数组,其中每个缓冲区仅包含单个通道的数据。


1
问题在于有时变量名会误导人。我也不喜欢这种情况,但以下是其原因的解释。
mFormatFlags 被设置为 NonInterleaved (of any form) 时,mChannelsPerFrame 指定通道数,其余字段应指定单个通道的所需属性。因此,您不需要乘以通道数。正确的值将是:
mBytesPerPacket = mFramesPerPacket * sizeof(sampleSizeInBytes);   // e.g. sizeof(float)
mBytesPerFrame = sizeof(sampleSizeInBytes);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接