Перезагрузка AKAudioFile в AKSequencer с использованием AKCallbackInstrument.noteOff? - PullRequest
0 голосов
/ 27 августа 2018

Сначала я вызвал AKMIDISampler для воспроизведения аудиофайла, а затем назначил его AKSequencer.Миди-файл, который я использовал, - это всего лишь 2 такта, нота C3, миди-файл с одной дорожкой, ровно столько же, сколько аудиофайл, который я хотел воспроизвести.Но, вызывая AKAudioFile, я хотел выбрать mp3-файл случайным образом.Я временно сделал 1.mp3, 2.mp3 и 3.mp3, как показано ниже.

    let track = AKMIDISampler()
    let sequencer = AKSequencer(filename: "midi")

    try? track.loadAudioFile(AKAudioFile(readFileName: String(arc4random_uniform(3)+1) + ".mp3"))

    sequencer.tracks[0].setMIDIOutput(track.midiIn)
    // Tempo track I had to made to remove sine wave
    sequencer.tracks[1].setMIDIOutput(track.midiIn)

И сделал некоторые настройки секвенсора,

    sequencer.setTempo(128.0)
    sequencer.setLength(AKDuration(beats: 8))

    sequencer.setLoopInfo(AKDuration(beats: 8), numberOfLoops: 4)
    sequencer.preroll()

и назначил AKMIDISampler для AudioKit.output, затемdid sequencer.play ().

Воспроизведение секвенсора прошло успешно!Он случайно загружал три файла mp3 и воспроизводил 8 ударов (2 такта), зацикливаясь ровно 4 раза.

Но моя цель - загружать случайные файлы MP3 каждый раз, когда цикл повторяется.Кажется, что секвенсор воспроизводит только первый назначенный mp3-файл при цикле.Я изо всех сил пытаюсь найти решение этой проблемы.

Возможно, я мог бы использовать "AKCallbackInstrument"?Так как в этом случае я проигрываю аудиофайл через ноту midi, я могу сбросить «loadAudioFile» всякий раз, когда нота midi выключена?Таким образом, я мог бы зациклить секвенсор и воспроизводить случайным образом аудиофайл в каждом цикле.Это всего лишь идея, но мне сейчас сложно написать это правильно.Я надеюсь, что я на правильном пути.Было бы здорово, если бы я мог получить здесь совет.<3 </p>

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Это было очень полезно, c_booth!Благодаря вам, я добился огромного прогресса сегодня.Вот что я написал на основе ваших советов.Сначала я сделал массив AKPlayers, включающий 6 mp3-файлов.Они назначены на AKMixer, а затем я вызвал секвенсор и инструмент обратного вызова.Я сделал трек и заметку на секвенсоре, который вызывает функцию playRandom для каждой ноты:

let players: [AKPlayer] = {
    do {
        let filenames = ["a1.mp3", "a2.mp3", "a3.mp3", "b1.mp3", "b2.mp3", "b3.mp3"]
        return try filenames.map { AKPlayer(audioFile: try AKAudioFile(readFileName: $0)) }
    } catch {
        fatalError()
    }
}()

func playRandom() {
    let playerIndex = Int(arc4random_uniform(UInt32(players.count)))
    players[playerIndex].play()
}

func addTracks() {
    let track = sequencer.newTrack()!
    track.add(noteNumber: 48, velocity: 127, position: AKDuration(beats: 0), duration: AKDuration(beats: 16), channel: 0)
    track.setMIDIOutput(callbackInst.midiIn)
    callbackInst.callback = { status, note, vel in
        guard status == .noteOn else { return }
        self.playRandom()
    }
}

func sequencerSettings() {
    sequencer.setTempo(128.0)
    sequencer.setLength(AKDuration(beats: 16))
    sequencer.setLoopInfo(AKDuration(beats: 16), numberOfLoops: 4)
    sequencer.preroll()
}

func makeConnections() {
    players.forEach { $0 >>> mixer }
}

func startAudioEngine() {
    AudioKit.output = mixer
    do {
        try AudioKit.start()
    } catch {
        print(error)
        fatalError()
    }
}

func startSequencer() {
    sequencer.play()
}

Это сработало отлично.Он случайным образом выбирает один из 6 файлов mp3 (все они имеют одинаковую длину, 128 ударов в минуту и ​​16 ударов).Здесь мне показалось странным то, что при первом воспроизведении одновременно воспроизводятся два аудиофайла.Работает нормально после второго цикла.Я изменил параметр numberOfLoop, enableLooping () и т. Д., Но все тот же - воспроизводит два файла при первом воспроизведении.Трек-счет все еще равен 1, и я, как вы могли видеть, позвонил только одному AKPlayer.Могу ли я что-нибудь с этим сделать?

Кроме того, в конечном итоге, я бы хотел назвать сотни mp3-файлов в массиве, поскольку то, что я пытаюсь сделать, - это своего рода приложение для диджеинга (что-то вродеПредустановка Ableton Live).Считаете ли вы хорошей идеей использовать AKPlayer, предполагая, что этот код будет загружать mp3-файлы из облака и передавать его пользователю?Очень признателен.<3 </p>

0 голосов
/ 27 августа 2018

Вы определенно на правильном пути - вы можете легко получить случайные аудиофайлы для зацикливания с фиксированным интервалом с помощью AKSequencer + AKCallbackInstrument.Но я бы не стал беспокоиться о попытке перезагрузить сообщение NoteOff.

Сначала я бы загрузил каждый mp3 в отдельный проигрыватель (например, AKAppleSampler) в массиве (например, вы могли бы назвать его players).и создайте метод, который будет запускать одного из этих игроков случайным образом:

func playRandom() {
    let playerIndex = Int(arc4random_uniform(UInt32(players.count)))
    try? players[playerIndex].play()
}

Когда вы создаете свой секвенсор, добавьте трек и назначьте его для AKCallbackInstrument.Функция обратного вызова для этого AKCallbackInstrument вызовет playRandom, когда получит сообщение noteOn.

seq = AKSequencer()
track = seq.newTrack()!
callbackInst = AKCallbackInstrument()
track.setMIDIOutput(callbackInst.midiIn)
callbackInst.callback = { status, note, vel in 
    guard status == .noteOn else { return }
    self.playRandom()
}

Нет необходимости загружать секвенсор с файлом MIDI.Вы можете просто добавить инициирующее MIDI-событие непосредственно на дорожку.

track.add(noteNumber: 48, // i.e., C3
      velocity: 127,
      position: AKDuration(beats: 0), // noteOn message here
      duration: AKDuration(beats: 8), // noteOff 8 beats later
      channel: 0)

Возможно, ваша проблема с синусоидальной волной вызвана дополнительной дорожкой (возможно, дорожкой темпа) в созданном вами MIDI-файле, который не имеетне был назначен выход.Вы можете полностью избежать этой проблемы, напрямую добавляя события MIDI.

В принципе, вы можете использовать обратный вызов для проверки событий noteOff и запуска кода из noteOff, но я не рекомендовал бы это в вашем случае.Нет веских причин повторно использовать один плеер для нескольких аудиофайлов.При загрузке файла вы, скорее всего, создадите ошибку.Что произойдет, если ваш файл не закончил воспроизведение, и вы пытаетесь загрузить другой?Ресурсы, необходимые для хранения нескольких плееров в памяти, довольно тривиальны - если вы собираетесь воспроизводить один и тот же файл более одного раза, его будет проще и безопаснее загрузить один раз и сохранить плеер в памяти.

...