NSString *tracks = @"tracks";
[asset loadValuesAsynchronouslyForKeys:@[tracks] completionHandler:^{
AVKeyValueStatus status = [asset statusOfValueForKey:tracks error:nil];
NSData *sampleData = nil;
if (status == AVKeyValueStatusLoaded) { //资源已经加载完成
sampleData = [self readAudioSamplesFromAsset:asset];
}
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(sampleData);
});
}];
}
+ (NSData *)readAudioSamplesFromAsset:(AVAsset *)asset {
// Listing 8.3
NSError *error = nil;
AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:asset error:&error];
//创建⼀个AVAssetReader实例,并赋给他⼀个资源读取。
if (!assetReader) {
NSLog(@"error creating asset reader :^%@",error);
return nil;
}
AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
/
/获取资源到的第⼀个⾳频轨道,根据期望的媒体类型获取轨道。
NSDictionary *outputSettings =
@{
AVFormatIDKey:@(kAudioFormatLinearPCM),//样本需要以未压缩的格式被读取
AVLinearPCMIsBigEndianKey:@NO,
AVLinearPCMIsFloatKey:@NO,
AVLinearPCMBitDepthKey:@(16)
};
//创建NSDictionary保存从资源轨道读取⾳频样本时使⽤的解压设置。
AVAssetReaderTrackOutput *trackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:outputSettings];    if ([assetReader canAddOutput:trackOutput]) {
[assetReader addOutput:trackOutput];
}
//创建新的AVAssetReaderTrackOutput实例,将创建的输出设置传递给它,
//将其作为AVAssetReader的输出并调⽤startReading来允许资源读取器开始预收取样本数据。
[assetReader startReading];
NSMutableData *sampleData = [NSMutableData data];
while (assetReader.status == AVAssetReaderStatusReading) {
CMSampleBufferRef sampleBuffer = [trackOutput copyNextSampleBuffer];
//调⽤跟踪输出的⽅法开始迭代,每次返回⼀个包含⾳频样本的下⼀个可⽤样本buffer。
if (sampleBuffer) {
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer);
//CMSampleBuffer中的⾳频样本包含在⼀个CMBlockBuffer类型中
/
/CMSampleBufferGetDataBuffer函数可以⽅位block buffer
size_t length = CMBlockBufferGetDataLength(blockBufferRef);
SInt16 sampleBytes[length];
//确定长度并创建⼀个16位带符号整型数组来保存⾳频样本
CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, sampleBytes);
//⽣成⼀个数组,数组中元素为CMBlockBuffer所包含的数据
[sampleData appendBytes:sampleBytes length:length];
//将数组数据内容附加在NDSData实例后⾯。
CMSampleBufferInvalidate(sampleBuffer);session如何设置和读取
//指定样本buffer已经处理和不可再继续使⽤

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。