MATLAB 编写简易电子琴

这篇博客介绍了如何使用MATLAB编写一个简易电子琴程序,探讨了声音的基础模型,包括基频和泛频对音高和音色的影响。作者通过MATLAB的sound函数生成声音,并分享了A4音的实现代码。此外,还讨论了电子琴程序的局限性,如按键响应不连贯的问题。最后,提供了实际钢琴音的频谱分析及简易电子琴的实现代码片段。


用MATLAB遍了一个小程序,可以弹奏一些简单的曲子。演示视频:
Bilbili视频:MATLAB 编写简易电子琴
一个电子琴基本的要求应当是能按键盘命令发出特定音高和音色的声音。键盘命令我用的是input 函数,缺点是每按一个键要回车使得弹奏很难连续,但目前没想到合适的替代方法;而声音的音高和音色则分别基频和泛频决定

声音模型

声音本质是机械振动产生的波通过介质传播至人耳,这一振动可由函数 x ( t ) x(t) x(t)表示,离散化后即为向量 x n x_n xn以及采样率 f s f_s fs,且满足 x n = x ( t n ) , t n = n / f s x_n=x(t_n), t_n=n/f_s xn=x(tn),tn=n/fs.
而MATLAB 中可用sound(x,fs)函数发出一段声音,如下面的代码运行后将发出一段白噪声:

 x=normrnd(0,1,1,10000);
 fs=5000;
 sound(x,fs)

琴弦则近似以如下方式振动(数学物理方法等教材有介绍):
x ( t ) = ∑ n = 1 N A n s i n ( 2 π f n t + ϕ n ) x(t)=\sum_{n=1}^{N}A_nsin(2\pi f_nt+\phi_n) x(t)=n=1NAnsin(2πfnt+ϕn)
其中基频 f 1 f_1 f1 决定声音的音高, f n , n > 1 f_n, n>1 fn,n>1决定音色。基频与音阶的部分对应表如下(没有加升降音):
E4 329.63
F4 349.23
G4 392
A4 440
B4 493.88
C5 523.25
D5 587.33
E5 659.25
F5 698.46
G5 783.99
A5 880
B5 987.77
C6 1046.5
D6 1174.66
E6 1318.51
F6 1396.91
G6 1567.98
A6 1760
B6 1975.53

于是,在MATLAB中发出A4音的代码如下:

fs=5000;
t=0:1/fs:1;
f=440;
x=sin(2*pi*f*t);
sound(x,fs)

音色

除基频 f 1 f_1 f1外,还有由高阶模式振动产生的倍频,各本征频频的振幅 A n A_n An以及相位 ϕ n \phi_n ϕn确定了声音的音色,简单起见,假定 ϕ 0 = 0 \phi_0=0 ϕ0=0。并加入一个衰减:
x ( t ) = e − t 2 / 2 t 0 2 ∑ n = 1 N A n s i n ( 2 π f n t ) x(t)=e^{-t^2/2t_0^2}\sum_{n=1}^{N}A_nsin(2\pi f_nt) x(t)=et2/2t02n=1NAnsin(2πfnt)
从网上找到一段任意音高的钢琴音,傅里叶变换后频谱如下:
记录下前八个本征频率对应的振幅 A n A_n An如下:
645.4
183.7
30
20
20
20
20
56

简易电子琴

编写函数piano(f,amp),其中f 为基频,amp为最低的数个本征频率对应的振幅,其中f通过查找键盘输入的音阶对应的频率得到。再循环运行此函数即可
代码如下:

Amp=xlsread('Amp.xlsx');
Amp=1/max(Amp)*Amp;
n=length(Amp);

f=xlsread('frequency.xlsx','B:B');
%To input "exit" to exit
IN=0;
or=1;
while 1
   IN=input('','s');
   switch IN
       case 's'
           or=1;
       case 'a'
           or=0;
       case 'd'
           or=2;
       case '1'
           piano(f(or*7+1),Amp);
       case '2'
           piano(f(or*7+2),Amp);
       case '3'
           piano(f(or*7+3),Amp);
       case '4'
           piano(f(or*7+4),Amp);
       case '5'
           piano(f(or*7+5),Amp);
       case '6'
           piano(f(or*7+6),Amp);
       case '7'
           piano(f(or*7+7),Amp); 
       case 'exit'
           break
       otherwise
           disp('Again');
   end
end

function p=piano(f,amp)
fs=32000;
t=0:1/fs:1;
x=0*t;
n=length(amp);
for i=1:n
   x=x+amp(i)*sin(2*pi*f*i*t); 
end
x=x.*exp(-1/(2*0.3^2)*t.^2);
sound(x,fs)
p=1;
end

这一电子琴小程序是写着玩的,非常简陋,一个较大的问题就是弹奏很难连续。如果有改进建议欢迎留言

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值