Чтение аудио сэмплов через AVAssetReader
Как вы читаете аудио-образцы через AVAssetReader? Я нашел примеры дублирования или микширования с использованием AVAssetReader, но эти петли всегда управляются контуром AVAssetWriter. Можно ли просто создать AVAssetReader и прочитать его, получить каждый образец и выбросить int32 каждого аудио-образца в массив?
Благодарю.
- Очереди отправки: как узнать, запущены ли они и как их остановить
- Как сделать ui отзывчивым все время и делать обновление фона?
- QLPreviewController удаляет или добавляет UIBarButtonItems
- как правильно использовать insertRowsAtIndexPaths?
- UITextView с подсветкой синтаксиса
- Как проверить локальный Wi-Fi (не только сотовую связь) с помощью iPhone SDK?
- как создать круглую кнопку?
- Переменная Property vs. instance
- Как использовать performSelector: withObject: afterDelay: с примитивными типами в cocoa?
- Несоответствие UUID обнаружено в загруженной библиотеке
- На iPhone: узнать, какая песня сейчас играет? (в музыкальном проигрывателе iPod)
- Как включить / выключить флэш-память iPhone?
- Ссылка с UITableViewCell на родительский UITableView?
Чтобы расширить ответ на @ amrox, вы можете получить AudioBufferList из CMBlockBufferRef, например
CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(buffer); AudioBufferList audioBufferList; CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( buffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &buffer ); for (int bufferCount=0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) { SInt16* samples = (SInt16 *)audioBufferList.mBuffers[bufferCount].mData; for (int i=0; i < numSamplesInBuffer; i++) { // amplitude for the sample is samples[i], assuming you have linear pcm to start with } } //Release the buffer when done with the samples //(retained by CMSampleBufferGetAudioBufferListWithRetainedblockBuffer) CFRelease(buffer);
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; NSDictionary *settings = @{ AVFormatIDKey : [NSNumber numberWithInt:kAudioFormatLinearPCM] }; AVAssetReaderTrackOutput *readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:settings]; [reader addOutput:readerOutput]; [reader startReading]; CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer]; while ( sample ) { sample = [readerOutput copyNextSampleBuffer]; if ( ! sample ) { continue; } CMBlockBufferRef buffer = CMSampleBufferGetDataBuffer(sample); size_t lengthAtOffset; size_t totalLength; char *data; if ( CMBlockBufferGetDataPointer( buffer, 0, &lengthAtOffset, &totalLength, &data ) != noErr ) { NSLog(@"error!"); break; } // do something with data... CFRelease(sample); }
Ответы здесь не общие. Вызов CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer
может завершиться неудачно, если AudioBufferList
должен быть разным. При использовании в качестве примера неперечисленных образцов.
Правильный способ – дважды вызвать CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer
. Первый вызов запрашивает размер, необходимый для AudioBufferList
а второй фактически заполняет AudioBufferList
.
size_t bufferSize = 0; CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( sampleBuffer, &bufferSize, NULL, 0, NULL, NULL, 0, NULL ); AudioBufferList *bufferList = malloc(bufferSize); CMBlockBufferRef blockBuffer = NULL; CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( sampleBuffer, NULL, bufferList, bufferSize, NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer ); // handle audio here free(bufferList); CFRelease(blockBuffer);
В реальном мире вы должны выполнить обработку ошибок, а также не должны malloc каждый кадр, а затем кэшировать AudioBufferList
.