返回列表 发新帖

乐音合成:天空之城 MATLAB钢琴版

[复制链接]

93

主题

896

帖子

1082

积分

金牌会员

Rank: 6Rank: 6

积分
1082
发表于 2022-7-24 20:56:04 | 显示全部楼层 | 阅读模式 IP:北京
注:由于钢琴世界文章无法上传音频,请有需要的读者自行复制代码运行。
实验内容

乐音的基本特征可用基波频率、谐波成分和包络波形三个方面来描述:
1)每个音调对应固定的基波频率。例如对于钢琴,琴键中央音调A 对应的频率值是440Hz,其他A 音是440Hz 的整数倍,如高八度A 音是880Hz,低八度A 音是220Hz。一个八度内频率被等间隔分为12 等分,相邻两音之间的频率倍率关系是2 ^(1/12) 倍,称为半音。
2)谐波成分及其强度的比例影响音色。不同乐器有不同的谐波分布。
3)包络波形与乐器的类型有关。
试查阅相关资料了解相关知识,用MATLAB 合成一小段音乐。
实验脚本

1. 国际标准音高与频率对照表(Scientific Pitch Notation)
八度*10行:0,1,2,3,4,5,6,7,8,9
音符*12列:C(do),C#/Db,D(re),D#/Eb,E(mi),F(fa),F#/Gb,G(so),G#/Ab,A(la),A#/Bb,B(si)
SCP=[...
    16.352,17.324,18.354,19.446,20.602,21.827,...
    23.125,24.500,25.957,27.501,29.136,30.868;...
    32.704,34.649,36.709,38.892,41.204,43.655,...
    46.250,49.001,51.914,55.001,58.272,61.737;...
    65.408,69.297,73.418,77.784,82.409,87.309,...
    92.501,98.001,103.829,110.003,116.544,123.474;...
    130.816,138.595,146.836,155.567,164.818,174.618,...
    185.002,196.002,207.657,220.005,233.087,246.947;...
    261.632,277.189,293.672,311.135,329.636,349.237,...
    370.003,392.005,415.315,440.010,466.175,493.895;...
    523.264,554.379,587.344,622.269,659.271,698.473,...
    740.007,784.010,830.629,880.021,932.350,987.790;...
    1046.528,1108.758,1174.688,1244.538,1318.542,1396.947,...
    1480.013,1568.019,1661.258,1760.042,1864.699,1975.580;...
    2093.056,2217.515,2349.376,2489.076,2637.084,2793.893,...
    2960.027,3136.039,3322.517,3520.084,3729.398,3951.160;...
    4186.112,4435.031,4698.751,4978.153,5274.169,5587.787,...
    5920.053,6272.077,6645.034,7040.168,7458.797,7902.319;...
    8372.224,8870.062,9397.502,9956.306,10548.337,11175.573,...
    11840.106,12544.155,13290.068,14080.335,14917.594,15804.639...
    ]; 钢琴88键:大字二/一组,大/小字组,小字一/二/三/四/五组;A0到C8,3+7*12+1=88
SCPT=SCP';
SCP_MAIN=SCP(:,[1,3,5,6,8,10,12]);
SCPT_MAIN=SCPT([1,3,5,6,8,10,12],:);
PIANO=SCPT(10:97);
PIANO_MAIN=SCPT_MAIN(6:57); 全局采样率设为8000
f=8000;2. 模拟钢琴的音色和音量衰减
1)真实钢琴的标准音(A4, 440Hz)
sample=audioread("49.mp3");         %所下载音频为双声道,采样率44100
sample=sample(:,1);
sample=sample/max(sample);
samplet=(1:length(sample))/44100;
clf;subplot(2,2,1);plot(samplet,sample);title("真实钢琴的时域波形");ylim([-1,1]);
samplel=length(samplet);
samplen=2^nextpow2(samplel);
sampley=fft(sample,samplen);
samplep=abs(sampley/samplel);
samplep=samplep/max(samplep);
samplep=samplep(1:ceil(samplen/2));
samplep(2:end-1)=samplep(2:end-1);
subplot(2,2,2);plot(0:(44100/samplen):(44100/2-44100/samplen),samplep);
title("真实钢琴的频域分量");xlim([0,4000]);
%sound(sample,44100);
pause(2);2)虚拟钢琴的标准音(A4, 440Hz)
依据真实钢琴的各级谐波比例,设置k值;根据网络资料的推荐及真实钢琴音效的时域波形,设置包络函数;通过sound函数试听,进一步调整上述两组参数,以最大程度还原真实钢琴的音效。 由此结果编写文末的mypiano函数。
testt=(1:3*f)/f;
testf=440.0100;
wave=sin(2*pi*testf*testt);
k=[1,0.20,0.15,0.15,0.10,0.10,0.01,0.05,0.01,0.01,0.003,0.003,0.002,0.002];
for i=2:14
    wave=wave+k(i)*sin(2*pi*testf*i*testt);
