Вызов случайных AKPlayers в AKSequencer с повторяющимися случайными результатами
Это проект воспроизведения нескольких аудиофайлов, над которым я сейчас работаю, где несколько AKPlayer воспроизводятся в произвольном порядке через AKSequencer.
Во-первых, у меня есть массив имен файлов:
Let filenames = [“1.mp3”, “2.mp3, “3.mp3”, … “10.mp3”]
Он загружается на AKPlayer индивидуально, чтобы затем вызывать его в случайном порядке:
Let players: [AKPlayer] = {
Do {
Let filenames = [“1.mp3”, “2.mp3, “3.mp3”, … “10.mp3”]
Return try filenames.map { AKPlayer(audioFile: try AKAudioFile(readRileName: $0)) }
} catch {
fatalError()
}
}()
Затем я вызвал AKPlayer через AKsequencer, вызвав его через 'playRandom
функция:
Let sequencer = AKSequencer()
Let callbackInst = AKCallbackInstrument()
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()
}
}
Наконец, я установил AKPlayer как AudioKit.output и запустил секвенсор. Пока это было успешно! Секвенсор играет AKPlayer без проблем, в случайном порядке.
Но я хотел попробовать разные виды случайности: повторять случайно выбранного игрока 2 или 3 раза. (например, 2, 2, 3, 3, 3, 1, 1, 5, 5, 5, 9, 9, …) Прямо сейчасplayRandom
'просто выбирает разные AKPlayer при каждом повторении.
В качестве одного решения, благодаря мастерам StackOverFlow, я попробовал что-то вроде:
class RandomWithRepeats {
var range: ClosedRange<Int>
var repeatRange: ClosedRange<Int>
var repeatCount = 0
var value = 0
init(range: ClosedRange<Int>, repeatRange: ClosedRange<Int>) {
self.range = range
self.repeatRange = repeatRange
}
// generate a random number in a range
// Just use Int.random(in:) with Swift 4.2 and later
func random(in range: ClosedRange<Int>) -> Int {
return Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound + 1))) + range.lowerBound
}
func nextValue() -> Int {
// if repeatCount is 0, its time to generate a new value and
// a new repeatCount
if repeatCount == 0 {
// For Swift 4.2, just use Int.random(in:) instead
value = self.random(in: range)
repeatCount = self.random(in: repeatRange)
}
repeatCount -= 1
return value
}
}
А потом я модифицировал playRandom
функция как:
func playRandom() {
Let rand = randomWithRepeats(range: 1…players.count, repeatRange: 2…3)
Do { players[rand.nextValue()].play() }
}
Оказывается, это точно такой же результат, потому что сама функция playRandom запускает (AKSequencer) каждый повтор, поэтому она фактически не "повторяет" случайный AKPlayer 2 или 3 раза. Могу ли я решить эту проблему по-другому? Очень признателен. <3
1 ответ
Работа RandomWithRepeats
класс, чтобы отслеживать, когда доставить вам другой AKPlayer
экземпляр, но вы создаете новый экземпляр RandomWithRepeats
каждый раз, когда вы звоните playRandom()
поэтому он не может ничего отслеживать.
Создать один экземпляр RandomWithRepeats
когда вы создаете массив игроков и используете этот экземпляр в вашем playRandom()
метод.
let rand = RandomWithRepeats(range: 0 ... players.count, repeatRange: 2 ... 3)
func playRandom() {
try? players[rand.nextValue()].play()
}
Для более чистого решения вы можете заключить в себе логику RandomWithRepeats
вместе с AKPlayer
массив в один класс, такой как RandomlyRepeatingPlayer
учебный класс.