Эквивалент MusicTrackSetDestNode для AVAudioUnitSampler (AVAudioEngine)?

Следуя этой статье в блоге , я могу подключить MusicTrack в MusicSequence к нужному AUNode в AUGraph.
Поскольку AUGraph устарел, я ищу эквивалент AVAudioEngine. Есть ли способ для MusicTrack воспроизводить ноты MIDI для отдельного и определенного AVAudioUnitSampler?

Ниже приведен мой код.

      func createMusicSequence() -> MusicSequence {
    var musicSequence: MusicSequence?
    var status = NewMusicSequence(&musicSequence)
    if status != noErr {
        print("bad status when creating a musicSequence \(status)")
    }
    // add tracks
    var pianoTrack: MusicTrack?
    status = MusicSequenceNewTrack(musicSequence!, &pianoTrack)
    if status != noErr {
        print("error creating piano track \(status)")
    }
        
    var metronomeTrack: MusicTrack?
    status = MusicSequenceNewTrack(musicSequence!, &metronomeTrack)
    if status != noErr {
        print("error creating metronome track \(status)")
    }
        
    var time = MusicTimeStamp(0.0)
    for i:UInt8 in 60...80 {
        var mess = MIDINoteMessage(channel: 0,
                                   note: i,
                                   velocity: 64,
                                   releaseVelocity: 0,
                                   duration: 1.0)
            
        status = MusicTrackNewMIDINoteEvent(pianoTrack!, time, &mess)
        if status != noErr {
            print("failed to assign note to piano track")
        }
            
        mess = MIDINoteMessage(channel: 0,
                               note: 77,
                               velocity: 64,
                               releaseVelocity: 0,
                               duration: 1.0)
        status = MusicTrackNewMIDINoteEvent(metronomeTrack!, time, &mess)
        if status != noErr {
            print("failed to assign mess to the metronome track")
        }
        time += 1
    }

    // associating the musicSequence with the AUGraph
    MusicSequenceSetAUGraph(musicSequence!, processingGraph!)
        
    // in order for the track to be connected to the desired node, the below needs to be configured after associating the musicSequence with the AUGraph
    MusicSequenceGetIndTrack(musicSequence!, 0, &pianoTrack)
    MusicTrackSetDestNode(pianoTrack!, pianoNode)
    MusicSequenceGetIndTrack(musicSequence!, 1, &metronomeTrack)
    MusicTrackSetDestNode(metronomeTrack!, metronomeNode)
        
    return musicSequence!
}

Изменить. Я нашел решение своей проблемы с помощью AudioKit.

      class PlaySound {
    
    static let shared = PlaySound()
    
    // need to set Background Modes
    var pianoSampler = MIDISampler(name: "piano")
    var sequencer = AppleSequencer()
    var metronomeSampler = MIDISampler(name: "metronome")
    var mixer = Mixer()
    var engine = AudioEngine()
    
    private init() {
        setup()
        setSequence()
    }
    
    func play() {
        sequencer.play()
    }
    
    func setup() {
        mixer.addInput(pianoSampler)
        mixer.addInput(metronomeSampler)
        engine.output = mixer
        
        loadSF2(name: "Nice-Steinway-Lite-v3.0", ext: "sf2", preset: 0, sampler: pianoSampler)
        loadMetronome(name: "Metronom", ext: "sf2", preset: 48, sampler: metronomeSampler)
        do {
            try engine.start()
        } catch {
            print("error starting the engine: \(error)")
        }
    }
    
    func loadSF2(name: String, ext: String, preset: Int, sampler: MIDISampler) {
        guard let url = Bundle.main.url(forResource: name, withExtension: ext) else {
            print("Could not get SoundFont URL")
            return
        }
        do {
            try sampler.loadMelodicSoundFont(url: url, preset: preset)
        } catch {
            print("can not load SoundFont \(name) with error: \(error)")
        }
    }
    
    func loadMetronome(name: String, ext: String, preset: Int, sampler: MIDISampler) {
        do {
            try sampler.loadSoundFont(name, preset: preset, bank: 128, in: .main)
        } catch {
            print("can not load SoundFont \(name) with error: \(error)")
        }
    }
    
    func setSequence() {
        let pianoTrackManager = sequencer.newTrack("piano")
        let metronomeTrackManager = sequencer.newTrack("metronome")
        var time = Duration(beats: 0.0)
        for _ in 0...10 {
            let note = UInt8.random(in: 48...72)
            pianoTrackManager?.add(noteNumber: MIDINoteNumber(note), velocity: 64, position: time, duration: Duration(beats: 0.5))
            metronomeTrackManager?.add(noteNumber: 77, velocity: 64, position: time, duration: Duration(beats: 0.5))
            time += Duration(beats: 1.0)
        }
        sequencer.setTempo(30)
        
        pianoTrackManager?.setMIDIOutput(pianoSampler.midiIn)
        metronomeTrackManager?.setMIDIOutput(metronomeSampler.midiIn)
    }
}

0 ответов

Другие вопросы по тегам