3

我正在使用 AudioKit 将WAV文件与MIDI文件混合在一起。我还需要将结果保存在单独的文件中。

要混合 WAV 和 MIDI,我使用的AKMIDISamplerAKSequencer这样的:

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
    }
}

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

4

2 回答 2

1

不要使用 AKOfflineRender,而是尝试 AudioKit 4.0.4 中的新 AudioKit.renderToFile: https ://github.com/AudioKit/AudioKit/commit/09aedf7c119a399ab00026ddfb91ae6778570176

于 2017-11-13T19:28:18.953 回答
0

我认为你需要在 iOS11 中使用这个方法

[AudioKit renderToFile:file duration:self->_audioDurationSeconds error:&error prerender:^{ [self.voicePlayer start]; }];

于 2018-09-04T07:37:38.960 回答