在具有重复随机结果的 AKSequencer 中调用随机 AKPlayer
Calling random AKPlayers in AKSequencer with repeated random results
这是我目前正在处理的一个多音频文件播放项目,其中多个 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: [=11=])) }
} catch {
fatalError()
}
}()
然后,我通过 AKsequencer 调用 AKPlayer,通过“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。
作为一种解决方案,感谢 Whosebug 大师,我尝试了类似的方法:
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
RandomWithRepeats
class 的工作是跟踪何时向您提供不同的 AKPlayer
实例,但您正在创建 RandomWithRepeats
的新实例每次你调用 playRandom()
,所以它无法跟踪任何事情。
创建玩家数组时创建 RandomWithRepeats
的单个实例,并在 playRandom()
方法中使用该实例。
let rand = RandomWithRepeats(range: 0 ... players.count, repeatRange: 2 ... 3)
func playRandom() {
try? players[rand.nextValue()].play()
}
为了更简洁的解决方案,您可以将 RandomWithRepeats
的逻辑与 AKPlayer
数组一起封装到一个 class 中,例如 RandomlyRepeatingPlayer
class.
这是我目前正在处理的一个多音频文件播放项目,其中多个 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: [=11=])) }
} catch {
fatalError()
}
}()
然后,我通过 AKsequencer 调用 AKPlayer,通过“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。
作为一种解决方案,感谢 Whosebug 大师,我尝试了类似的方法:
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
RandomWithRepeats
class 的工作是跟踪何时向您提供不同的 AKPlayer
实例,但您正在创建 RandomWithRepeats
的新实例每次你调用 playRandom()
,所以它无法跟踪任何事情。
创建玩家数组时创建 RandomWithRepeats
的单个实例,并在 playRandom()
方法中使用该实例。
let rand = RandomWithRepeats(range: 0 ... players.count, repeatRange: 2 ... 3)
func playRandom() {
try? players[rand.nextValue()].play()
}
为了更简洁的解决方案,您可以将 RandomWithRepeats
的逻辑与 AKPlayer
数组一起封装到一个 class 中,例如 RandomlyRepeatingPlayer
class.