我正在使用AudioKit将WAV
文件与MIDI
文件混合在一起。我还需要将结果保存在单独的文件中。
混合WAV和MIDI我使用AKMIDISampler
和AKSequencer
像这样:
func add(track: MixerTrack) -> Bool {
do{
let trackSampler = AKMIDISampler()
try trackSampler.loadWav(track.instrument.fileName)
trackSampler.connect(to: mixer)
let sequencer = AKSequencer(filename: track.midi.fileName)
sequencer.setTempo(Double(tempo))
sequencer.setRate(rate)
sequencer.setGlobalMIDIOutput(trackSampler.midiIn)
sequencer.enableLooping()
sequencer.enableLooping()
sequencers.append(sequencer)
tracks.append(track)
return true
} catch {
return false
}
}
我正在使用来自AudioKit示例的SongProcessor
示例来了解如何使用AKOfflineRenderNode
的想法。
事情是这个例子适用于AKAudioPlayer
实例而不是我正在使用的序列发生器。我相信我不能使用播放器,因为我需要混合WAV和MIDI文件,而我只能使用音序器来实现。
我的第一个问题是:是否可以像在SongProcessor中使用播放器一样从顺控程序创建文件?
我能够保存一个m4a
文件,但结果很奇怪。首先,如果我没有手动将速率设置为40这样的数字,那么播放所有音符的速度都很慢。当我将ti设置为这样的值时,我可以听到序列播放但速度错误。在某些时刻,节拍正常播放,但它们通常在不同时间开始播放太慢或太快。
有什么我做错了吗?这是AKOfflineRenderNode的错误还是不是故意这样使用?
这是我用来将混音保存到磁盘的代码:
func saveMixToDisk() -> URL? {
do {
let fileManager = FileManager.default
let name = UUID().uuidString.appending(".m4a")
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let fileURL = documentDirectory.appendingPathComponent(name)
offlineRender.internalRenderEnabled = false
let duration = sequencers.first!.length.seconds
for sequencer in sequencers {
sequencer.stop()
sequencer.setTime(AKDuration(seconds: 0).musicTimeStamp)
sequencer.rewind()
}
for sequencer in sequencers {
sequencer.setRate(40) // I would like to find a way to avoid having to set this, since this value is hardcoded and I don't know how to find the correct one. (When I only play through the sequencer inside the app the rate is perfect, but it gets messed up when rendering to URL)
sequencer.play()
}
try offlineRender.renderToURL(fileURL, seconds: duration * 10)
for sequencer in sequencers {
sequencer.stop()
sequencer.setTime(AKDuration(seconds: 0).musicTimeStamp)
sequencer.rewind()
}
offlineRender.internalRenderEnabled = true
return fileURL
} catch let error {
print(error)
return nil
}
}
很感谢任何形式的帮助。我似乎无法让它工作,遗憾的是我不知道iOS中的任何其他选项来实现我的需要。
而不是使用AKOfflineRender,在AudioKit 4.0.4中尝试新的AudioKit.renderToFile:https://github.com/AudioKit/AudioKit/commit/09aedf7c119a399ab00026ddfb91ae6778570176
我想你需要在iOS11中使用这个方法
[AudioKit renderToFile:file duration:self - > _ audioDurationSeconds error:&error prerender:^ {[self.voicePlayer start]; }];