Matlab音乐合成实验
课程设计《音乐合成》实验报告
专 业: 测控技术与仪器 班 级: 测控11-2 班 姓 名: 谷晓峰 学 号: 11034010219
指导教师: 贺婷
广东石油化工学院计算机与电子信息学院
1
信号与系统课程设计
-------利用matlab合成音乐
一、实验目的
1. 熟悉MATLAB的软件和语言指令的使用;
2. 学习利用MATLAB进行连续信号的时域、频域分析;
3. 熟悉抽样信号与连续信号的区别。
二、实验
1(请根据《画心》片断的简谱和“十二平均律”计算出该片断中各个乐音的频率,在MATLAB 中生成幅度为1抽样频率为8kHz 的正弦信号表示这些乐音。请用sound
数播放每个乐音,听一听音调是否正确。最后用这一系列乐音信号拼出《画心》片断,注意控制每个乐音持续的时间要符合节拍,用sound 播放你合成的音乐,听起来感觉如何,并用图显示生成的音乐信号。 相关知识:
? 《画心》完整曲谱,实验时从中随机截取几节用于编程。
2
? 利用十二平均律计算频率以及相关音乐知识。
如图1,其中错误~未找到引用源。,错误~未找到引用源。,错误~未找到引用源。相当于错误~未找到引用源。的二次谐波,二者是倍频的关系。从A到A1共有12个键,7个白色键,5个黑色键。中间这些频率值得计算规律为相邻音倍乘系数错误~未找到引用源。。即错误~未找到引用源。,别的依次类推。
图1 钢琴键盘
图1中各键对应的频率如下表:
bG表示的F升高半音,在乐谱中用#表示。或者G降低半音,用b表示。乐谱这中的4/4表示每小节有四拍,一个1/4音符的持续时间为一拍,一拍大概0.5s左右。 eg:
y=0*t; %初始化
y(t<0.25)=sin(440*2*pi*t(t<0.25)); %第一个音 5,持续时间0.25s y(0.25<t&t<0.5)=sin(392*2*pi*t(0.25<t&t<0.5)); %第二个音3,持续时间0.25s
sound(y,8000) %播放音乐
三(实验步骤
3
3.1音乐合成
根据《画心》第一小节的简谱和十二平均律计算出该小节每个乐音的
频率,在MATLAB中生成幅度为1,抽样频率为8kHz的正弦信号表示这些乐音,用sound播放合成的音乐。
由图可知《画心》的曲调定为D,即1=D,对应的频率为293.66Hz,据此可以计算出其他乐音的频率,一次类推计算出第一小节各乐音对应的频率为: 乐音 频率 乐音 频率 乐音 频率
在确定了各乐音的频率之后需要确定每个乐音的持续时间。每小节有两拍,一拍的时间是0.5s,因此各乐音的持续时间为: 乐音 时间 乐音 时间 乐音 时间
而在MATLAB中表示乐音所用的抽样频率为fs=8000Hz,也就是所1s钟内有8000个点,抽样点数的多少就可表示出每个乐音的持续时间的长短。用一个行向量来存储这段音乐对应的抽样点,在用sound函数播放即可。 根据以上分析在MATLAB中编写如下程序: sound_1_1.m
5 0.25 5 0.25 5 0.25
3 0.25 3 0.25 3 0.25
3 0.5 3 0.5 3 0.5
2 0.25 2 0.25 2 0.25
1 0.25 1 0.25 1 0.25
2 0.5 3 0.5 2 0.5
2 0.25 5 0.25 1 0.25
5 0.25 6 0.25 7 0.25
3 1.5 3 1.5
5 440 5 440 5 440
3 3 2 1 2 2 5 3 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 3 3 2 1 3 5 6 3 349.23 349.23 329.23 293.66 349.23 440 493.88 349.23 3 3 2 1 2 1 7 349.23 349.23 329.63 293.66 329.63 293.66 277.96
4
在MATLAB中运行sound_1_1.m,播放出了《画心》的第一段,但是
可以听出效果很不好,只能听出具有《画心》的调子而已。
3.2除噪音,加包络
最简单的包络为指数衰减。最简单的指数衰减是对每个音乘以e
实验中首先加的是e?1.5t??t因子,在的衰减,这种衰减
使用的是
相同速度的衰减,但是发现噪音并没有完全消除,播放的音乐效果不是很
好,感觉音乐起伏性不强。于是采用不同速度的衰减,根据乐音持续时间
的长短来确定衰减的快慢,乐音持续时间越长,衰减的越慢,持续时间越
短,衰减的越快。在1.1程序的基础上加上包络,编写如下程序:
sound_1_21.m
clear;clc;
5
fs=8000; %抽样频率
f=[440 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66
277.96]; %各
个乐音对应的频率
time=fs*[0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,
0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25]; %各个乐音的抽样点数
N=length(time); %这段音乐的总抽样点数
east=zeros(1,N); %用east向量来储存抽样点
n=1;
for num=1:N %利用循环产生抽样数据,num表示乐音编号 t=1/fs:1/fs:time(num)/fs; %产生第num个乐音的抽样点
baoluo=zeros(1,time(num)); %为存储包络数据的向量
for j=1:time(num)
if (j<0.2*time(num))
y=7.5*j/time(num);
else
if(j<0.333*time(num))
y=-15/4*j/time(num)+9/4;
else
if(j<0.666*time(num))
y=1;
else
y=-3*j/time(num)+3;
end
end
end
baoluo(j)=y;
end
east(n:n+time(num)-1)=sin(2*pi*f(num)*t).*baoluo(1:time(num));
%给第num个乐音加上包络
n=n+time(num);
end
sound(east,8000) %播放音乐
6
plot(east)
播放后可以听出噪音已经消除,同时因为不同时长的乐音衰减的快慢不一样,音乐听起来更有起伏感,下图是加包络后的east图像。
3.3改变程序,实现3.2中的音乐升高和降低一个八度
升高一个八度即每个乐音的频率都提高一倍,变为原来的2被;降低一个八度即每个乐音的频率都减小一倍,变为原来的1/2。因此最简单的办法是将存储乐音频率的向量每个元素改变为2或1/2倍。
即将程序中的即将程序中的f=[440 349.23 349.23 329.63 293.66 329.63
329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88
349.23 440 349.23 349.23 329.63 293.66 329.63 293.66 277.96];改为 f=[440
349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66 277.96]; *2;或
f=[440 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66 277.96]; /2;
将上述音乐上高半个音阶,即将频率变为原来的2
resamlpe函数对原来的数据点进行重采样来实现
east=resample(east,100,106);
7 1/12(1.06)倍,可以利用
因为resample进行重新采样后会使每个乐音的持续时间改变,但是因
为升高半个音阶,频率改变不大,所以每个音的持续时间是基本不变的。
升高一个八度:
fs=8000; %抽样频率
f=[440 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66
277.96]; %各个乐音对应的频率
time=fs*[0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25];
%各个乐音的抽样点数 N=length(time); %这段音乐的总抽样点数
east=zeros(1,N); %用east向量来储存抽样点
n=1;
for num=1:N %利用循环产生抽样数据,num表示乐音编号
f=f*2
t=1/fs:1/fs:time(num)/fs; %产生第num个乐音的抽样点
east(n:n+time(num)-1)=sin(2*pi*f(num)*t);
n=n+time(num);
end
sound(east,8000)
%播放音乐
运行得到图像为:
8
降低一个八度:
fs=8000; %抽样频率
f=[440 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440
349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66
277.96]; %各个乐音对应的频率
time=fs*[0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,
0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25];
%各个乐音的抽样
点数
N=length(time); %这
段音乐的总抽样点数
east=zeros(1,N); %用east
向量来储存抽样点
n=1;
for num=1:N %利用循环产生抽样数据,
num表示乐音编号
f=f/2
t=1/fs:1/fs:time(num)/fs; %产生第num
个乐音的抽样点
east(n:n+time(num)-1)=sin(2*pi*f(num)*t);
9
n=n+time(num);
end
sound(east,8000)
%播放音乐
plot(east)
运行得到图像为:
在3.2的音乐中加入谐波
在1.2的音乐中加上二、三、四次谐波,基波幅度为1,高次谐波幅
度分别为0.2、0.3、0.1。只需将1.2程序改为
sound_1_4.m fs=8000; %抽样频率
f=[440 349.23 349.23 329.63 293.66 329.63 329.63 440 349.23 440 349.23 349.23 329.63 293.66 349.23 440 493.88 349.23 440 349.23 349.23 329.63 293.66 329.63 293.66
277.96]; %各个乐音对应的频率
time=fs*[0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25,1.5,0.25,0.25,0.5,0.25,0.25,0.5,0.25,0.25];
%各个乐音的抽样
点 10
数
N=length(time); %这段
音乐的总抽样点数
east=zeros(1,N); %用east向量来储存抽样点
n=1;
for num=1:N %利用循环产生抽样数据,num表示乐音编号
t=1/fs:1/fs:time(num)/fs; %产生第num个乐音的抽样点
baoluo=zeros(1,time(num)); %为存储包络数据的向量
for j=1:time(num)
if (j<0.2*time(num))
y=7.5*j/time(num);
else
if(j<0.333*time(num))
y=-15/4*j/time(num)+9/4;
else
if(j<0.666*time(num))
y=1;
else
y=-3*j/time(num)+3;
end
end
end
baoluo(j)=y;
end
h=[1 0.2 0.3 0.1];
xiebo=zeros(1,length(t));
for i=1:length(n)
xiebo=xiebo+h(i)*sin(2*i*pi*f(num)*t);
end
east(n:n+time(num)-1)=xiebo.*baoluo(1:time(num));
n=n+time(num);
end
sound(east,8000) %
播放音乐
11
plot(east)
运行得到图像为:
四(用傅立叶变换分析音乐
1、载入 fmt.wav 并播放
利用wavread函数载入,用sound函数播放,这段音乐听起来比之前合成的音乐更加真实, 因为里边含有丰富的谐波。
fmt_wave=wavread('fmt.wav');
sound(fmt_wave);
2、载入文件 Guitar.mat,处理原始数据 realwave
载入文件Guitar.mat,分析wave2proc是怎么由realwave得到的。利用load Guitar.mat;载入并 用plot函数将realwave、wave2proc分别画出。 12
plot(realwave);
plot(wave2proc);
程序:
clear all;clc;
fmt_wave=wavread('fmt.wav'); sound(fmt_wave);
load Guitar.mat;
figure;
plot(realwave);
figure;
plot(wave2proc);
运行结果:
13
14