Осторожно: приведенный ниже ответ действителен, только если вы получаете данные PCM с сервера.Это, конечно, никогда не происходит.Вот почему между рендерингом аудио и получением данных вам необходим еще один шаг: преобразование данных.
В зависимости от формата, это может быть более или менее сложно, но в целом вы должны использовать Audio Converter Services для этого шага.
Вы должны использовать -(void)connection:(NSURLConnection )connection didReceiveData:(NSData)data
только для заполнения буфера с помощьюданные, поступающие с сервера и воспроизводящие его, не должны иметь ничего общего с этим методом.
Теперь, чтобы воспроизвести данные, которые вы «сохранили» в памяти, используя буфер, вам необходимо использовать RemoteIO и аудиоустройства. Вот хороший, всеобъемлющий учебник .Вы можете удалить часть «запись» из руководства, поскольку она вам на самом деле не нужна.
Как вы видите, они определяют обратный вызов для воспроизведения:
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
и playbackCallback
функция выглядит следующим образом:
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
for (int i = 0 ; i < ioData->mNumberBuffers; i++){
AudioBuffer buffer = ioData->mBuffers[i];
unsigned char *frameBuffer = buffer.mData;
for (int j = 0; j < inNumberFrames*2; j++){
frameBuffer[j] = getNextPacket();//this here is a function you have to make to get the next chunk of bytes available in the stream buffer
}
}
return noErr;
}
В основном этозаполнить буфер ioData
следующим фрагментом байтов, которые необходимо воспроизвести.Обязательно обнуляйте (отключайте) буфер ioData
, если нет новых данных для воспроизведения (проигрыватель отключается, если в буфере потока недостаточно данных).
Кроме того, вы можете добиться того жечто-то с OpenAL с использованием alSourceQueueBuffers
и alSourceUnqueueBuffers
для постановки в очередь буферов один за другим.
Вот и все.Удачной кодировки!