Использование нескольких AVAudioSequencer с одним или несколькими AVAudioUnitSampler - PullRequest
0 голосов
/ 24 сентября 2019

Контекст: я пытаюсь воспроизвести несколько MIDI-последовательностей в приложении для iOS, используя AVFoundation.Треки загружаются в MIDI-файлы, и мне удалось успешно воспроизвести их один за другим, если я загрузил их в AVAudioSequencer.У меня также есть объект AVAudioUnitSampler, подключенный к AVAudioEngine, и он успешно воспроизводит выбранный инструмент из загруженного звукового банка в сэмплере.

Настройка работает правильно, если я создаю новый AVAudioSequencerкаждый раз, когда я играю звук.Однако, если я хотел бы повторно использовать секвенсор после его завершения, звучит так, как будто он не использует инструмент сэмплера.

Я подозреваю, что когда я создаю AVAudioSequencer объекты, они автоматически подключаются к AVAudioEngine, нотолько последний объект будет подключен к сэмплеру.

Я пытался вручную подключить destinationAudioUnit треков в секвенсоре к сэмплеру, но тогда он вообще не воспроизводит звук,Я также пытался создать несколько сэмплеров и подключить их все к движку, но это тоже не сработало.

Мой главный вопрос: как правильно использовать несколько AVAudioSequencer объектов содин AVAudioUnitSampler?Или мне нужно создать сэмплер для каждого секвенсора и как-то их соединить?

Вот очень простой пример двух секвенсоров.Когда я запускаю его, секвенсор B успешно воспроизводит звук через сэмплер, но А. не использует инструмент.

import UIKit
import PlaygroundSupport
import AVFoundation

class MyViewController : UIViewController {

    let buttonA = UIButton(type: .system), buttonB = UIButton(type: .system)
    let engine = AVAudioEngine()
    lazy var sequencerA = AVAudioSequencer(audioEngine: engine)
    lazy var sequencerB = AVAudioSequencer(audioEngine: engine)
    let sampler = AVAudioUnitSampler()

    // UI setup
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
        buttonA.setTitle("Sequencer A", for: .normal)
        buttonB.setTitle("Sequencer B", for: .normal)
        buttonA.addTarget(self, action: #selector(playSequencerA), for: .touchUpInside)
        buttonB.addTarget(self, action: #selector(playSequencerB), for: .touchUpInside)
        view.addSubview(buttonA)
        view.addSubview(buttonB)
        buttonA.frame = CGRect(x: 150, y: 200, width: 100, height: 100)
        buttonB.frame = CGRect(x: 150, y: 300, width: 100, height: 100)
        self.view = view
    }

    // Sound engine setup
    override func viewDidLoad() {
        engine.attach(sampler)
        engine.connect(sampler, to: engine.mainMixerNode, format: nil)
        let soundBankPath = playgroundSharedDataDirectory.appendingPathComponent("gs_instruments.dls")
        let midiA = playgroundSharedDataDirectory.appendingPathComponent("sfx_a.mid")
        let midiB = playgroundSharedDataDirectory.appendingPathComponent("sfx_b.mid")
        try! sampler.loadSoundBankInstrument(at: soundBankPath, program: 11, bankMSB: UInt8(kAUSampler_DefaultMelodicBankMSB), bankLSB: UInt8(kAUSampler_DefaultBankLSB))
        try! sequencerA.load(from: midiA, options: [])
        try! sequencerB.load(from: midiB, options: [])
        try! engine.start()
    }

    @objc public func playSequencerA() { play(sequencerA) }

    @objc public func playSequencerB() { play(sequencerB) }

    func play(_ sequencer: AVAudioSequencer) {
        if sequencer.isPlaying { sequencer.stop() }
        sequencer.currentPositionInBeats = 0
        try! sequencer.start()
    }

}

PlaygroundPage.current.liveView = MyViewController()

Редактировать: После некоторых дополнительных экспериментов я подозреваю, что AVAudioEngine не может иметь более одногоAVAudioSequencer экземпляр (или я все еще делаю что-то не так).В качестве обходного пути я создал отдельный объект AVAudioEngine для каждого MIDI-файла, который мне нужно воспроизвести, и у них всех есть свои собственные входы сэмплера и секвенсора, которые прекрасно воспроизводят звуки.Я уверен, что это решение не является оптимальным, поэтому буду рад любым советам по улучшению настроек.

...