You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在AudioKit的STKAudiokitdemo中能否实时修改合成节拍器的音调频率?

可以实现实时修改合成声音的音调频率

修改方案

当前代码通过Sequencer触发节拍音符,结合Shaker生成STK合成音。要实现实时音调调整,只需扩展数据模型添加音调控制属性,并在节拍触发逻辑中动态关联即可。

1. 扩展数据模型,增加音调控制项

在ShakerMetronomeData里添加控制重拍和普通节拍音调的属性(这里用MIDI音符编号,和现有逻辑兼容;也可以直接用频率值,按需选择):

struct ShakerMetronomeData {
    // 保留原有属性(tempo、isPlaying等)
    @Published var downbeatNoteNumber: MIDINoteNumber = 60 // 重拍对应的音符
    @Published var beatNoteNumber: MIDINoteNumber = 55     // 普通节拍对应的音符
    // 若需直接控制频率,可替换为:
    // @Published var downbeatFrequency: Double = 440.0
    // @Published var beatFrequency: Double = 392.0
}

2. 更新节拍序列生成逻辑

修改updateSequences方法,确保每次数据变化时,使用最新的音调属性生成节拍序列:

func updateSequences() {
    var track = sequencer.tracks.first!
    track.length = Double(data.timeSignatureTop)
    track.clear()
    // 用最新的重拍音符生成重拍事件
    track.sequence.add(noteNumber: data.downbeatNoteNumber, position: 0.0, duration: 0.1)
    let vel = MIDIVelocity(Int(data.beatNoteVelocity))
    for beat in 1 ..< data.timeSignatureTop {
        // 用最新的普通节拍音符生成节拍事件
        track.sequence.add(noteNumber: data.beatNoteNumber, velocity: vel, position: Double(beat), duration: 0.1)
    }

    // 第二条轨道逻辑按需调整(如果不需要可以忽略)
    track = sequencer.tracks[1]
    track.length = Double(data.timeSignatureTop)
    track.clear()
    for beat in 0 ..< data.timeSignatureTop {
        track.sequence.add(noteNumber: MIDINoteNumber(beat), position: Double(beat), duration: 0.1)
    }
}

3. 绑定UI实现实时控制

在Playground的UI部分添加滑块或其他交互控件,绑定到data.downbeatNoteNumber和data.beatNoteNumber。拖动控件时,data的didSet会自动触发updateSequences,实时更新节拍的音调。

特殊情况处理

如果当前用的Shaker是无音调的噪音类STK乐器(比如沙锤),则需要替换为支持音调的合成器(如STK正弦波、方波等),示例代码如下:

// 替换原有的Shaker为STK正弦波合成器
let oscillator = STKSineWave()

// 初始化回调乐器时,动态设置频率
callbackInst = CallbackInstrument { [weak self] note, vel in
    guard let self = self else { return }
    // 将MIDI音符转换为频率,或者直接用自定义的频率值
    let frequency = note.midiNoteToFrequency()
    self.oscillator.frequency = frequency
    self.oscillator.amplitude = Double(vel) / 127.0
    self.oscillator.start()
    // 控制发声时长
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        self.oscillator.stop()
    }
}

// 记得将oscillator连接到mixer和引擎
mixer.addInput(oscillator)
engine.output = mixer

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:28:12