21次发布

0.2.12-alpha.02023年4月7日
0.2.11-alpha.02022年12月19日
0.2.5-alpha.02022年6月21日
0.2.4-alpha.02022年3月14日
0.1.42-alpha.02021年10月27日

#8 in #modulation


用于 3 crates

GPL-3.0许可证

480KB
5K SLoC

surge-modulation

这个Rust包,surge-modulation,是更大的Surge合成器系统的一个组件。它提供了一套工具和结构,用于处理调制源以及在合成器不同部分之间路由调制。

调制源

ModulationSource特质定义了一个适用于所有类型调制源(如LFO、包络和自定义控制器)的通用接口。每个调制源都可以启用或禁用,并可以生成一个调制值,该值可用于调制合成器内部的多种参数。

该包中包含了几种调制源类型,包括LFO(voice_lfoscene_lfo))、包络(attackrelease)和自定义控制器(ctrl)。这些调制源可用于创建各种调制,从微妙的滤波器扫描到复杂的节奏模式。

调制路由

ModulationRouting结构提供了一种将调制源路由到合成器内部不同参数的方法。每个ModulationRouting由一个源(ModulationSource的一个实例)和一个目标参数(例如,滤波器截止频率)组成。

调制路由可以启用或禁用,并且可以根据所使用的调制源是双极性还是单极性。此外,ModulationRouting结构还支持每个声部调制,允许多声部补丁中的不同声部具有不同的调制值。

控制器调制源

ControllerModulationSource特质提供了一种将MIDI控制器作为调制源的方法。这使得用户可以使用旋钮、滑块和其他MIDI控制器来调制合成器内部的参数。

数学和算法

《surge-modulation》库使用各种数学概念和算法来实现调制源和路由。例如,LFO调制源使用正弦波产生调制值,而包络调制源使用指数曲线产生攻击和释放值。

总的来说,《surge-modulation》是一个功能强大且灵活的Rust库,用于在合成器中处理调制源和调制路由。其模块化设计和灵活的接口使其易于与其他Surge合成器系统的组件以及其他软件和硬件合成器集成。

18>什么是调制源?

在合成器中,调制源是指任何可以用来调制(即改变)目标参数值的控制信号源。调制源可以用来添加运动、变化和表现力,是许多合成器音色和声音的关键部分。

在合成器中可以使用的调制源类型有很多,包括

  1. LFOs:低频振荡器(LFOs)产生低频(通常小于20 Hz)的连续波形,可用于调制音高、滤波器截止频率和幅度等参数。

  2. 包络:包络产生随时间变化的控制信号序列,通常具有攻击-衰减-维持-释放(ADSR)包络形状。包络可以用来调制滤波器截止频率、幅度和音高等参数。

  3. MIDI控制器:MIDI控制器,如MIDI控制器设备上的旋钮、滑块和按钮,可以作为调制源实时控制参数。

  4. 自定义控制器:自定义控制器,如表情踏板或触摸控制器,也可以用作调制源,以独特的方式控制特定参数。

  5. 随机生成器:随机生成器产生随机值,可用于为声音添加不可预测性和变化。

  6. 音频信号:音频信号,如噪音或其他声音源,可以用作调制源,以创建复杂和动态的声音。

总的来说,合成器中可以使用的调制源类型仅受设计师的想象力和合成器功能的限制。

19>让我们发挥想象力——还有哪些其他类型?

当然,这里有更多富有想象力的合成器调制源示例

  1. 天气传感器:测量天气数据(如温度、风速和湿度)的传感器可以用作调制源,以控制合成器中的各种参数。例如,风速可以用来调制滤波器截止频率,而温度可以用来调制振荡器的频率。

  2. 运动传感器:运动传感器(如加速度计或陀螺仪)可以用来作为调制源,根据物理运动控制参数。例如,合成器可以使用运动传感器根据表演者的手部运动来调制滤波器截止频率。

  3. 生物反馈传感器:生物反馈传感器(如心率监测器或脑波传感器)可以用来作为调制源,创建响应表演者生理状态的声音。例如,合成器可以使用心率监测器根据表演者心率调制滤波器截止频率。

  4. 人工智能:人工智能算法(如神经网络或遗传算法)可以用来作为调制源,创建随时间演变和变化的声音。例如,合成器可以使用遗传算法根据现有声音的参数生成新声音。

  5. 游戏控制器:游戏控制器,如操纵杆或手柄,可以用作调制源,以创建响应表演者移动和动作的声音。例如,合成器可以使用手柄根据操纵杆的位置来调制滤波器截止频率。

