Несколько шагов:
I. Создайте свой локальный буфер, как в примере ниже, и вы должны убедиться, что
a: при записи в буфер достаточно свободного места
b: при чтении из буфера достаточно данных
глядя на чтение / запись idx
</p>
<pre><code>typedef struct
{
//suppose non-interleaved LEI16 LPCM format
SInt16 data[MUSIC_RING_BUFFER_NUM_CHANNEL][MUSIC_RING_BUFFER_SIZE];
UInt16 readIdx;
UInt16 writeIdx;
} MyRingBuffer;
II. Каждый раз получайте некоторые необработанные данные из AVAssetTrackOuput, например
</p>
<pre><code>CMSampleBufferRef nextBuffer = [self.trackOutput copyNextSampleBuffer];
CMBlockBufferRef buffer = CMSampleBufferGetDataBuffer( nextBuffer );
size_t lengthAtOffset;
size_t totalLength;
char* data;
if( CMBlockBufferGetDataPointer( buffer, 0, &lengthAtOffset, &totalLength, &data ) != noErr )
{
NSLog( @"error!" );
return;
}
//raw audio sample data now in (char*) data
III. Затем скопируйте данные в локальный буфер
Необработанные данные для 16-битного LPCM без чередования будут такими, как
[2 bytes data x N, from left channel][2 bytes data x N from right channel]
используйте memcpy для копирования в локальный буфер и обновления writeIdx
- Затем напишите функцию обратного вызова входного рендеринга для EQ AudioUnit, она читает из вашего локального буфера и обновляет readIdx в других потоках. И он вызывает заполнение буфера в другом потоке , если места достаточно, например
</p>
<pre><code>[self performSelectorOnMainThread:@selector(fillMusicBuffer:) withObject:Nil waitUntilDone:NO];
Кстати, всегда проверяя настройки аудиоформата одинаковые или нет. Получить информацию ASBD из CMSampleBufferRef и сравнить с настройкой входа AudioUnit
</p>
<pre><code>const AudioStreamBasicDescription *audioDescription = CMAudioFormatDescriptionGetStreamBasicDescription(CMSampleBufferGetFormatDescription(nextBuffer));