-
-
Save SpiritualEvan/d2788c7630c0dece4ee4 to your computer and use it in GitHub Desktop.
A Swift adaptation of Chris Adamson's Objective-C code for exporting iPod Library audio tracks (obtained as AVAssets using an MPMediaPickerController) to LPCM. See http://www.subfurther.com/blog/2010/12/13/from-ipod-library-to-pcm-samples-in-far-fewer-steps-than-were-previously-necessary/ for Chris' original post.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import AVFoundation | |
protocol FileConverterDelegate { | |
func fileConversionCompleted() | |
} | |
class FileConverter : NSObject { | |
var delegate : FileConverterDelegate? | |
func convertIpodAudioWithAsset(asset: AVURLAsset, exportPath: String) | |
{ | |
// MARK: Reader Setup | |
// create a reader | |
var assetError = NSErrorPointer() | |
let assetReader = AVAssetReader(asset: asset, error: assetError) | |
if (assetError != nil) { | |
println(assetError) | |
return | |
} | |
// create an asset for the reader | |
var assetReaderOutput : AVAssetReaderOutput = AVAssetReaderAudioMixOutput(audioTracks: asset.tracks, audioSettings: nil) | |
// confirm we can add an output to the reader... | |
if (assetReader.canAddOutput(assetReaderOutput) == false) { | |
println("can't add reader output... die!") | |
return // ...and bail if we can't | |
} | |
// but if we can, then add our output to the asset reader | |
assetReader.addOutput(assetReaderOutput) | |
// create an export url from our exportPath (AVAssetWriter requires an NSURL) | |
let exportURL = NSURL.fileURLWithPath(exportPath) | |
// MARK: Writer Setup | |
// create an asset writer with our new exportURL | |
let assetWriter = AVAssetWriter(URL: exportURL, fileType: AVFileTypeCoreAudioFormat, error: assetError) | |
// make sure we're good, bail if we're not | |
if (assetError != nil) { | |
println(assetError) | |
return | |
} | |
// set up the channel layout | |
var channelLayout = AudioChannelLayout() | |
memset(&channelLayout, 0, sizeof(AudioChannelLayout)); | |
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; | |
// set up a dictionary with our outputsettings | |
var outputSettings = [ | |
AVFormatIDKey: kAudioFormatLinearPCM, | |
AVSampleRateKey: 44100, | |
AVNumberOfChannelsKey: 2, | |
AVChannelLayoutKey: NSData(bytes:&channelLayout, length:sizeof(AudioChannelLayout)), | |
AVLinearPCMBitDepthKey: 16, | |
AVLinearPCMIsNonInterleaved: false, | |
AVLinearPCMIsFloatKey: false, | |
AVLinearPCMIsBigEndianKey: false | |
] | |
// create an asset writer input | |
let assetWriterInput = AVAssetWriterInput(mediaType:AVMediaTypeAudio, outputSettings:outputSettings as NSDictionary as [NSObject : AnyObject]) | |
if (assetWriter.canAddInput(assetWriterInput)) { | |
assetWriter.addInput(assetWriterInput) | |
} else { | |
println("can't add asset writer input... die!") | |
return | |
} | |
assetWriterInput.expectsMediaDataInRealTime = false | |
// MARK: File Conversion | |
assetWriter.startWriting() | |
assetReader.startReading() | |
let audioTrack = asset.tracks[0] as! AVAssetTrack | |
let startTime = CMTimeMake(0, audioTrack.naturalTimeScale) | |
assetWriter.startSessionAtSourceTime(startTime) | |
// we need to do this on another thread, so let's set up a dispatch group... | |
var convertedByteCount : Int = 0 | |
let dispatchGroup = dispatch_group_create() | |
let mediaInputQueue = dispatch_queue_create("mediaInputQueue", nil) | |
// ... and go | |
dispatch_group_enter(dispatchGroup) | |
assetWriterInput.requestMediaDataWhenReadyOnQueue(mediaInputQueue) { | |
while assetWriterInput.readyForMoreMediaData { | |
var nextBuffer = assetReaderOutput.copyNextSampleBuffer() | |
if nextBuffer != nil { | |
// append buffer | |
assetWriterInput.appendSampleBuffer(nextBuffer) | |
convertedByteCount += CMSampleBufferGetTotalSampleSize(nextBuffer) | |
} else { | |
// done! | |
assetWriterInput.markAsFinished() | |
assetReader.cancelReading() | |
dispatch_group_leave(dispatchGroup) | |
// notify our delegate that we're done with the conversion | |
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), { | |
self.delegate?.fileConversionCompleted() | |
}) | |
break | |
} | |
} | |
} // end assetWriterInput block | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment