iOS LPCM具有2个通道的非交错音频输入:不可能?

时间:2010-12-12 16:36:17

标签: iphone ios audio core-audio microphone

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个频道,因为它无论如何都要回来:

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 个答案:

答案 0 :(得分:2)

内置麦克风和耳机麦克风输入均为单声道。

相机连接套件可能允许在运行某些以前的操作系统版本的某些较新的iOS设备上从某些USB麦克风输入立体声音频,但我还没有看到任何有关当前操作系统版本的报告。

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

答案 1 :(得分:1)

我认为你混淆了“Interleaved”和“Non-Interleaved”以及CoreAudio如何在ABL中提供数据。 SetAUCanonical()正在做正确的事情。 ABL有一个可变的缓冲区数组,在非交错的情况下,每个缓冲区只保存单个通道的数据。

答案 2 :(得分:1)

问题是(有时)误导性的变量名称。我也不喜欢它,但这是对正在发生的事情的解释。

mFormatFlags设置为NonInterleaved (of any form)时,mChannelsPerFrame指定频道数,其余字段应指定单个频道的所需属性。 因此,您不需要多个通道数。正确的值将是:

mBytesPerPacket = mFramesPerPacket * sizeof(sampleSizeInBytes);   // e.g. sizeof(float)
mBytesPerFrame = sizeof(sampleSizeInBytes);