1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
- (void)convetM4aToWav:(NSURL *)originalUrlStr destUrl:(NSString *)destUrlStr completed:(void (^)(NSError *error)) completed { if ([[NSFileManager defaultManager] fileExistsAtPath:destUrlStr]) { [[NSFileManager defaultManager] removeItemAtPath:destUrlStr error:nil]; }
NSURL *originalUrl = originalUrlStr; NSURL *destUrl = [NSURL fileURLWithPath:destUrlStr]; AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:originalUrl options:nil]; NSError *error = nil; AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset error:&error]; if (error) { NSLog (@"error: %@", error); completed(error); return; } AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks audioSettings: nil]; if (![assetReader canAddOutput:assetReaderOutput]) { NSLog (@"can't add reader output... die!"); completed(error); return; } [assetReader addOutput:assetReaderOutput]; AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:destUrl fileType:AVFileTypeCoreAudioFormat error:&error]; if (error) { NSLog (@"error: %@", error); completed(error); return; } AudioChannelLayout channelLayout; memset(&channelLayout, 0, sizeof(AudioChannelLayout)); channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, [NSNumber numberWithFloat:44100], AVSampleRateKey, [NSNumber numberWithInt:2], AVNumberOfChannelsKey, [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!"); completed(error); return; } assetWriterInput.expectsMediaDataInRealTime = NO; [assetWriter startWriting]; [assetReader startReading]; AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0]; CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale); [assetWriter startSessionAtSourceTime:startTime]; __block UInt64 convertedByteCount = 0; dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL); [assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock: ^ { while (assetWriterInput.readyForMoreMediaData) { CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer]; if (nextBuffer) { [assetWriterInput appendSampleBuffer: nextBuffer]; NSLog (@"appended a buffer (%zu bytes)", CMSampleBufferGetTotalSampleSize (nextBuffer)); convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer); } else { [assetWriterInput markAsFinished]; [assetWriter finishWritingWithCompletionHandler:^{ }]; [assetReader cancelReading]; completed(nil); break; } CMSampleBufferInvalidate(nextBuffer); CFRelease(nextBuffer); nextBuffer = NULL; } }]; }
|