【问题标题】:Calling random AKPlayers in AKSequencer with repeated random results在 AKSequencer 中调用随机 AKPlayers 并重复随机结果
【发布时间】:2018-09-13 23:39:14
【问题描述】:

这是我目前正在进行的一个多音频文件播放项目,其中多个 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()
    }
}()

然后,我通过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。

作为一种解决方案,感谢 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 次。我可以用不同的方式解决这个问题吗?非常感激。

【问题讨论】:

    标签: swift audiokit arc4random aksequencer


    【解决方案1】:

    RandomWithRepeats 类的工作是跟踪何时为您提供不同的AKPlayer 实例,但您每次调用playRandom() 时都会创建一个新的RandomWithRepeats 实例,因此它可以'不跟踪任何事情。

    当您创建玩家数组并在您的playRandom() 方法中使用此实例时,创建RandomWithRepeats 的单个实例。

    let rand = RandomWithRepeats(range: 0 ... players.count, repeatRange: 2 ... 3)
    
    func playRandom() {
         try? players[rand.nextValue()].play() 
    }
    

    为了更简洁的解决方案,您可以将RandomWithRepeats 的逻辑与AKPlayer 数组一起封装到一个类中,例如RandomlyRepeatingPlayer 类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多