// // M4aToPcmHelper.m // TianyiProSwift // // Created by i2国际私塾 on 2017/3/21. // Copyright © 2017年 Chengdu Aitu Education Technology Ltd. All rights reserved. // #import "M4aToPcmHelper.h" #import #import #import @implementation M4aToPcmHelper /** * 根据m4a音频转化成pcm格式的音频 * * @param urlStr 音频路径 * * @return pcm格式的[Int16]的Data */ + (NSURL *) M4aToPcmWithUrl:(NSURL *)url { NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectoryPath = [dirs objectAtIndex:0]; NSString *exportPath = [documentsDirectoryPath stringByAppendingPathComponent:@"pcmData.pcm"]; if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) { [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil]; } NSURL *exportURL = [NSURL fileURLWithPath:exportPath]; AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil]; NSError *assetError = nil; AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset error:&assetError]; if (assetError) { NSLog (@"error: %@", assetError); return nil; } AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL fileType:AVFileTypeCoreAudioFormat error:&assetError]; AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks audioSettings: nil]; [assetReader addOutput: assetReaderOutput]; if (assetError) { NSLog (@"error: %@", assetError); return nil; } AudioChannelLayout channelLayout; memset(&channelLayout, 0, sizeof(AudioChannelLayout)); channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, [NSNumber numberWithFloat:8000.0], AVSampleRateKey, [NSNumber numberWithInt:2], AVNumberOfChannelsKey, [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey, [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey, [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, nil]; AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:outputSettings]; if ([assetWriter canAddInput:assetWriterInput]) { [assetWriter addInput:assetWriterInput]; } else { NSLog (@"can't add asset writer input... die!"); return nil; } assetWriterInput.expectsMediaDataInRealTime = YES; [assetWriter startWriting]; [assetReader startReading]; AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0]; CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale); [assetWriter startSessionAtSourceTime: kCMTimeZero]; // while (assetWriterInput.readyForMoreMediaData == FALSE) { // NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1]; // [[NSRunLoop currentRunLoop] runUntilDate:maxDate]; // NSLog(@"等待几秒试试"); // } // __block UInt64 convertedByteCount = 0; // BOOL isFinish = false; CMSampleBufferRef sample = [assetReaderOutput copyNextSampleBuffer]; while(sample != NULL) { while (TRUE) { if ([assetWriterInput isReadyForMoreMediaData]) { [assetWriterInput appendSampleBuffer:sample]; break; } } CFRelease( sample ); sample = [assetReaderOutput copyNextSampleBuffer]; } // while (assetWriterInput.readyForMoreMediaData) { // NSLog(@"ready for"); // CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer]; // if (nextBuffer) { // // append buffer // [assetWriterInput appendSampleBuffer: nextBuffer]; // convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer); // // } // else{ // // done! // [assetWriterInput markAsFinished]; // [assetWriter finishWritingWithCompletionHandler:^{ // }]; // [assetReader cancelReading]; // isFinish = true; // // return exportURL; // } // } [assetWriterInput markAsFinished]; [assetWriter finishWritingWithCompletionHandler:^{ }]; [assetReader cancelReading]; return exportURL; } @end