logo资料库

matlab音乐制作.docx

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
一、合成简单音乐
二、用傅里叶变换分析音乐
信号与系统设计性实验之 MATLAB 音乐制作 实验报告 吕祺 电信提高 0901 班 U200913911
摘要: 本文共有四大部分:第一部分,简单的音乐合成;第二部分,用傅里叶变换 分析音乐;第三部分,基于傅里叶级数的音乐合成;第四部分,加包络除噪声。 由潜入深,一步一步分析了用 MATLAB 进行音乐合成的过程。通过本实验达到了 加深对傅里叶级数和傅里叶分析的理解,熟悉对 MATLAB 基本使用的目标,提高了 对一维信号与线性系统的直观认识。 一、合成简单音乐 A、 频率选择 音符对应的频率表如下: 音符 频率(HZ) 简谱码(T 值) 音符 频率(HZ) 简谱码(T 值) 低 1 DO #1 DO# RE 低 2 #2 RE# 低 3 M 低 4 FA # 4 FA# 低 5 SO # 5 SO# 低 6 LA # 6 低 7 SI 中 1 DO # 1 DO# 中 2 RE # 2 RE# 中 3 M 中 4 FA 262 277 294 311 330 349 370 392 415 440 466 494 523 554 587 622 659 698 63628 63731 63835 63928 64021 64103 64185 64260 64331 64400 64463 64524 64580 64633 64684 64732 64777 64820 # 4 FA# 中 5 SO # 5 SO# 中 6 LA # 6 中 7 SI 高 1 DO # 1 DO# 高 2 RE # 2 RE# 高 3 M 高 4 FA # 4 FA# 高 5 SO # 5 SO# 高 6 LA # 6 高 7 SI 740 784 831 880 932 988 1046 1109 1175 1245 1318 1397 1480 1568 1661 1760 1865 1967 64860 64898 64934 64968 64994 65030 65058 65085 65110 65134 65157 65178 65198 65217 65235 65252 65268 65283 经过观察,发现相邻音符之间频率成线性倍数关系,相邻两频率之商为 2^(1/12),
少数为 2^(2/12)。 通过计算,写出分段函数如下: if real(a)<0 a1=-2*real(a)-14; elseif real(a)<=3&&real(a)~=0 a1=2*real(a); elseif real(a)<7&&real(a)~=0 a1=2*real(a)-1; elseif real(a)>=7 a1=2*real(a)-1; end 通过 cos(2*pi*494*2^(a1/12)*[1:10]'*(1/44100))即可对应正确的频率,这样 省去了加谐波时的不便,可以直接在幅度上修改成求和的形式,如下所示: fn=horzcat(fn,[1 0.3094 0.0762 0.0912 0.0164 0.0232 0.0312 0.0223 0.0131 0.0112]*cos(2*pi*494*2^(a1/12)*[1:10]'*(1/44100) *([0:lengt*(1+imag(a))].*exp(-0.2:-0.01/(lengt*(1+imag(a))):-0.21)))); %horzcat 做连接运算,将前后音乐数据放在一个数组中 B、 播放长度控制 播放长度与数据长度成正比,通过 lengt 设置每一节拍长度如下: if nargin<=1 lengt=5000; else lengt=lengt; end%可以通过输入参数控制播放长度,不自行设置时也可使用默认值 节拍长度由音乐文件的虚部控制,可以减少数据量,若有多个节拍或半拍等,通 过虚部进行加减即可。如下为《我和你》的音乐数据: [3 5 1+i 0 2 3 -6+i 0 1 2 3 5 2+3*i 0 0 0 3 5 1+i 0 2 3 -6+i 0 2 -5 2 3 1+3*i 0 0 0]; 6+i 0 5+i 0 6+i 0 1+i 0 2 6 3 5 2+3*i 0 0 0 3 5 1+i 0 2 3 -6+i 0 2 -5 2 3 1+3i 0 0 0 ]; 当节拍为 1/4,1/8,3/2 等非整数倍时,可以将虚部设置成相应的值,如下为《同 一首歌》的音乐数据,可以看到使用虚部控制可以很方便地改变持续时长: 2 2 3+0.5i 4-0.5i 3 1 2+i 1 [-5+i 1 -6 1+3i -5+i 1 3 3-0.5i 4-0.5i 5 1 4+0.5i 3-0.5i 5 2-0.5i 3-0.5i 3-0.5i 2+2.5i 3+i 5 7 7+0.5i 6-0.5i 6+i
5 5-0.5i 6-0.5i 7 6-0.5i 3+3i]; 二、用傅里叶变换分析音乐 通过查阅 matlab 关于 fft 函数的相关帮助,写出相应函数代码,这一步比较简 单。需要注意的是: 1、从公式上看,matlab 的 fft 序号是从 1 到 N,但是绝大多数教材上是从 0 到 N-1。 2、Y=fft(x)之后,这个 Y 是一个复数,它的模值应该除以(length(x)/2), 才能得到各个频率信号实际幅值。作 FFT 分析时,幅值大小与 FFT 选择点数有关, 但不影响分析结果。 3、根据需要选点作图,fft 变换的结果是关于 y 轴对称的,且在频域可能扩展 到很大的一个值,这样不利于较小频率的直观分析,此时应选择变换结果前面一 半的相应项。 y=fft(fn);y1=abs(y); dnum=length(y1); f=(0:dnum-1).*freq/dnum; figure,plot(f(1:dnum/20),y1(1:dnum/20)/length(fn)); 三、基于傅里叶级数的音乐合成
通过读取音乐文件,分析频谱后将文件分成 8 份,用 wavwrite 保存,然后选择 其中一个分析谐波。 用 fft 变换分析频域特性,然后对谐波的幅值进行记录,将基频设为大小“1”, 求出其他谐频与基频的比例,得到幅值数组[1 0.3094 0.0762 0.0912 0.0164 0.0232 0.0312 0.0223 0.0131 0.0112]。取幅值代码如下: [fn,freq]=wavread('0.wav') fn=repmat(fn,20,1); y=fft(fn);y1=abs(y); dnum=length(y1); f=(0:dnum-1).*freq/dnum; figure,plot(f(1:dnum/20),y1(1:dnum/20)); [x,y]=ginput(12);
四、加包络,除噪声 谐频加上后,音乐基本制作成功,声音更加动听,与吉他的音色有几分接近。可 是由于是函数模拟的原因,没有实际乐器演奏的淡入淡出的效果。通过查阅资料 发现可以使用包络来调节。于是我经过多次尝试,在原来函数的基础上加上了自 然对数 exp(0:-1/(lengt*(1+imag(a))):-1)),音色变得非常好,没有了换音时 的杂音。
附完整程序如下: function [t]=play(m,lengt) freq=44100; if nargin<=1 lengt=5000; else lengt=lengt; end t=0;fn=0; %m=textread('youandme.txt'); m=[3 5 1+i 0 2 3 -6+i 0 1 2 3 5 2+3*i 0 0 0 3 5 1+i 0 2 3 -6+i 0 2 -5 2 3 1+3*i 0 0 0 6+i 0 5+i 0 6+i 0 1+i 0 2 6 3 5 2+3*i 0 0 0 3 5 1+i 0 2 3 -6+i 0 2 -5 2 3 1+3i 0 0 0 ]; % m=[-5+i 1 2 3+0.5i 4-0.5i 3 1 2+i 1 -6 1+3i -5+i 1 2 3 3-0.5i 4-0.5i 5 1 % 4+0.5i 3-0.5i 5 2-0.5i 3-0.5i 3-0.5i 2+2.5i 3+i 5 7 7+0.5i 6-0.5i 6+i 5 5-0.5i 6-0.5i 7 6-0.5i 3+3i]; %5-0.5i];% 3+3i] s=size(m); if s(1)==1 error('not a song'); end
for i1=1:(s(1)) for i2=1:(s(2)) a=m(i1,i2); while a~=0 if real(a)<0 a1=-2*real(a)-14; elseif real(a)<=3&&real(a)~=0 a1=2*real(a); elseif real(a)<7&&real(a)~=0 a1=2*real(a)-1; elseif real(a)>=7 a1=2*real(a)-1; end fn=horzcat(fn,[1 0.3094 0.0762 0.0912 0.0164 0.0232 0.0312 0.0223 0.0131 0.0112]... *cos(2*pi*494*2^(a1/12)*[1:10]'*(1/44100)*[0:lengt*(1+imag(a))])... .*exp(0:-1/(lengt*(1+imag(a))):-1)); drawnow plot(1:length(fn),fn); break end end end wavplay(fn,freq); y=fft(fn);y1=abs(y); dnum=length(y1); f=(0:dnum-1).*freq/dnum; figure,plot(f(1:dnum/20),y1(1:dnum/20));
分享到:
收藏