前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数字复古声:用 Wolfram 语言和 System Modeler 为模拟合成器建模

数字复古声:用 Wolfram 语言和 System Modeler 为模拟合成器建模

作者头像
WolframChina
发布2020-10-30 11:09:57
1.8K0
发布2020-10-30 11:09:57
举报
文章被收录于专栏:WOLFRAMWOLFRAM

你有没有想过做自己的乐器?做一个乐器的数学模型听起来怎么样?无论你是否在寻找一个划算的替代品,或者是一位简单派但想要最好的声音,或者是一位对声音设计好奇的Wolfram语言爱好者,你可以使用Wolfram System Modeler搭建一个虚拟版本的模块化合成器。

为了给你快速展示这项科技可以用来做什么,可以看下面这个完全用模拟模型创建的科技式音乐样本片段:

请点击博文原地址播放音频或点击本文左下角的“阅读原文”(

https://blog.wolfram.com/2020/07/23/digital-vintage-sound-modeling-analog-synthesizers-with-the-wolfram-language-and-system-modeler/)

我使用模块化合成器设计声音,偶尔也做歌,而且我发现System Modeler很适合用于创建虚拟合成器,因为它让你可以轻易模拟和分析复古设备中的电子回路。

模块化合成器如何工作

我的模块化合成器是用不同部分合成起来的:有一些完全是我自己设计的,其他是商业模型。这样的合成器如何工作?每个模块都有一个基本函数。比如,它可以是一个振荡器、滤波器、包络发生器、放大器、混合器等等。通过连接这些核心组件,就可以模拟存在的声音或创建新的声音。你可以看到 System Modeler 有相似点,我们可以通过虚拟电线把组件连接的方法创建复杂的系统。

为何选择虚拟

模块化合成器的体积通常都很大。所以很难用安全的方法运输它们。我有一个小一点的可以在旅行的时候携带,但是通常还是会占据手提行李很大的容量。

商业模块的成本低至60,贵的要1,000以上,而一个小的合成器就需要十几个模块。这个成本可以迅速上升,对于爱好者们而言很快就会变得难以承受。如果你会使用烙铁的话,也许可以手工制作很多模块。实际上,有很大一群像我这样的爱好者喜欢使用和制作这样的系统。

我的模块化合成器,在过去几年间我一直在一个组件一个组件地制作这个合成器。

然而有另一种方法可以使用模块化合成器但是成本更低:虚拟模块化合成器。VCV Rack(https://vcvrack.com/)是复制模块化合成器体验的最常用的开源应用之一。该应用提供了上千个不同的模块。

在过去的两年中,我一直在为VCV Rack发布虚拟模块(https://library.vcvrack.com/?query=vult&brand=&tag=&license=)。我发布的模块有一个很强大的特点是我很努力地在软件中模拟声音的氛围。这个模拟模块是“不完美的”,但这反而是件好事。比如,一个数字正弦波振荡器可以产生一个近似完美的信号。这个完美的信号会被感知到是无聊、没有生机、冷冰冰的。但是,一个并不完美但努力想达到完美信号的模拟振荡器可以产生出让人们感觉丰富和温暖的声音。

我接下来会解释我用来生成模拟电路的一些科技,我可以利用这些科技来创建模拟声音的电子模块。

基础合成器模块

由合成器产生的声音可以是全新的声音或模拟先存的声音。用模拟合成器创造声音最常见的技术叫做减法合成(https://en.wikipedia.org/wiki/Subtractive_synthesis),由一个丰富的声音开始,并对声音进行修剪(从其中减去谐波)以得到理想特点的声音。你可以把这个过程想象成是有一块原石,你通过雕刻的方法去掉一些部分从而得到你想要的雕像。在减法合成中,主要的模块有:

  • 声音来源,比如可以产生在听觉频率范围内的声波的任意种类的振荡器
  • 声音处理器,比如滤波器或其他效果
  • 控制源,可以是低频振荡器、包络发生器等
  • 实用工具,如放大器、衰减器等

我们从一些基本的模块开始:一个振荡器和两个滤波器。为了指导我复制创造模拟声音的过程,我从我的模块库中选择了这些自制模块(https://youtu.be/Y853TDnG1Bg)作为参考:

一个简单的振荡器和两个滤波器。Wolfram Mathcore团队为2019年Wolfram科技大会做了这些面板当做纪念品,当时的大会也展示了一些本博文中说到的一些内容。

为基础模拟组件建模

想要为这些模块建模,我们需要对如何为电路建模有一些了解。我们从最基本的组件:电阻器和电容器开始。

最常用的电子组件可以用简单的方程来描述。(通过打开Text View文本查看)可以看到 System Modeler 内置的电阻器的代码(https://reference.wolfram.com/system-modeler/libraries/Modelica/Modelica.Electrical.Analog.Basic.Resistor.html),可以看到所有相关的方程式。有一个方程式复合欧姆定律 (https://demonstrations.wolfram.com/OhmsLaw/),其他的用于计算耗损功率和电阻温度的效应。终端的方程式在模型 OnePort(https://reference.wolfram.com/system-modeler/libraries/Modelica/Modelica.Electrical.Analog.Interfaces.OnePort.html)里面描述。通过修改这个代码,我们可以为 System Modeler 创建我们自己自定义的电子组件:

按照之前展示的电阻模型,我们可以创建一个简易版本的模型,模拟我们感兴趣的效应,但移除我们不会用到的效应。(你可以在 AnalogModeling(https://blog.wolfram.com/data/uploads/2020/07/AnalogModelingLibrary.zip)资源库中找到所有的模型。)在我们的合成模型中,我们假设所有组件都在恒定室温下。我们会移除所有能量损失的计算,因为声音并不受其影响。在下面的列表中,你可以看到我们创建的简版电阻模型:

电容器的模型很类似。主要的变化是定义了电压和电流之间关系的方程式。在电容器中,这是一个微分方程。下一步你可以看到我们会用到的简版电容器模型:

感应器在我建模的音频电路中并不常见。正因为此,我不会现在创建一个电感器,但其实从电容器的模型中可以很容易得到这个模型。

另一方面,由于电位计是我们用来控制合成器参数的主要组成部分,它们非常常见。想要模拟电位计的话,我会首先创建一个变量电阻。一旦有一个变量电阻,我就可以结合它们创建一个三角插头的电位计。

为了控制电位计的位置,我们会需要向模型中添加一个输入信号 u。这个信号范围从0到1,也分别与完整的顺时针和逆时针移动的范围相匹配:

使用两个变量电阻,我们可以通过下图所示的连接方法创建一个电位计:

难点在于用单个输入控制两个变量电阻。可以通过添加两个方程,在减少一个电阻值的同时增加另一个电阻值来达到这一目的:

如下图所示,这些方程式影响了电阻的值。x 轴的范围为从0到1:

既然我们有了基本组件,我们可以开始模拟我们的第一个电路了。

为RC滤波器建模

使用之前创建的电位计和电容器,我们可以如下图所示轻易模拟一个RC(电阻-电容)滤波器:

注意添加的输入u和p是用来分别提供输入和控制信号的。输出v提供了电容器中测量到的电压。我们将RC滤波器包装进一个System Modeler组件,这样就可以在不同模型中重复使用了。

为了测试RC滤波器模型,我们使用了一些从 System Modeler 资源库获取的组件用于提供刺激信号:

我们使用了110 Hz的脉冲信号作为音频输入。一道频率为1 Hz的声表面波提供了一个设定电位计的信号。滤波器的输出随机传到将信号记录为一个WAV文件的组件,该文件可被回放。

我们现在模拟4秒我们的测试模型:

下表显示了当我们模拟电位计位置变化时输入信号的振幅(蓝色表示)和过滤后的输出(橙色表示):

我们从图标中可以看到,当截断频率减小时,滤波输出是如何衰减的。一开始,滤波器是完全打开的,意思是截断频率高于人类可以听到的 22 kHz。当电位计移动,截断频率下降,滤波器衰减信号中更多的高频谐波。

要理解这个效应,一个更简单的方法是可以听我们的测试模型产生的声音。我们可以导入生成的音频文件并回放。如果你听这个声音,你会听到当RC滤波器移除高频谐波时声音是如何变化的。这个声音类似弦乐乐器演奏时的声音:

看一下Spectrogram(http://reference.wolfram.com/language/ref/Spectrogram.html),高频谐波(图形的顶端)在衰减,而低频谐波(图形的底部)基本保持不变:

这时,我们有一个RC滤波器的模型,允许我们去做很多分析,并提供给我们关于每个组件的电压和电流的非常详细的信息。如果我们将这个模型(以现在的样子)转换为一个音频插件,它当然可以工作,但会占用不必要的 CPU 容量。这是因为我们的模型有很多方程式在计算电路的所有细节。但是,当我们做音乐的时候,我们并不是很关心电路的内部结构,滤波器更像一个黑匣子。为了让模型更有效,我们可以使用 Wolfram 语言的符号能力尽量减少我们的方程组。我们的目标是获取电路的常微分方程表达式。

我们的简版RC滤波器有27个方程式。我们可以看到它们都是用了SystemModel(http://reference.wolfram.com/language/ref/SystemModel.html)命令:

SytemModel命令可以在我们指定简化水平时帮助我们减少方程式的数量:

我们可以看到方程式的数量减少到4个了。这是通过简化所有的平凡方程式如x=0和x=y来达到的。在这个例子中,由于我们不能计算电路中所有的电压和电流了,所以我们不需要很多关于模型的信息。得到的方程组可以进一步用命令Eliminate(http://reference.wolfram.com/language/ref/Eliminate.html)进行简化。当消除最后一个变量时,我们还可以将一些变量名称替换为短符号,这样还可以提高方程式的可读性。这种简化过程最后得到一个单个微分方程,其中名称dvc代表vc(电容器的电压)的导数,然后vin是input voltage(输入电压):

我们可以用得到的方程组和命令 Solve(http://reference.wolfram.com/language/ref/Solve.html)放进一个传统的常微分方程形式中:

从这个微分方程中,很容易得到滤波器的转换函数:

为了确认该滤波器的行为,我们可以为位于三个不同位置的电位计创建一个转换函数的波特图。在这个图中,我们可以看到根据输入音频信号频率内容的不同,其衰减会是什么样的:

这个方程式是一个简单的微分方程,可以用任何编程语言运行。稍后我会讨论如何实现它,并分析其中可能会产生的难点。

现在我们先来模拟一个更复杂的滤波器。

为Sallen-Key滤波器建模

Sallen-Key 拓扑结构(https://en.wikipedia.org/wiki/Sallen%E2%80%93Key_topology)允许构建不同种类的滤波器,比如低通、高通、带通等等。我现在会着重低通的结构。之前模拟的简版RC滤波器只有一个极点,但Sallen-Key滤波器有两个奇点,所以在移除频率上效率翻倍:

上图展示了需要一个运算放大器(OPAMP)来构建这个模型。在这种情况下,这个OPAMP连接到了群集配置,使得其可以轻易创建一个基础模型。在群集模式下,OPAMP的输出电压就是输入电压,但输入电流基本为零。这个设置称为缓冲器。

可以用Modelica资源库中的组件在System Modeler中制作一个简单的缓冲器模型。注意这个模型非常简单,并不需要考虑一个真实OPAMP可能会有的非线性行为——比如,输出电压饱和的情况。为了得到更类似的声音,我还会需要模拟饱和和其他效应,不过这篇博文上我不会讨论这个问题。

一旦我有了缓冲器的模型,通过连接组件就可以构建一个Sallen-Key滤波器的模拟模型。为了改变频率,我们需要一个双电位计。双电位计,如同其名称说明的一样,是由两个电位计组成的,但都由单个轴控制。在Sallen-Key滤波器模型中,我们会用到两个电位计组件,并用同一个信号来控制它们。

你可以在下图中看到我们新滤波器组件的电路图:

现在我们通过使用一个类似我们用来测试RC滤波器的模型来模拟一个滤波器(一个音频脉冲波和一个声表面波来控制电位计)。这个模拟测试模型会运行四秒然后我们将结果绘制出来:

这一次也一样,橙色信号是滤波后的输出,蓝色是输入的音频。我们可以在后面那段音频片段中听到这个滤波后的声音:

你可能会注意到得到的结果仍然听起来像是弹拨弦乐,但是声音已经听起来更柔和了。这是因为滤波器已经出了一些高频谐波。这个效应可从光谱图中看到。下面你可以看到Sallen-Key和RC滤波器的输出:

现在我们可以用Sallen-Key滤波器了,接下来我们用同样的简化方法得到微分方程和转换函数。把所有不需要限额变量都消去,并把变量名称变短:

这个系统有两个微分方程,每个电容器一个。输出电压对应C2电容器的电压:

从这些微分方程中,获取用电位计位置表示的转换方程:

下图显示了三个不同电位计位置对应的频率响应:

现在我们来逐项对比这两个滤波器。然后你可以看到两个滤波器的频率响应:Sallen-Key用橙色表示,RC用蓝色表示。RC滤波器有一个极点,提供的是每十倍频20分贝的衰减(即每八倍频6分贝),而Sallen-Key滤波器提供的是40分贝的衰减(每八倍频12分贝):

模拟一个简单的振荡器

我们在参考的一个自制振荡器是使用555集成电路构建的。通常基于555的振荡器是脉冲发生器。在我们的例子中,我们将调整了电路,生成了一个声表面波振荡器。为了模拟这个振荡器,我们首先需要创建一个555 集成电路的模型。幸运的是,555集成电路的资料记录完好,我们可以轻易地找到一个可以描述集成电路内部的方块图:

这个555由一个分压器,两个比较测量器,一个开关,一个晶体管和一个缓冲器。我可以使用Modelica组件创建这个模型。但是,在这个情况下,我决定尝试直接用Modelica代码创建这个模型。这是System Modeler可以为高级用户或想要完全控制模型里方程式的资源库程序员提供的一个强大功能。

这里我们可以看到我创建的代码。读者们不需要理解它们,只需要知道这些代码就是之前展示过的方块图就行。

通过连接振荡器配置中的555集成电路做成这个振荡器通常被称为“非稳态”。这让我们可以使用单个电位计就能控制音调。为了生成声表面波,我们使用缓冲器来测量电容器C1的充电/放电电压,然后加上C2作为解耦电容器,移除直流电的偏移量。你可以在下图中看到振荡器的组件图:

为了测试这个模型,我们使用了模拟电位计渐变变化,得到了振荡器音高的变化。就像我们前面在滤波器上做的测试一样,我们记录模拟产生的音频:

如果我们绘制模拟结果的一个小片段,我们可以看见生成的声表面波:

你注意到的第一件事可能是,这个波不是一个完美的声表面波。部分原因是电容器的充电不是完美线性。这种小细节决定了模拟振荡器的声音。但是我们不是说接受所有的缺陷。比如,模拟振荡器会随温度变化跑调。为了弥补这个缺点,更复杂的电路可以包括温度补偿机制。

当导入生成的音频文件时,我们可以听到振荡器是如何发出声音的:

我们可以听到这个声音一开始音调比较高,然后频率逐渐降低。我们从光谱图中可以看到这个效应。另外一件要注意的事情是,这个声表面波是如何由很多谐波组成的一个丰富的信号:

像之前提到的一样,通过使用类似滤波器这样的模块对谐波整形再组合起来得到减法合成。现在我们来看看,如果组合我们的滤波器和振荡器,会得到什么样的声音。

得到的声音类似一个低音大号。通过绘制波谱图,我们可以看到滤波器是如何打开和关上的,用来移除很多谐波。

模拟其他合成模块

到目前为止我们已经讨论了两种基本模块,一个振荡器和一个滤波器。为了创造更复杂的声音,必须创造一个常用函数的模型,比如包络发生器和放大器。以下组件不是由现存电路模拟而来。它们是模拟实际模块的真实行为的行为模型。

第一个是VCA,表示voltage-controlled amplifier(压控放大器)。在System Modeler中运行VCA很简单明了,因为VCA其实就是两个信号的倍增。其中一个信号用于控制,另一个信号用作来源。

请看下图,可以看见VCA的图标:

我们可以用Modelica资源库中的两个正弦波组件来测试这个模型:

在模拟结果中,我们可以看见信号振幅的变化:

如果你听这个音频,你会注意到感知音量是如何变化的:

下个模型中,我们需要一个包络发生器。包络常用于对声音振幅的整形。比如,敲鼓的时候,声音最初会有一个突然振幅变大的变化,然后逐渐衰减。为了模拟这个行为,我们可以用一个简单的RC电路,就像我们之前展示的滤波器的例子一样:

在前面的图标中,电容器C1在每次输入电压大于0.5V时回充到1V。可以通过把下列方程式加到模型来达到这一目的:

包络的衰减由改变电容器C1的值来定义。这个包络有用于使转换平滑的第二个RC阶段。随机选择电容器和电阻器的值来提供想要的转换。

为了测试这个包络,我们将包络与VCA模型结合起来,并用1 Hz的脉冲触发。音频信号是440 Hz的正弦波:

在模拟结果中,我们可以看到信号振幅的变化:

听听这个结果,我们可以听到这个模拟听起来像是用手指轻触红酒杯:

使用基础模型(加上一些Modelica资源库的实用程序),我创建了本篇博文一开始展示的数码音乐的短回路。我们不需要太关注细节,这个回路由三个声音组成:一个踏板鼓、一个贝斯合成器和一个踩擦合成器。所有这些都用一个混频器结合(电压相加),然后用WAV文件直接记录:

为什么音乐家不用System Modeler现场演奏?

之前的范例花了大概70秒来渲染30秒的音频。耗时比现实的时间多了一倍。主要原因是 System Modeler 用的解算器更多关注在提供高准确度的模拟。而且,System Modeler 会计算每个组件电路内部的电压和电流。这在我们做模型分析的时候很方便,但是就像我之前提到的一样,当创造音乐的时候,我们可以把我们所有的模型当做是黑匣子,并以使用尽可能少的 CPU 为目的优化它们。

当优化模拟模型时,为了得到一个有效的模拟我们还可以做一些其他让步。其中之一是用更低的精度进行模拟。这会导致模拟不那么完美,但是速度会更快,而且听众会很难辨别哪个模拟是哪个。所以要找到模型/模拟质量和效率之间找到一个平衡点。如果模拟过于简单,我们可能会丢失声音的“模拟电颤音”。另一方面,如果模拟非常准确,则CPU资源会被迅速耗尽。

将滤波器用作音频插件

现在我们可以开始用我们获取的Sallen-Key滤波器方程式,然后用该滤波器处理VCV Rack内的音频。所以我们需要VCV Rack和一个叫做VCV Prototype的插件。这两个工具都能从VCV Rack网站(https://vcvrack.com/)上免费获取。VCV Prototype是一个特殊模块,允许用我们自己的DSP代码测试,而不需要额外的工具。它还能支持我开发的一个编程语言叫做Vult。Vult语言(https://modlfo.github.io/vult/)是一个易懂但有限制的语言,我用这个语言来写我自己的插件。

VCV Rack Prototype模块。

为了用我们的滤波器,我们准备用得到的微分方程然后用一个数字积分器实时模拟这些方程。在这个范例中,我们会用到前向欧拉法。这个方法简单且快速,但是可能会有不稳定和不精确的缺点。但是对于这个范例而言,这个方法已经够好了。

下面的图表展示了我们得到的模拟Sallen-Key方程式的Vult语言代码。你可能会注意到这个代码有点像JavaScript或C++代码。这个代码描述了一个滤波器,接受输入电压vin,电位计的位置p和模拟时间步长h。

计算dvc1和dvc2两个导数,然后用欧拉方法使模拟进行一步。在我们运行代码之前,我们需要一小段代码计算时间步长h和电位计的位置。在运行这段代码之前,有三件事我们需要非常注意,所有这些都与电位计的位置p有关。第一个是值不能为0,因为这样会在方程式中产生一个0的除数。第二,p的值不能太小,不然这样会让欧拉模拟方法变得不稳定。第三,p与频率是线性关系,在处理音频的时候这并不是最佳情况。在声音滤波器中,比较倾向于用声音的方法控制临界值。为了处理这些问题,我们是用一个简单的公式来计算参数p:

这个公式使用knob变量,代表了电位计的线性位置(范围从0到1),然后返回p,这个值指数变化,并不为0.

如果我们把这个翻译成Vult语言,然后把最终的代码在VCV Prototype里运行,我们可以使用VCV Rack里的滤波器来制作音乐:

在这个视频(https://youtu.be/NZHgplJ0fHA)中,你可以听到我们用的滤波器在VCV Rack中实时运行。

用Wolfram科技进行尝试

使用System Modeler和Mathematica,我建立了一批模拟电路的模型,已在超过35个虚拟模块中进行了应用,这些模块可用于像VCV Rack和Cherry音频电压模块这样的平台上。

使用System Modeler创建的虚拟模块

在所有这些电路中,我已经建模了超过13个模拟滤波器,可用于电压合成器。所有这些模型都可以在我设计的自定义的硬件模块中运行。现在模拟滤波器可以有丰富的声音了,但可以很方便地打包进一个完整的数字模块。

自制硬件模块范例

我自己做了一个可以下载的完整的资源库。你可以自己下载 (https://blog.wolfram.com/data/uploads/2020/07/AnalogModelingLibrary.zip)并测试。你还可以下载一个无限制的12.1 System Modeler 30天试用版(https://www.wolfram.com/system-modeler/trial/),并按照自己的喜好调整包含的模型,或研究、学习开发你自己的模型进行更高级的分析。

想要了解更多Wolfram System Modeler新版本的细节,访问新功能(https://www.wolfram.com/system-modeler/what-is-new/)页面或可以到SystemModeler先有的资源库(https://www.wolfram.com/system-modeler/libraries/)去看看。


免费软件试用

创建 Wolfram ID 登录扫码下载试用版:

Wolfram Mathematica:

https://www.wolfram.com/mathematica/trial/

Wolfram System Modeler:

https://www.wolfram.com/system-modeler/trial/

有关软件购买和使用的问题,欢迎联系:

info-china@wolfram.com

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WOLFRAM 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档