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

AudioKit新手求助:如何连续改变AKMorphingOscillatorBank频率?

解决AudioKit中连续调频的波形表振荡器需求

嘿,作为AudioKit新手,你想做的这个可调谐、带波形变形还能同步其他振荡器的单音波形表振荡器,确实用AKMorphingOscillatorBank会遇到实时调频的问题——毕竟这个类是为多复音音符触发设计的,它的频率绑定MIDI音符号,没法直接在播放过程中连续修改基频。我给你捋两个实用的解决方案:

方案一:改用单音版AKMorphingOscillator(最推荐)

单音的AKMorphingOscillator就是为这种实时参数调整场景设计的,它直接暴露了frequency属性,支持你随时连续修改,同时也保留了波形变形的index参数。

核心代码示例

import AudioKit

class TunableMorphSynth {
    private let audioEngine = AudioEngine()
    private var morphOsc: AKMorphingOscillator!
    private let outputMixer: AKMixer!

    init() {
        // 初始化波形表,你可以替换成自定义的波形数组
        let waveforms = [
            AKTable(.sine),
            AKTable(.triangle),
            AKTable(.sawtooth),
            AKTable(.square)
        ]
        morphOsc = AKMorphingOscillator(waveformArray: waveforms)
        
        // 初始参数设置
        morphOsc.frequency = 440.0 // 默认A4
        morphOsc.amplitude = 0.5
        morphOsc.index = 0.0 // 起始用正弦波
        
        // 路由到输出
        outputMixer = AKMixer(morphOsc)
        audioEngine.output = outputMixer
        
        // 启动音频引擎
        do {
            try audioEngine.start()
        } catch {
            print("音频引擎启动失败: \(error.localizedDescription)")
        }
    }

    // 控制振荡器启停
    func togglePlay() {
        morphOsc.isStarted ? morphOsc.stop() : morphOsc.start()
    }

    // 连续调整基频(直接绑定旋钮/滑块的输入值)
    func updateBaseFrequency(_ newValue: Double) {
        // newValue可以是20~20000Hz范围内的任意数值
        morphOsc.frequency = newValue
    }

    // 调整波形变形程度(0~1之间连续变化,平滑切换波形)
    func updateMorphIndex(_ newValue: Double) {
        morphOsc.index = newValue
    }

    // 和其他振荡器同步频率
    func syncFrequency(with otherOscillator: AKOscillator) {
        otherOscillator.frequency = morphOsc.frequency
    }
}

为什么这个方案更合适?

AKMorphingOscillatorBank是为多复音场景设计的,每次触发MIDI音符时它会创建一个独立的振荡器实例,频率由音符号决定,没法直接修改正在发声的那个振荡器的频率。而单音版本完全由你直接控制参数,完美适配“播放时用旋钮连续调基频”的需求。

方案二:如果非要用AKMorphingOscillatorBank(仅限小范围调频)

如果你有复音需求,必须用Bank类,那可以通过**弯音(Pitch Bend)**来实现小范围的频率调整,但这个方法只能做相对偏移,没法直接设置绝对基频:

// 假设你已经触发了一个MIDI音符(比如69对应A4=440Hz)
// 计算要偏移的半音数:比如从440调到450,半音数是 log2(450/440)*12 ≈ 0.39半音
let targetFrequency = 450.0
let currentFrequency = 440.0
let pitchBendValue = log2(targetFrequency / currentFrequency) * 12

// 应用弯音
morphingOscBank.setPitchBend(pitchBendValue)

注意:弯音的默认范围是±2半音,如果需要更大范围,你需要先设置morphingOscBank.pitchBendRange = 12(比如±12半音),但这种方式始终是基于触发音符的相对偏移,不如单音振荡器直接调绝对频率灵活。

额外提示:波形变形的细节

不管用哪个方案,index参数都是0到1之间的连续值,对应波形数组里的波形平滑过渡。比如index=0.25就是第一个和第二个波形的混合,index=0.75是第三个和第四个波形的混合,完全支持实时旋钮调节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:08:25