end
wave=wave/max(wave);                        %幅值归一化
wave=wave.*(testt.^0.01.*exp(-3*testt));    %波形包络线
subplot(2,2,3);plot(testt,wave);ylim([-1,1]);title("虚拟钢琴的时域波形");
testl=length(testt);
testn=2^nextpow2(testl);
testy=fft(wave,testn);
testp=abs(testy/testl);
testp=testp/max(testp);
testp=testp(1:ceil(testn/2));
testp(2:end-1)=testp(2:end-1);
subplot(2,2,4);plot(0:(f/testn):(f/2-f/testn),testp);ylim([0,1]);
title("虚拟钢琴的频域分量");
%sound(wave,8000);



3. 创建一段简谱:《天空之城》节选
tune记录音调,其中升1,升2等用8,9来表示,以此类推;0.5代表休止符0,后续会用mod1方法筛选出休止符。
rhythm记录每个音调的持续时间,4/4拍下,以16分音符为1,全音符为16;延音符号的其起始位置,将其值加0.5,同样用mod1筛选。
tune=[...
    6,7,8,7,8,10,7,3,3,6,5,6,8,5,0.5,3,3,4,3,4,8,...
    3,0.5,8,8,8,7,4,4,7,7,0.5,6,7,8,7,8,10,7,0.5,3,3,6,5,6,8,...
    5,0.5,3,4,8,7,7,8,9,9,10,8,0.5,8,7,6,6,7,5,6,0.5,8,9,10,9,10,12,...
    9,0.5,5,5,8,7,8,10,10,0.5,0.5,6,7,8,7,9,9,8,5,5,0.5,11,10,9,8,...
    10,10,0.5,10,13,12,12,10,9,8,0.5,8,9,8,9,9,12,10,0.5,10,...
    13,12,10,9,8,0.5,8,9,8,9,9,7,6,0.5,6,7,6];
rhythm=[...
    2.5,2,6.5,2,4,4,12,2,2,6.5,2,4,4,8,4,2,2,6.5,2,2.5,3,...
    8,2,2,2,2,6.5,2,4.5,4,8,4,2.5,2,6.5,2,4,4,8,4,2,2,6.5,2,4,4,...
    12,2,2,4,2.5,2.5,4,4,2,2,2,4,4,4.5,2,2,2,4,4,8,4,2,2,6.5,2,4,4,...
    8,4,2,2,2.5,2,4,4,8,4,4,2.5,2,4,4,2,2,6.5,2.5,4,4,4,4,4,4,...
    16.5,8,4,4,8,4,4,2,2,4,2,2,4,2.5,2.5,2,4,8,4,4,...
    8,8,2.5,2,8,2,2,2,2,2.5,2,4,8,4,2.5,2,16];
D_L=0+7*4;      %此曲为D大调
ftune=tune;     %音调转化为频率
for i=1:length(ftune)
    if mod(tune(i),1)==0
        ftune(i)=SCPT_MAIN(D_L+ftune(i));
    else
        ftune(i)=0;
    end
end
l=sum(rhythm);
speed=100;      %曲速(每分钟speed拍)
t0=60/speed/4;  %16分音符占t0秒
music=zeros(1,f*l*t0+5*f-1);
position=1;
n=1:length(music);
t=n/f;4. 合成钢琴曲
对简谱的解释不完全同于音乐理论,各种分类方法及参数配置由听感决定。
for i=1:length(ftune)
    if mod(tune(i),1)~=0                 %休止符:音量同步衰减一半
        music(position:position+3*f-1)=...
            music(position:position+3*f-1)*0.5;
    elseif mod(rhythm(i),1)~=0           %延音符号开始:a=0.01,b=2,衰减变慢
        music(position:position+3*f-1)=...
            music(position:position+3*f-1)+0.8*mypiano(8000,ftune(i),0.01,2);
    elseif i~=0 && mod(rhythm(i-1),1)~=0 %延音符号之中:a=0.05,b=3,开始变慢
        music(position:position+3*f-1)=...
            music(position:position+3*f-1)+0.4*mypiano(8000,ftune(i),0.05,3);
    elseif rhythm(i)>=8                  %较长音符(此为全音符),a=0.01,b=1.5,衰减变慢
        music(position:position+3*f-1)=...
            music(position:position+3*f-1)+mypiano(8000,ftune(i),0.01,1.5);
    else
        music(position:position+3*f-1)=...
            music(position:position+3*f-1)+mypiano(8000,ftune(i),0.01,3);
    end
    position=position+rhythm(i)*t0*f+1;
