• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - AudioKit ios AKSequencer 无法准确重启播放

[复制链接]
菜鸟教程小白 发表于 2022-12-12 14:39:54 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在尝试使用 AudioKit 在小节的每个节拍上播放声音。虽然我已经实现了 this 中的代码关于通过 AudioKit 进行回调的类似问题,我似乎无法让音序器正确更新更改和播放。它会准确播放一次,但是在倒带和更改值后,它将仅使用初始值(或根本不播放)。

我的目的是为每个小节创建一个带有节拍值的小节结构,然后使用 MIDI 和回调根据有多少小节/节拍播放不同的声音。谢谢!

import UIKit
import AudioKit

class ViewController: UIViewController {

let sequencer = AKSequencer()

let click = AKSynthSnare()
let callbackInst = AKCallbackInstrument()

// Create the struct that defines each line
struct Line {
    var name: String
    var measures: Int
    var beatsPerMeasure: Int
    func totalBeats() -> Int {
        return (measures * beatsPerMeasure)
    }
}

// Initialize intro line
var intro = Line(name: "Intro", measures: 0, beatsPerMeasure: 0)

// A function to create/update/playback the sequence on button press
func playBack() {

    let metronomeTrack = sequencer.newTrack()
    metronomeTrack?.setMIDIOutput(click.midiIn)
    let callbackTrack = sequencer.newTrack()
    callbackTrack?.setMIDIOutput(callbackInst.midiIn)

    for steps in 0 ... Int(measuresRowOneValue) {
        // this will trigger the sampler on the four down beats
        metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))

        // set the midiNote number to the current beat number
        callbackTrack?.add(noteNumber: MIDINoteNumber(steps), velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))

        // set the callback
        callbackInst.callback = {status, noteNumber, velocity in
            guard status == .noteOn else { return }
            print("beat number: \(noteNumber + 1)")

        }
    }
}


@IBOutlet weak var rowOneLocationOne: UIImageView!
// Listener for UI display values
var measuresRowOneValue: Int = 0 {
    didSet {
        intro.measures = measuresRowOneValue
    }
}

@IBAction func rowOnePlusButton(_ sender: UIButton) {
    measuresRowOneValue += 1
}

@IBAction func rowOneMinusButton(_ sender: UIButton) {
    measuresRowOneValue -= 1
}

@IBAction func playbackStart(_ sender: UIButton) {
    playBack()
    sequencer.play()
}

@IBAction func playbackStop(_ sender: UIButton) {
    sequencer.stop()
}

@IBAction func playbackRestart(_ sender: UIButton) {
    sequencer.rewind()
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    AudioKit.output = click
    try!AudioKit.start()
}
}



Best Answer-推荐答案


您的代码中有一些令人困惑的事情,所以我不确定这是否是您唯一的问题,但至少,每次您更改序列的长度时,您都需要调用 setLength() 后跟 enableLooping。基本上,默认情况下(即,除非您明确设置长度)序列的长度将是序列中最长轨道的长度。在您的“播放”方法中,您在轨道顶部添加轨道而不删除旧轨道,因此它无法知道您希望序列持续多长时间。

您的“播放”方法正在做两件不同的事情(都不涉及播放)。你可能想打破它。你可以有一个 setup() 来做只需要做一次的事情(创建轨道,设置它们的输出,设置回调)和一个 rewriteSequence() 方法,当你想重写轨道时被调用。通过这种方式,您可以重复使用现有轨道,而不是不断创建新轨道。

var metronomeTrack: AKMusicTrack!
var callbackTrack: AKMusicTrack!

    // call this just once at the start
    func setup() {
        metronomeTrack = sequencer.newTrack()
        metronomeTrack?.setMIDIOutput(click.midiIn)
        callbackTrack = sequencer.newTrack()
        callbackTrack?.setMIDIOutput(callbackInst.midiIn)

        callbackInst.callback = {status, noteNumber, velocity in
            guard status == .noteOn else { return }
            print("beat number: \(noteNumber + 1)")

        }
    }

    // call this each time you want to change the sequence
    func rewriteSequence() {
        metronomeTrack?.clear()
        callbackTrack?.clear()
        for steps in 0 ... Int(measuresRowOneValue) {
            metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
            callbackTrack?.add(noteNumber: MIDINoteNumber(steps), velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
        }

        // This will make sure it loops correctly:
        sequencer.setLength(AKDuration(beats: Double(measuresRowOneValue)))
        sequencer.enableLooping()
    }

我希望这会有所帮助。

关于ios - AudioKit ios AKSequencer 无法准确重启播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50622527/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap