当前位置:首页>java>代码分享 | 基于十二平均律的C大调音阶正弦波合成与动态可视化

代码分享 | 基于十二平均律的C大调音阶正弦波合成与动态可视化

  • 2026-10-17 19:22:05
代码分享 | 基于十二平均律的C大调音阶正弦波合成与动态可视化

一、算法核心原理:十二平均律音阶合成与声学建模

该代码通过十二平均律生成C大调音阶的15个音符(含高低八度),并基于正弦波合成原理生成对应音频信号。关键算法原理如下:

补充阅读

十二平均律音阶

十二平均律(12-Tone Equal Temperament)又称十二等程律,是将八度音程分为12个半音,使各相邻两律波长之比相等的律制。东周周王族曾国的曾侯乙编钟证明中国十二律的实践开始于西周或更早。 后由明太祖九世孙、郑藩第五代世子朱载堉于16世纪首次提出,时名“新法密率”,其通过自制81档大算盘完成八度均分计算,结果精确到小数点后25位。

十二平均律通过指数关系将八度分成12份,半音公比为2的12次方根,解决了三分损益法产生的“狼五度”问题,纯五度与自然泛音2/3高度近似,且允许自由转调 。现代钢琴调律采用平均加减调律法,通过调整纯律音程为平均律音程,结合上行或下行的循环生律方式构建音阶,并引入校对检验程序提升精度 。朱载堉设计基于等比数列的律管和律准重新规范乐器调音方法,该理论比荷兰数学家西蒙·斯蒂芬(1605年)和法国数学家马林·梅森(1636年)的类似研究早数十年 。巴赫的《等程律钢琴曲集》(1722年)通过48首作品验证了该律制的转调优势,而朱载堉的理论成果通过传教士著作传入欧洲,为键盘乐器的普及奠定基础。

十二平均律的音阶构建依赖于严格的指数关系:以基准音(如A4=440Hz)为起点,其他音的频率按 fk=fbase×212k 计算(k 为半音偏移数)。例如,C大调音阶中Do(261.63Hz)、Re(293.66Hz)、Mi(329.63Hz)等音高的生成,均遵循此公式。

1. 十二平均律的频率计算模型

数学基础:相邻半音频率比为 r=2^(1/12)(代码中 Once=2^(1/12))

音阶频率公式:

设基准频率 fbase=440Hz(国际标准A4音),则第 k 个半音的频率为:

其中 k 为半音索引(代码中 i 从1到25),常数10表示A4音在序列中的位置偏移。

补充阅读

C大调音阶

C大调是以C音为主音的自然大调音阶,由CDEFGAB七个自然音构成,无任何升降号。其音程结构遵循"全全半、全全全半"的规则,在音乐理论体系中具有基础性地位。历史上该调式曾被赋予庄严理性的象征意义,18世纪前后成为皇室庆典与宗教仪式的专用调式,贝多芬《欢乐颂》等作品通过C大调传递光明与希望的情感。现代音乐实践中,C大调的和弦体系(如C-F-G主属关系)构成吉他弹唱的基础框架,同时在交响乐创作中仍保持着重要地位。

C大调音阶以C音(Do)为起始音,由连续的七个基本音符构成完整序列:C(261.63Hz)、D(293.66Hz)、E(329.63Hz)、F(349.23Hz)、G(392.00Hz)、A(440.00Hz)、B(493.88Hz),并结束于高八度的C'(523.25Hz),形成八度闭环(频率比2:1)。其核心结构遵循“全音-全音-半音-全音-全音-全音-半音”的音程模式,即在十二平均律下,相邻音符的频率比严格对应:C到D为全音(频率比2^{2/12}≈1.122),D到E为全音,E到F为半音(频率比2^{1/12}≈1.059),F到G、G到A、A到B均为全音,B到C'为半音,总计12个半音实现完美的八度循环。C大调音阶的音符频率基于基准A4=440Hz通过指数公式f = 440 × 2^{(k-9)/12}计算(k为半音位置),其独特优势在于不含任何升降号,便于初学者理解和演奏键盘乐器,成为音乐教育的基石,在声学实验中,C大调常被用作测试标准,验证十二平均律的可靠性,强化了其在艺术与科学交叉领域的重要性。

2. 音阶映射逻辑

C大调音阶选择:

代码通过条件语句筛选特定索引(i=1,3,5,6,8,10,12,13,15,17,18,20,22,24,25)对应C大调音阶的15个音符:

Do(261.63Hz), Re(293.66Hz), Mi(329.63Hz), Fa(349.23Hz), Sol(392.00Hz), La(440.00Hz), Si(493.88Hz), Do'(523.25Hz), Re'(587.33Hz), Mi'(659.26Hz),Fa'(698.46Hz), Sol'(783.99Hz),La'(880.00Hz),Si'(987.77Hz), Do''(1046.50Hz)

音乐理论依据:

大调音阶遵循“全-全-半-全-全-全-半”的音程结构(如C到D为全音,E到F为半音)。

二、音频合成与信号处理的数学模型

1. 正弦波音频合成

时域信号公式:

每个音符的声波由正弦函数生成:

其中 t 为离散时间向量(代码中 Tn),由采样率 Fs=5000Hz 决定。

时间向量构造:

(总时长1秒,共2500个采样点)。

2. 声学参数设计

采样定理应用:

采样率 Fs=5000Hz 满足奈奎斯特准则(最高频率 fmax=1046.5Hz≪Fs/2)。

谐波特性:

纯正弦波不含谐波分量,生成音色纯净但单调,符合基础合成需求。

三、可视化与交互逻辑的数学表达

1. 频率点动态可视化

坐标系设计:

X轴:音符序列 A={1,2,…,15}

Y轴:频率范围 [100,1200]Hz(ylim([100,1200]))

动态标记:

每个音符播放时,在坐标 (i,fk) 处绘制蓝色圆圈('bo')和红色叉号('rx')。

2. 音频播放控制

时间延迟模型:

音符间间隔由 Twait=1秒(pause(Twait))控制,确保听觉连续性。

声卡接口调用:

sound(y(i,:), Fs) 函数将离散信号 y 按采样率 Fs 转换为模拟声波。

四、算法背后的声学与数学原理

1. 十二平均律的历史意义

十二平均律是朱载堉于16世纪提出的音律系统,将八度音程均分为12个半音,满足:

此系统解决了纯律的“转调不兼容”问题,成为现代音乐的理论基石。

2. 正弦波合成的局限性

音色简化:真实乐器音色包含基频 f0 与谐波 nf0 (n=2,3,…),而纯正弦波仅保留基频。

改进方向:

可通过傅里叶级数叠加谐波分量:

其中 An 和 ϕn 控制各谐波振幅与相位。

五、工程应用与扩展

1.音乐教育工具:直观展示音高与频率的对应关系,验证十二平均律的数学一致性。

2.声学算法验证平台:可作为滤波器设计、混响效果等音频处理算法的测试信号源。

3.可扩展性建议:1.引入ADSR包络模型(Attack-Decay-Sustain-Release)控制音量变化2.叠加多个振荡器(方波、锯齿波)丰富音色3.增加MIDI接口支持实时演奏

结论

该代码通过离散正弦波合成与十二平均律频率计算,实现了C大调音阶的生成与播放。其核心价值在于:1.数学严谨性:以指数关系 fk=440×2(k−10)/12 精确量化音高;2.声学基础性:验证采样定理与音频合成的底层原理;3.教育直观性:动态可视化频率点增强认知。

代码

clcclear;Fz=440;                                             %基准440HzFs=5000;                                            %采样频率Tn=2/Fs:2/Fs:1;                                     Once=2^(1/12);                                      %一阶变化for i=1:1:25;M(i)=Fz/Once^(10-i);                                    if i==1                                  y(1,:)=sin(2*pi*Tn*M(i));            %Do=261.63                                  x(1)=M(i);                                 elseif i==3                                  y(2,:)=sin(2*pi*Tn*M(i));            %Ra=293.66                                  x(2)=M(i);                                 elseif i==5                                  y(3,:)=sin(2*pi*Tn*M(i));            %Mi=329.63                                  x(3)=M(i);                                elseif i==6                                  y(4,:)=sin(2*pi*Tn*M(i));            %Fa=349.23                                  x(4)=M(i);                                 elseif i==8                                  y(5,:)=sin(2*pi*Tn*M(i));            %So=392.00                                  x(5)=M(i);                                                     elseif i==10                                  y(6,:)=sin(2*pi*Tn*M(i));            %La=440.00                                  x(6)=M(i);                                  elseif i==12                                  y(7,:)=sin(2*pi*Tn*M(i));            %Xi=493.88                                  x(7)=M(i);                                 elseif i==13                                  y(8,:)=sin(2*pi*Tn*M(i));            %Do!=523.25                                  x(8)=M(i);                             elseif i==15                                  y(9,:)=sin(2*pi*Tn*M(i));            %Ra!=587.33                                  x(9)=M(i);                                    elseif i==17                                  y(10,:)=sin(2*pi*Tn*M(i));           %Mi!=659.26                                  x(10)=M(i);                                elseif i==18                                  y(11,:)=sin(2*pi*Tn*M(i));           %Fa!=698.46                                  x(11)=M(i);                                                     elseif i==20                                  y(12,:)=sin(2*pi*Tn*M(i));           %So!=783.99                                  x(12)=M(i);                                        elseif i==22                                  y(13,:)=sin(2*pi*Tn*M(i));           %La!=880.00                                  x(13)=M(i);                               elseif i==24                                  y(14,:)=sin(2*pi*Tn*M(i));           %Xi!=987.77                                  x(14)=M(i);                               elseif i==25                                  y(15,:)=sin(2*pi*Tn*M(i));           %Do!!=1046.5                                  x(15)=M(i);                                endendfigure(1)A=1:16;                                            %序列长度plot(A,'k.')                                       %绘制函数图grid onhold onxlim([0,16])                                       % X轴范围ylim([100,1200])                                   % Y轴范围set(gca,'XTick',0:1:16);                           % X轴刻度 set(gca,'YTick',200: 100:1200);                    % Y轴刻度 for i=1:1:15    Twait=1;                                          plot(i,x(i),'bo')                              %蓝色×    plot(i,x(i),'rx')                              %红色点    sound(y(i,:),Fs);                              %sound    pause(Twait)                                   %播放间隔时间endhold off

计算结果

与我交流(为方便长期交流合作,加好友请按要求备注行业/专业,不胜感激))

微信号|wx18813053116

常用马甲|Grandfissure

最新文章

随机文章