//
//  M4aToPcmHelper.m
//  TianyiProSwift
//
//  Created by i2国际私塾 on 2017/3/21.
//  Copyright © 2017年 Chengdu Aitu Education Technology Ltd. All rights reserved.
//

#import "M4aToPcmHelper.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

@implementation M4aToPcmHelper

/**
 *  根据m4a音频转化成pcm格式的音频
 *
 *  @param urlStr 音频路径
 *
 *  @return pcm格式的[Int16]的Data
 */

+ (NSData *) 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 = NO;
    
    [assetWriter startWriting];
    [assetReader startReading];
    
    AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
    CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
    [assetWriter startSessionAtSourceTime: startTime];
    
    __block UInt64 convertedByteCount = 0;
    
    while (assetWriterInput.readyForMoreMediaData) {
        CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
        if (nextBuffer) {
            // append buffer
            [assetWriterInput appendSampleBuffer: nextBuffer];
            convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
        } else {
            // done!
            [assetWriterInput markAsFinished];
            [assetWriter finishWritingWithCompletionHandler:^{
            }];
            [assetReader cancelReading];
            return [NSData dataWithContentsOfURL:exportURL];
            break;
        }
    }
    return [NSData dataWithContentsOfURL:exportURL];
}

@end
