M4aToPcmHelper.m 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // M4aToPcmHelper.m
  3. // TianyiProSwift
  4. //
  5. // Created by i2国际私塾 on 2017/3/21.
  6. // Copyright © 2017年 Chengdu Aitu Education Technology Ltd. All rights reserved.
  7. //
  8. #import "M4aToPcmHelper.h"
  9. #import <AudioToolbox/AudioToolbox.h>
  10. #import <AVFoundation/AVFoundation.h>
  11. #import <MediaPlayer/MediaPlayer.h>
  12. @implementation M4aToPcmHelper
  13. /**
  14. * 根据m4a音频转化成pcm格式的音频
  15. *
  16. * @param urlStr 音频路径
  17. *
  18. * @return pcm格式的[Int16]的Data
  19. */
  20. + (NSURL *) M4aToPcmWithUrl:(NSURL *)url {
  21. NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  22. NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
  23. NSString *exportPath = [documentsDirectoryPath stringByAppendingPathComponent:@"pcmData.pcm"];
  24. if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
  25. [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
  26. }
  27. NSURL *exportURL = [NSURL fileURLWithPath:exportPath];
  28. AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil];
  29. NSError *assetError = nil;
  30. AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset
  31. error:&assetError];
  32. if (assetError) {
  33. NSLog (@"error: %@", assetError);
  34. return nil;
  35. }
  36. AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportURL
  37. fileType:AVFileTypeCoreAudioFormat
  38. error:&assetError];
  39. AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
  40. assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
  41. audioSettings: nil];
  42. [assetReader addOutput: assetReaderOutput];
  43. if (assetError) {
  44. NSLog (@"error: %@", assetError);
  45. return nil;
  46. }
  47. AudioChannelLayout channelLayout;
  48. memset(&channelLayout, 0, sizeof(AudioChannelLayout));
  49. channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
  50. NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
  51. [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
  52. [NSNumber numberWithFloat:8000.0], AVSampleRateKey,
  53. [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
  54. [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
  55. [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
  56. [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
  57. [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
  58. [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
  59. nil];
  60. AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
  61. outputSettings:outputSettings];
  62. if ([assetWriter canAddInput:assetWriterInput]) {
  63. [assetWriter addInput:assetWriterInput];
  64. } else {
  65. NSLog (@"can't add asset writer input... die!");
  66. return nil;
  67. }
  68. assetWriterInput.expectsMediaDataInRealTime = YES;
  69. [assetWriter startWriting];
  70. [assetReader startReading];
  71. AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
  72. CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
  73. [assetWriter startSessionAtSourceTime: kCMTimeZero];
  74. // while (assetWriterInput.readyForMoreMediaData == FALSE) {
  75. // NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1];
  76. // [[NSRunLoop currentRunLoop] runUntilDate:maxDate];
  77. // NSLog(@"等待几秒试试");
  78. // }
  79. // __block UInt64 convertedByteCount = 0;
  80. // BOOL isFinish = false;
  81. CMSampleBufferRef sample = [assetReaderOutput copyNextSampleBuffer];
  82. while(sample != NULL)
  83. {
  84. while (TRUE) {
  85. if ([assetWriterInput isReadyForMoreMediaData]) {
  86. [assetWriterInput appendSampleBuffer:sample];
  87. break;
  88. }
  89. }
  90. CFRelease( sample );
  91. sample = [assetReaderOutput copyNextSampleBuffer];
  92. }
  93. // while (assetWriterInput.readyForMoreMediaData) {
  94. // NSLog(@"ready for");
  95. // CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
  96. // if (nextBuffer) {
  97. // // append buffer
  98. // [assetWriterInput appendSampleBuffer: nextBuffer];
  99. // convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
  100. //
  101. // }
  102. // else{
  103. // // done!
  104. // [assetWriterInput markAsFinished];
  105. // [assetWriter finishWritingWithCompletionHandler:^{
  106. // }];
  107. // [assetReader cancelReading];
  108. // isFinish = true;
  109. //
  110. // return exportURL;
  111. // }
  112. // }
  113. [assetWriterInput markAsFinished];
  114. [assetWriter finishWritingWithCompletionHandler:^{
  115. }];
  116. [assetReader cancelReading];
  117. return exportURL;
  118. }
  119. @end