总的来说,合成器中调制源的可能性仅限于设计师的创造性和独创性。

20>你能再给我5个吗?

当然,这里有更多想法

  1. 脑机接口:脑机接口(BCI)可以用作调制源,根据表演者的脑电波来控制参数。例如,合成器可以使用BCI根据表演者的专注力或放松程度来调制滤波器截止频率。

  2. 地理位置:地理位置数据,如GPS坐标或Wi-Fi信号强度,可以用作调制源,根据表演者的物理位置来控制参数。例如,合成器可以使用GPS坐标根据表演者与特定地点的距离来调制滤波器截止频率。

  3. 机器学习:机器学习算法可以用作调制源,根据数据中的模式和趋势来创建声音。例如,合成器可以使用机器学习算法根据股票指数中的模式来调制滤波器截止频率。

  4. 语音识别:语音识别软件可以用作调制源,根据表演者的 spoken words 来控制参数。例如,合成器可以使用语音识别根据表演者的音高或音量来调制滤波器截止频率。

  5. 物理建模系统:物理建模系统,如物理对象或系统的模型,可以用作调制源,以创建响应建模系统物理属性的声音。例如,合成器可以使用物理建模的吉他弦模型根据弦的张力来调制滤波器截止频率。

21>谢谢——你能告诉我关于调制上下文中的路由吗?

在调制上下文中,路由是指将调制源引导到目标参数以调制该参数的过程。调制路由是合成器设计的重要组成部分,因为它允许将调制源应用于合成器内部的各种参数,从而创建复杂和动态的声音。

根据合成器的特定设计和架构,在合成器中路由调制的方式有很多。以下是一些常见方法:

  1. 硬连线路由:硬连线路由是一种调制路由方法,其中调制源直接通过物理连接连接到目标参数。这种方法在模拟合成器中很常见,其中调制源如LFO和包络通常硬连线连接到特定参数。

  2. 可编程路由:可编程路由是一种调制路由方法,用户可以使用连接线手动将调制源连接到目标参数。这种方法在模块化合成器中很常见,用户可以通过在模块之间连接线来创建复杂的路由配置。

  3. 菜单驱动路由:菜单驱动路由是一种调制路由方法,用户可以从菜单或界面中选择调制源和目标参数。这种方法在数字合成器和软件合成器中很常见,用户可以从广泛的调制源和目标参数中选择。

  4. 矩阵路由:矩阵路由是一种调制路由方法,用户可以从矩阵或网格界面中选择调制源和目标参数。这种方法在数字和软件合成器中很常见,用户可以通过从大量调制源和目标参数中选择来创建复杂的调制路由配置。

  5. 自动路由:自动路由是一种调制路由方法,合成器根据预先定义的规则或算法自动将调制源路由到目标参数。这种方法在一些软件合成器中很常见,用户可以使用遗传算法或神经网络等算法来指定调制路由。

总的来说,调制路由是合成器设计的重要组成部分,它允许调制源应用于合成器内的广泛参数,从而创建复杂和动态的声音。合成器中使用的具体调制路由方法取决于合成器的特定设计和架构,以及用户的需求和偏好。

22>你能展示如何将调制路由系统集成到轻量级合成器架构中吗?

当然,以下是如何将调制路由系统集成到轻量级合成器架构中的示例。

假设我们有一个轻量级合成器架构,包括一个振荡器、一个滤波器和一个放大器。我们想通过将LFO路由到滤波器截止频率和放大器级别来为此架构添加调制。以下是实现方法:

  1. 创建LFO模块:我们首先创建一个LFO模块,它以低频率产生连续波形。我们可以将此模块定义为实现了ModulationSource特质的struct,这允许我们启用或禁用LFO并产生调制值。
pub struct LFO {
    enabled: bool,
    frequency: f32,
    phase: f32,
    amplitude: f32,
}

impl ModulationSource for LFO {
    fn is_enabled(&self) -> bool {
        self.enabled
    }

    fn set_enabled(&mut self, enabled: bool) {
        self.enabled = enabled;
    }