end
music=0.75*music/max(music);    %音量调节
clf;plot(t,music);title("天空之城");
%sound(music);
audiowrite("天空之城.wav",music,8000);



实验结果与讨论

上文已经详细给出了用以实现钢琴音并演奏曲目《天空之城》的代码,在此做以如下说明:
1)将sound函数的注释取消掉,即可通过试听来实时调整参数k,a,b,这也就是在实验进行中需要做的;
2)代码中通过audioread函数读取了“49.mp3”,此为互联网上下载的钢琴A4标准音音效,用来调整k,a,b等参数;
3)代码最后用audiowrite输出了“天空之城.wav”文件,此为用代码实现演奏的钢琴曲《天空之城》片段。
通过上述MATLAB代码演奏的钢琴曲,对真实钢琴有着较高的还原度。但音色不如真实钢琴清脆饱满,且受限于作者的乐理知识,忽略了乐谱中的复杂成分,故而连贯性和可欣赏性欠佳。真实的钢琴具有更加复杂多样的泛音特征,不同钢琴的音色也不尽相同,真实地还原钢琴音色需要及其复杂的数据作为支撑。
通过本文给出的代码,只要以同样的方式重新条件k,a,b,即可实现小提琴、吉他、二胡等其他乐器音色的模拟,理论上任何乐器,甚至人声,都可以通过相同方式、不同参数模拟出来。若想对此进行验证,可仅仅将a值改为0.5左右,其他保持不变,就可以得到类似管乐器或是弦乐器的声音。
函数mypiano

根据1中的调试结果,构建用以生成单个钢琴音的函数mypiano;
参数a主要作用于开始阶段,a越小,琴音出现越陡峭,听感越清脆;a越大,开始的波形越圆滑,听感向管乐器和弦乐器靠近;
参数b主要起衰减作用,b越大,衰减越快,反之衰减越慢。
此外,为了方便,为每个音调配置了相同的泛音比例,而这与实际情况是不同的。真实的钢琴每个音的泛音比例是有差异的。
function wave=mypiano(f,ftune,a,b)  %f:采样频率;ftune:基音频率;a:包络参数1;b:包络参数2.
    t=(1:3*f)/f;
    wave=sin(2*pi*ftune*t);
    k=[1,0.20,0.15,0.15,0.10,0.10,0.01,0.05,0.01,0.01,0.003,0.003,0.002,0.002];
    for i=2:14
        wave=wave+k(i)*sin(2*pi*ftune*i*t);
    end
    wave=wave/max(wave);
    wave=wave.*(t.^a.*exp(-b*t));
end
附录:国际标准音高与频率对照表和音乐简谱可自行在网络上搜索。
声明:作者并非相关行业从业人员,文中代码和结果均为原创,如有错误敬请批评指正。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册   手机动态码快速登录

x
打赏鼓励一下!

0

主题

337

帖子

40

积分

新手上路

Rank: 1

积分
40
发表于 2022-7-24 20:56:21 | 显示全部楼层 IP:吉林延边朝鲜族自治州
[赞同][赞同]
回复

使用道具 举报

0

主题

322

帖子

259

积分

中级会员

Rank: 3Rank: 3

积分
259
发表于 2022-7-24 20:56:55 | 显示全部楼层 IP:北京
[举报]
回复

使用道具 举报

0

主题

354

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
发表于 2022-7-24 20:57:16 | 显示全部楼层 IP:北京
感觉包络用指数不如用一次函数()[思考]
回复

使用道具 举报

0

主题

328

帖子

250

积分

中级会员

Rank: 3Rank: 3

积分
250
发表于 2022-7-24 20:57:58 | 显示全部楼层 IP:CNNIC
请问那个标注音49.mp3从哪里下载?谢谢。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册   手机动态码快速登录

本版积分规则

 
 
点击这里给我发消息
点击这里给我发消息
官方微信

招募城市商务合作 电话/微信 18702940294
 
快速回复 返回顶部 返回列表