使用 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编写简易电子琴(改进版)