iOS LPCM Аудиовход без чередования с 2 каналами: невозможно?

В примере приложения aurioTouch аудиоустройство RemoteIO настроен для 2-канального LPCM без чередования в формате с фиксированной точкой 8.24. Это предпочтительный формат на платформе iOS, и я предполагаю, что это то, что излучает аппаратный АЦП. Они даже прокомментировали это (источник ):

// 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;
    }
}

Если «чередование» равно 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 канала? Я даже не думаю, что микрофон стереомикрофон.


person Gareth Farrington    schedule 12.12.2010    source источник


Ответы (3)


Встроенный микрофон и микрофонный вход гарнитуры являются монофоническими.

Комплект для подключения камеры, возможно, допускал ввод стереозвука с некоторых USB-микрофонов на некоторых новых устройствах iOS, работающих под управлением некоторых предыдущих версий ОС, но я не видел никаких сообщений об этом в текущей версии ОС.

Кроме того, проверьте, может ли 2-канальный (стерео) формат без чередования возвращать 2 буфера для обратного вызова RemoteIO вместо конкатенированных данных в 1 буфере.

person hotpaw2    schedule 12.12.2010
comment
Я расследую это сегодня вечером. - person Gareth Farrington; 14.12.2010
comment
Это был мой опыт. Я ничего не указывал для чередующегося состояния. Симулятор по умолчанию требовал один буфер с чередованием в обратном вызове ввода-вывода, но устройство по умолчанию требовало 2 одноканальных буфера. - person Hari Honor; 12.02.2012

Я думаю, вы путаете «чередование» и «не чередование» и то, как CoreAudio предоставляет вам эти данные в ABL. SetAUCanonical() работает правильно. ABL имеет переменный массив буферов, где в случае без чередования каждый буфер содержит данные только для одного канала.

person MilesMonroe    schedule 17.09.2012

Проблема заключается в (иногда) вводящих в заблуждение именах переменных. Мне это тоже не нравится, но вот объяснение происходящему.

Когда mFormatFlags установлено как NonInterleaved (of any form), тогда mChannelsPerFrame указывает количество каналов, а остальные поля должны указывать желаемые свойства для одного канала. Следовательно, вам НЕ нужно будет умножать на количество каналов. Правильные значения будут:

mBytesPerPacket = mFramesPerPacket * sizeof(sampleSizeInBytes);   // e.g. sizeof(float)
mBytesPerFrame = sizeof(sampleSizeInBytes);
person Rahav    schedule 17.11.2014