简体   繁体   English

通过AVAssetReader读取音频样本

[英]Reading audio samples via AVAssetReader

How do you read audio samples via AVAssetReader? 你如何通过AVAssetReader读取音频样本? I've found examples of duplicating or mixing using AVAssetReader, but those loops are always controlled by the AVAssetWriter loop. 我找到了使用AVAssetReader进行复制或混合的示例,但这些循环始终由AVAssetWriter循环控制。 Is it possible just to create an AVAssetReader and read through it, getting each sample and throwing the int32 of each audio sample into an array? 是否可以创建一个AVAssetReader并读取它,获取每个样本并将每个音频样本的int32抛入一个数组?

Thanks. 谢谢。

To expand on @amrox's answer, you can get an AudioBufferList from the CMBlockBufferRef, eg 要扩展@ amrox的答案,您可以从CMBlockBufferRef获取AudioBufferList,例如

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);
}

The answers here are not generic. 这里的答案不是通用的。 The call to CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer might fail when the AudioBufferList needs to be sized differently. AudioBufferList大小不同时,对CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer的调用可能会失败。 When having non-intererleaved samples as example. 以非交错样本为例。

The correct way is to call CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer twice. 正确的方法是两次调用CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer The first call queries the size needed for the AudioBufferList and second one actually fills the AudioBufferList . 第一个调用查询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);

In a real world example you must perform error handling and also you should not malloc every frame, instead cache the AudioBufferList . 在现实世界的示例中,您必须执行错误处理,并且您不应该每帧都使用malloc,而是缓存AudioBufferList

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM