как правильно заполнить стереозвук AudioBuffer - PullRequest
1 голос
/ 23 мая 2011

, поэтому я использую образец кода Apple MixerHost , чтобы выполнить базовую настройку аудиографа для синтеза стереозвука. У меня есть некоторые проблемы с выяснением, как я должен заполнить буферный срез. В частности, я получаю звук только в левом канале, правый канал молчит:

AudioUnitSampleType *buffer = (AudioUnitSampleType *)ioData->mBuffers[0].mData;    
SInt16 sampleValue;

for(UInt32 i = 0; i < inNumberFrames; i++)
{
    sampleValue = sinf(inc) * 32767.0f; // generate sine signal
    inc += .08;

    buffer[i] = sampleValue;
}

if(inc > 2e10) inc -= 2e10;

Это воспроизводит синусоидальную волну на левом канале ... Вид высоты тона меняется каждые 10 секунд или около того, еще один индикатор того, что я делаю это неправильно:]

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

Если я проверяю структуру AudioBuffer, она подтверждает, что есть 2 канала, а размер байта на кадр равен 4. Итак, на кадр, есть два SInt16, верно? Один для левого, а другой для правого канала ... и они должны чередоваться?

Обратите внимание, что я использую формат потока, который отличается от примера Apple, потому что я не знаю математики с фиксированной точкой.

Формат потока настроен так:

size_t bytesPerSample = sizeof (AudioUnitSampleType);

stereoStreamFormat.mFormatID          = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags       = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
stereoStreamFormat.mBytesPerPacket    = bytesPerSample;
stereoStreamFormat.mFramesPerPacket   = 1;
stereoStreamFormat.mBytesPerFrame     = bytesPerSample;
stereoStreamFormat.mChannelsPerFrame  = 2;                    
stereoStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
stereoStreamFormat.mSampleRate        = graphSampleRate;

Итак, мой вопрос: как мне заполнить стерео буфер, который настроен, как указано выше, данными, чтобы он просто работал?

спасибо!

Ответы [ 2 ]

2 голосов
/ 23 мая 2011

Взгляните на Classes/MixerHostAudio.m в примере MixerHost и прокрутите вниз туда, где они определяют и присваивают outSamplesChannelLeft и outSamplesChannelRight. Похоже, что API ожидает левые и правые сэмплы в разных буферах, без чередования.

Что касается изменения высоты тона, попробуйте

if (inc > M_PI) inc -= 2.0*M_PI;

(или то, что Apple определяет вместо M_PI) и делайте это в цикле, а не после заполнения всего кадра. Ошибка с плавающей точкой накапливается на удивление быстро. В приведенном выше исправлении используется тот факт, что sin является периодическим по сравнению с 2*pi. Ваше исправление произвольно переносит inc обратно и вызовет сбой в точке переноса, если перенос не является непрерывным по фазе.

И, наконец, мне не ясно, равен ли ваш bytesPerSample 2 или нет, вы можете проверить это. Если это так, то я предполагаю, что ваше другое предположение о bytesPerFrame является правильным.

1 голос
/ 17 марта 2012

Вы устанавливаете mBytesPerFrame = bytesPerSample.Это позволяет только один образец на кадр.Для чередующегося стерео (т. Е. MChannelsPerFrame = 2) вам нужно два сэмпла на кадр.Попробуйте установить mBytesPerFrame = 2 * bytesPerSample.

В вашей функции рендеринга:

UInt32 numOfSamples = 2 * inNumberFrames;
for (i = 0; i < numOfSamples; i+=2) {
 buffer[i] = //assign left channel value;
 buffer[i+1] = //assign right channel value;
}
...