MATLAB 编写简易电子琴(二)


前几天用MATLAB做了一个简易电子琴,链接:
MATLAB 编写简易电子琴
这个电子琴输入用的input函数,每按一个字符要敲回车,现在用另一种方法解决了这个问题:

使用 set(gcf,‘KeyPressFcn’,@key_Press) 输入字符,其中f=key_Press(~,event) 为自定义函数,例如,以下代码实时输出按下的键:

set(gcf,'KeyPressFcn',@key_Press)

function f=key_Press(~,event)
f=event.Key
end

电子琴完整代码如下:
主程序

%读入频谱、音阶-频率表
Amp_p=xlsread('Amp_p.xlsx');
Amp_p=1/max(Amp_p)*Amp_p;
global Amp
Amp=Amp_p;
global or
or=1;
global f_key
f_key=xlsread('frequency.xlsx','Sheet3','B1:C21');


%绘出钢琴图
global dW lW dB lB
dW=32;
lW=200;
dB=16;
lB=120;
global A;
A=key_image();
%figure(1)
figure('color',[0 0 0])
imshow(A)
title('Electronic Organ 1.0')
hold on

%键盘控制
set(gcf,'keyPressFcn',@key_Press)

function f=key_Press(~,event)
global or Amp f_key
c=event.Key;
   switch c
      case 'z'
          Amp=Amp_p;
      case 's'
          or=1;
      case 'a'
          or=0;
      case 'd'
          or=2;
      case '1'
          piano(f_key(or*7+1,1));  
          Dot_plot(1,1);
      case '2'
          piano(f_key(or*7+2,1));  
          Dot_plot(2,1);
      case '3'
          piano(f_key(or*7+3,1));  
          Dot_plot(3,1);
      case '4'
          piano(f_key(or*7+4,1));  
          Dot_plot(4,1);
      case '5'
          piano(f_key(or*7+5,1));  
          Dot_plot(5,1);
      case '6'
          piano(f_key(or*7+6,1));  
          Dot_plot(6,1);
      case '7'
          piano(f_key(or*7+7,1));  
          Dot_plot(7,1);
      case 'q'
          piano(f_key(or*7+1,2));  
          Dot_plot(1,2);
      case 'w'
          piano(f_key(or*7+2,2));  
          Dot_plot(2,2);
      case 'r'
          piano(f_key(or*7+4,2));  
          Dot_plot(4,2);
      case 't'
          piano(f_key(or*7+5,2));  
          Dot_plot(5,2);
      case 'y'
          piano(f_key(or*7+6,2)); 
          Dot_plot(6,2);
      otherwise
          disp('Again');
   end
   f=1;
end

%发出特定音高和音色的声音
function p=piano(f)
global 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.2^2)*t.^2);
x=sqrt(400/f)*x;   %这一行是想把低音变强一些,可以去掉
sound(x,fs)
p=1;
end

function plt=Dot_plot(para_1,para_2)
global dW lW dB lB or
L=1/2*dB;
global A
A2=A;
if para_2==1
  I_cen=3/4*lW;
  J_cen=(or*7+para_1)*dW-1/2*dW;
  A2(I_cen-L/2:I_cen+L/2,J_cen-L/2:J_cen+L/2,1)=ones(L+1,L+1,1);
  A2(I_cen-L/2:I_cen+L/2,J_cen-L/2:J_cen+L/2,2:3)=0*ones(L+1,L+1,2);
else
  I_cen=3/4*lB;
  J_cen=(or*7+para_1)*dW;
  A2(I_cen-L/2:I_cen+L/2,J_cen-L/2:J_cen+L/2,1)=ones(L+1,L+1,1);
  A2(I_cen-L/2:I_cen+L/2,J_cen-L/2:J_cen+L/2,2:3)=zeros(L+1,L+1,2);
end
imshow(A2)
plt=1;
end

调用的自定义函数 key_image() 用于生成琴键的图像:

function f=key_image()
dW=32;
lW=200;
dB=16;
lB=120;
A=ones(lW,dW*21,3);
for i=1:20
    A(:,i*dW-1:i*dW,:)=1/2*A(:,i*dW-1:i*dW,:);
end
Bkey_N=[1 2 4 5 6];
for i=1:3
    for j=1:5
    A(1:lB,((i-1)*7+Bkey_N(j))*dW-dB/2:((i-1)*7+Bkey_N(j))*dW+dB/2,:)=0*A(1:lB,((i-1)*7+Bkey_N(j))*dW-dB/2:((i-1)*7+Bkey_N(j))*dW+dB/2,:);
    end
end
f=A;
end

运行结果如下,在键盘上按下各按键后,会发出对应的琴声,并在对应的琴键上标出红框。
在这里插入图片描述附表:
frequency.xlsx
%第二列是全音频率,第三列是升半音,不存在的半音用0填上
C4 261.63 277.18
D4 293.66 311.13
E4 329.63 0
F4 349.23 369.99
G4 392 415.3
A4 440 466.16
B4 493.88 0
C5 523.25 554.37
D5 587.33 622.25
E5 659.25 0
F5 698.46 739.99
G5 783.99 830.61
A5 880 932.33
B5 987.77 0
C6 1046.5 1108.73
D6 1174.66 1244.51
E6 1318.51 0
F6 1396.91 1479.98
G6 1567.98 1661.22
A6 1760 1864.66
B6 1975.53 0

Amp_p.xlsx
%通过对某钢琴琴音做FFT得到的前八个倍频的相对振幅
645.4
183.7
30
20
20
20
20
56

演示视频:
MATLAB编写简易电子琴(改进版)

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值