我正在使用 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
}
}
我正在使用SongProcessor
AudioKit 示例中的示例来了解如何使用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 中有任何其他选项可以实现我所需要的。