Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saved file using AudioKit AKOfflineRenderNode not right

Tags:

ios

audiokit

I am using AudioKit to mix WAV files together with MIDI files. I also need to save the result in a separate file.

To mix the WAVs and MIDIs I am using an AKMIDISampler with an AKSequencer like this:

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

I am using the SongProcessor example from AudioKit's examples for ideas on how to use AKOfflineRenderNode.

The thing is the example works with AKAudioPlayer instances and not sequencers as I am using. I believe I cannot use players because I need to mix the WAV and MIDI files, and I was only able to achieve that using sequencers.

My first question is: Is it possible to create files from sequencers the same way it is done in SongProcessor with players?

I was able to save an m4a file but the result is weird. First, if I don't set the rate manually to a number like 40, it is veeery slow to play all the notes. And when I set ti to a value like that,I can hear the sequence playing but at wrong rates. At some moments the beats play correctly but they often start playing too slow or too fast at different times.

Is there something I am doing wrong? Is this a bug with AKOfflineRenderNode or is it just not mean to be used like this?

Here is the code I use to save the mix to disk:

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

Any help is very much appreciated. I can't seem to be able to get this to work, and sadly I don't know of any other options in iOS to achieve what I need.

like image 268
Martín Zúñiga Avatar asked Jul 09 '26 22:07

Martín Zúñiga


1 Answers

Instead of using AKOfflineRender, try the new AudioKit.renderToFile in AudioKit 4.0.4: https://github.com/AudioKit/AudioKit/commit/09aedf7c119a399ab00026ddfb91ae6778570176

like image 169
Aurelius Prochazka Avatar answered Jul 11 '26 19:07

Aurelius Prochazka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!