3

AudioKit を使用して、ファイルWAVMIDIファイルをミックスしています。また、結果を別のファイルに保存する必要があります。

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

使用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 の他のオプションを知りません。

4

2 に答える 2