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

AudioKit v5:如何修改DunneAudioKit Synth的波形?

解决AudioKit Synth波形修改与扩展功能问题

为什么你的代码没生效

AudioKit的Synth类默认使用内置的合成器语音(AKSynthVoice),直接调用au.setWavetable无法覆盖默认语音的波形设置。要自定义波形,必须替换Synth的默认语音为你自己实现的SynthVoice子类——每个复音音符对应一个Voice实例,波形、调制等逻辑都要在Voice里定义。

步骤1:自定义SynthVoice实现波形控制

创建继承自AKPolyphonicSynthVoice的自定义语音类,在里面定义波形表、振荡器组合,以及子振荡器、FM、噪声模块:

import AudioKit

class CustomSynthVoice: AKPolyphonicSynthVoice {
    // 主振荡器
    var oscillator: AKWavetableOscillator
    // 子振荡器(可选)
    var subOscillator: AKOscillator?
    // FM调制器
    var fmOscillator: AKOscillator?
    var fmAmount: AKParameter = 0.0
    // 噪声发生器
    var noiseGenerator: AKWhiteNoise?
    // 包络与滤波
    var envelope: AKAmplitudeEnvelope
    var filter: AKLowPassFilter

    override init() {
        // 组合多种波形:正弦+方波各50%比例混合
        let sineTable = Table(.sine)
        let squareTable = Table(.square)
        let mixedTable = Table([sineTable, squareTable], weights: [0.5, 0.5])
        
        oscillator = AKWavetableOscillator(wavetable: mixedTable)
        envelope = AKAmplitudeEnvelope(oscillator)
        
        // 初始化子振荡器(低八度,方波)
        subOscillator = AKOscillator(waveform: AKTable(.square))
        subOscillator?.amplitude = 0.3
        
        // 初始化FM调制器
        fmOscillator = AKOscillator(waveform: AKTable(.sine))
        fmAmount = 50.0
        
        // 初始化噪声发生器
        noiseGenerator = AKWhiteNoise(amplitude: 0.1)
        
        // 构建信号链:主振荡器+子振荡器+噪声 → 包络 → 滤波
        let mixer = AKMixer(envelope, subOscillator!, noiseGenerator!)
        filter = AKLowPassFilter(mixer)
        
        super.init()
        self.connect(input: filter)
    }

    // 触发音符时的参数配置
    override func start(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, frequency: Double, amplitude: Double) {
        oscillator.frequency = frequency
        oscillator.amplitude = Double(velocity) / 127.0
        
        // 子振荡器设为低八度
        subOscillator?.frequency = frequency / 2
        subOscillator?.start()
        
        // FM调制:调制器频率为主音2倍,调制量控制谐波丰富度
        fmOscillator?.frequency = frequency * 2
        fmOscillator?.amplitude = fmAmount
        fmOscillator?.start()
        oscillator.modulationSource = fmOscillator
        
        noiseGenerator?.start()
        envelope.start()
        oscillator.start()
    }

    // 释放音符时的收尾处理
    override func stop(velocity: MIDIVelocity) {
        envelope.stop()
        oscillator.stop()
        subOscillator?.stop()
        fmOscillator?.stop()
        noiseGenerator?.stop()
        // 延迟移除Voice,确保包络播放完毕
        DispatchQueue.main.asyncAfter(deadline: .now() + envelope.releaseDuration) {
            self.stop()
        }
    }

    // 复音Voice必备实现方法
    override func renderSilence() -> Bool {
        return envelope.isStopped
    }

    override func reset() {
        oscillator.reset()
        envelope.reset()
        subOscillator?.reset()
        fmOscillator?.reset()
        noiseGenerator?.reset()
    }
}

步骤2:将自定义Voice关联到Synth实例

替换Synth的默认语音,使用自定义的CustomSynthVoice,这样调用play(noteNumber:velocity:)时就会应用你的波形和模块:

import AudioKit

class SynthManager {
    let audioEngine = AudioEngine()
    var audioSynth: Synth!

    init() {
        // 初始化Synth并指定自定义Voice类型
        audioSynth = Synth(voice: CustomSynthVoice.self)
        
        // 设置包络参数(和你之前修改的attack/decay一致)
        audioSynth.attackDuration = 0.1
        audioSynth.decayDuration = 0.2
        audioSynth.sustainLevel = 0.7
        audioSynth.releaseDuration = 0.5
        
        // 连接输出并启动音频引擎
        audioEngine.output = audioSynth
        try? audioEngine.start()
    }

    // 播放音符方法
    func playNote(_ noteNumber: MIDINoteNumber, velocity: MIDIVelocity = 100) {
        audioSynth.play(noteNumber: noteNumber, velocity: velocity)
    }

    // 停止音符方法
    func stopNote(_ noteNumber: MIDINoteNumber) {
        audioSynth.stop(noteNumber: noteNumber)
    }
}

关键说明

  • 波形组合:通过Table的多波形初始化方法,调整weights参数可改变正弦、方波、锯齿波的混合比例。
  • 子振荡器:独立添加振荡器并设置为低八度或其他倍数,控制振幅调整混合占比。
  • FM调制:将FM振荡器输出连接到主振荡器的modulationSource,调整fmAmount可改变调制深度,生成更丰富的谐波。
  • 噪声发生器:混合白/粉噪声模块,增加音色质感(比如模拟复古合成器底噪)。
  • 复音支持:Synth本身是复音架构,会自动为每个触发音符创建CustomSynthVoice实例,无需手动管理多个振荡器——每个复音对应一个Voice,Voice内部可包含多个振荡器模块。

调试提示

  • 若波形无变化,检查自定义Voice的信号链连接是否正确,确保connect(input:)指向最终混合信号。
  • 调整振荡器振幅、包络参数,避免信号被过度衰减导致听不见。
  • 可单独测试每个模块(先启用主振荡器,再逐步添加子振荡器、FM、噪声),定位问题。

内容的提问来源于stack exchange,提问作者Evan Aaron Escobar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:26:13