AudioBufferList для модуля AUHAL, формат выходного потока которого сжат.

Я знаю, что этот пост довольно длинный, но я стараюсь максимально контекстуализировать мою проблему, потому что считаю, что она довольно уникальна (не смог найти ни одной связанной проблемы, кроме этот. Последний вопрос находится в самом конце поста и вот полный код.

Прежде всего, немного контекста. я использую CoreAudio а также AudioToolbox библиотека, точнее Аудиоустройства. Я на MacOS. Моя конечная цель — записать звук с любого устройства ввода (следовательно, использовать аудиоустройства поверх простого AudioQueueBuffer) и записать его в аудиофайл. Я считаю, что самая сложная часть моей программы — конвертировать из LPCM в AAC (в моем случае) в течение один аудио блок, следовательно, AUGraph не используется.

Моя программа — это всего лишь одно аудиоустройство, заключенное в класс, AudioUnit mInputUnit который является AUHAL единицей. Следовательно, я следовал этому это техническое примечание настроить это. По сути, я связываю область ввода элемента ввода (поскольку элемент вывода отключен) с аудиоустройством, т.е. моим встроенным микрофоном.

Затем я обновляю AudioFormat выходной области блока соответственно.

  ...
inputStream.mFormatID = kAudioFormatMPEG4AAC;
inputStream.mFormatFlags = 0;
inputStream.mBitsPerChannel = 0;
checkError(
AudioUnitSetProperty(
mInputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&inputStream,
propertySize
),
"Couldn't set output stream format.");

Следовательно, на данный момент, аудиоустройство должен работать следующим образом:

Запись с устройства ввода в LPCM [INPUT SCOPE] ==> Преобразование из LPCM в ==> Визуализация в AAC.

Обратите внимание, что каждый формат потока (вход и выход) использует 2 канала. Ни входной, ни выходной поток не имеет своего mFormatFlags установлен в kAudioFormatIsNonInterleavedтак что они оба чередуются.
На самом деле, я думаю, что именно отсюда и возникает проблема, но не понимаю, почему.

На данный момент, кажется, все работает правильно. Проблема возникает, когда я пытаюсь визуализировать аудиоустройство после установки входного обратного вызова.

Я нашел записку, в которой говорится следующее:

«По соглашению, AUHAL устраняет перемежение многоканального звука. Это означает, что вы устанавливаете два AudioBuffer одного канала каждый вместо того, чтобы устанавливать один AudioBuffer с mNumberChannels == 2. Распространенной причиной проблем paramErr (-50) в вызовах AudioUnitRender () является наличие AudioBufferLists, чья топология (или расположение буферов) не совпадает с тем, что готово для создания устройства. Работая на уровне юнитов, вы почти всегда хотите делать это без чередования ».

Выдержка из: Крис Адамсон & Кевин Авила. «Learning Core Audio: практическое руководство по программированию звука для Mac и iOS». IBooks.

Следовательно, я следовал соответствующей структуре кода для воспроизведения аудио.

OSStatus Recorder::inputProc(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData
)
{
Recorder *This = (Recorder *) inRefCon;
CAStreamBasicDescription outputStream;
This->getStreamBasicDescription(kAudioUnitScope_Output, outputStream);

UInt32 bufferSizeBytes = inNumberFrames * sizeof(Float32);
UInt32 propertySize = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * outputStream.mChannelsPerFrame);
auto bufferList = (AudioBufferList*) malloc(propertySize);
bufferList->mNumberBuffers = outputStream.mChannelsPerFrame;

for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
{
bufferList->mBuffers[i].mNumberChannels = 1;
bufferList->mBuffers[i].mDataByteSize = bufferSizeBytes;
bufferList->mBuffers[i].mData = malloc(bufferSizeBytes);
}

checkError(
AudioUnitRender(
This->mInputUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
bufferList
),
"Couldn't render audio unit.");
free(bufferList);
}

И затем, когда я пытаюсь сделать аудио, у меня появляется следующая ошибка Error: Couldn't render audio unit. (-50) который на самом деле тот, который должен был фиксированный следуя примечанию, которое смущает меня еще больше.

Вопрос

На данный момент, я не знаю, связано ли это с моей общей архитектурой, т.е. AUGraph и добавить выходной модуль вместо попытки конвертировать из канонического формата в сжатый формат В рамках одного AUHAL модуля?
Или это как-то связано с тем, как я предварительно выделяю свой AudioBufferList?

1

Решение

Мне удалось решить эту проблему, переработав весь процесс. Короче говоря, у меня все еще есть уникальный модуль AUHAL, но вместо преобразования формата в модуле AUHAL я делаю это в обратном вызове рендеринга с расширенным аудиофайлом, который принимает исходный формат и формат назначения.
Вся задача состоит в том, чтобы найти правильное описание формата, которое в основном просто проверяет различные значения для mFormatID, mFormatFlags так далее…

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]