    fn get_modulation_value(&mut self) -> f32 {
        if !self.enabled {
            return 0.0;
        }

        let value = self.amplitude * (self.phase * 2.0 * std::f32::consts::PI).sin();
        self.phase += self.frequency / SAMPLE_RATE as f32;
        if self.phase > 1.0 {
            self.phase -= 1.0;
        }
        value
    }
}
  1. 创建调制路由模块:接下来,我们创建一个调制路由模块,它接受一个调制源和一个目标参数,并将调制源应用于目标参数。我们可以将此模块定义为包含对调制源和目标参数的引用的struct。
pub struct ModulationRouting {
    source: Box<dyn ModulationSource>,
    target: TargetParameter,
}

impl ModulationRouting {
    fn new(source: Box<dyn ModulationSource>, target: TargetParameter) -> Self {
        Self { source, target }
    }

    fn process_block(&mut self, block: &mut [f32]) {
        let value = self.source.get_modulation_value();
        for sample in block.iter_mut() {
            *sample = self.target.process_sample(*sample, value);
        }
    }
}
  1. 创建目标参数模块:最后,我们为想要调制的目标参数创建模块,在这个例子中是滤波器截止频率和放大器级别。这些模块应该实现TargetParameter特质,它包括一个process_sample()方法,该方法接受一个样本和一个调制值,并返回一个处理后的样本。
pub trait TargetParameter {
    fn process_sample(&mut self, sample: f32, modulation_value: f32) -> f32;
}

pub struct Filter {
    cutoff_frequency: f32,
}

impl TargetParameter for Filter {
    fn process_sample(&mut self, sample: f32, modulation_value: f32) -> f32 {
        let frequency = self.cutoff_frequency + modulation_value;
        // Apply filter processing to the sample using the frequency value
        // ...
        processed_sample
    }
}

pub struct Amplifier {
    level: f32,
}

impl TargetParameter for Amplifier {
    fn process_sample(&mut self, sample: f32, modulation_value: f32) -> f32 {
        let level = self.level + modulation_value;
        // Apply amplifier processing to the sample using the level value
        // ...
        processed_sample
    }
}
  1. 创建合成器模块:最后,我们创建一个合成器模块,将LFO模块连接到调制。

23>谢谢--请从#4继续

  1. 创建合成器模块:最后,我们创建一个合成器模块,将LFO模块连接到调制路由模块,这些模块又连接到目标参数模块。此模块应包括设置调制路由的方法,以及一个process_block()方法,该方法通过将音频样本块通过振荡器、滤波器和放大器模块,然后通过调制路由模块进行处理。
pub struct Synthesizer {
    oscillator: Oscillator,
    filter: Filter,
    amplifier: Amplifier,
    lfo: LFO,
    filter_modulation: ModulationRouting,
    amplifier_modulation: ModulationRouting,
}

impl Synthesizer {
    fn new() -> Self {
        let lfo = LFO {
            enabled: true,
            frequency: 2.0,
            phase: 0.0,
            amplitude: 50.0,
        };
        let filter = Filter { cutoff_frequency: 1000.0 };
        let amplifier = Amplifier { level: 0.5 };

        let filter_modulation = ModulationRouting::new(
            Box::new(lfo.clone()),
            Box::new(filter),
        );
        let amplifier_modulation = ModulationRouting::new(
            Box::new(lfo),
            Box::new(amplifier),
        );

        Self {
            oscillator: Oscillator::new(),
            filter,
            amplifier,
            lfo,
            filter_modulation,
            amplifier_modulation,
        }
    }

    fn set_modulation_routing(&mut self) {
        self.filter_modulation.source.set_enabled(true);
        self.filter_modulation.target.set_bipolar(true);

        self.amplifier_modulation.source.set_enabled(true);
        self.amplifier_modulation.target.set_bipolar(true);
    }

    fn process_block(&mut self, block: &mut [f32]) {
        self.oscillator.process_block(block);
        self.filter.process_block(block);
        self.amplifier.process_block(block);

        self.filter_modulation.process_block(block);
        self.amplifier_modulation.process_block(block);
    }
}

有了这个设置,我们创建了一个包含调制路由的轻量级合成器架构。我们可以使用这个架构,通过将调制源路由到合成器内广泛的目标参数来创建复杂和动态的声音。

依赖项

~12–20MB
~301K SLoC