I been searching for a solution for this but so far I couldn't find it.
Right now I'm creating an audio file with AVMutableComposition and writing it to disk with AVAssetExportSession so I can load it with AVAudioPlayer and play it at a certain time. The fact that writing it to disk takes to much time is slowing things down and in some cases make my app very slow.
The creation part of the audio takes very little time, so I was wondering if insteed of exporting the file to disk I could just export it like NSData or something so I can use it in AVAudioPlayer without writing/reading from disk
code let soundPath = "temp" let filepath = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(soundPath, ofType: "wav")!)
var songAsset = AVURLAsset(URL: filepath, options: nil)
var track = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
var source: AnyObject = songAsset.tracksWithMediaType(AVMediaTypeAudio)[0]
var startTime = CMTimeMakeWithSeconds(0, 44100)
var time_insert = CMTimeMakeWithSeconds(atTime, 44100)
var trackDuration = songAsset.duration
var longestTime = CMTimeMake(882000, 44100)
var timeRange = CMTimeRangeMake(startTime, longestTime)
var trackMix = AVMutableAudioMixInputParameters(track: track)
trackMix.setVolume(volume, atTime: startTime)
audioMixParams.insert(trackMix, atIndex: audioMixParams.count)
track.insertTimeRange(timeRange, ofTrack: source as AVAssetTrack, atTime: time_insert, error: nil)
This happens several times in a loop generating a whole track
Finally I use
var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
exporter.audioMix = audioMix
exporter.outputFileType = "com.apple.m4a-audio"
exporter.outputURL = NSURL(fileURLWithPath: fileName)
exporter.exportAsynchronouslyWithCompletionHandler({
switch exporter.status{
case AVAssetExportSessionStatus.Failed:
println("failed \(exporter.error)")
case AVAssetExportSessionStatus.Cancelled:
println("cancelled \(exporter.error)")
default:
println("complete")
callback()
}
})
to export the file.
and after that it calls a callback that loads the sound and loops it in a time.
The fact I don't loop with the normal loop property is that each file might not have the same length as loopDuration
callback: {
self.fillSoundArray()
self.fillSoundArray()
self.fillSoundArray()
}
private func fillSoundArray() {
var currentloop = self.current_loop++
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
var fileName = documentsPath + "/temp.mp4"
var tempAudio = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: fileName), error: nil)
if (self.start_time == 0) {
self.start_time = tempAudio.deviceCurrentTime
}
queue.insert(tempAudio, atIndex: queue.count)
tempAudio.prepareToPlay()
tempAudio.delegate = self
tempAudio.playAtTime(start_time + currentloop*self.loopDuration)
}
Use AVPlayerItem & AVPlayer to make a quick preview of your audio composition