matlab演奏最炫民族风的代码注释
用Matlab来放音乐,和用单片机加蜂鸣器放音乐的原理都差不多,就是把连续的声音信号事先转换成用数字信号,然后用扬声器按照一定的节奏放出来。换句话说,演唱者是把声音经过麦克风转换成电信号,录音设备对这个电信号按照一定的时间间隔(采样频率)进行采样,得到一长串数字。如果采样的频率高,即单位时间采样的点数多,同样长度的一首歌,得到的这串数字也越长。数字的大小表示电压的高低,也就是录制时声音的大小。这串数字就是原始的音频信号。
链接里给出的那段Matlab代码的功能,就是模拟产生那串代表音频信号的数字,把这串数字交给数字模拟转换器,生成对应的电压信号,再由扬声器把这个电信号(电能)转变成声音信号(机械能)。
我不懂音乐,就从信号的角度来解释吧。
%%----------------------------------------------------------------------
fs = 44100; % sample rate
dt = 1/fs;
这一行定义了采样频率为44100赫兹,也就是说每秒钟需要播放44100个数字。为什么是44100Hz,或者44.1KHz,而不是其他更高或者更低的频率?因为我们的耳朵能够感受到的声音频率大约是20Hz ~ 20KHz(我最多只能听到17KHz左右),对于更高频率的声音我们的耳朵只能“呵呵”了。然后根据采样定理,“当采样频率大于信号中最高频率的2倍时,采样之后的数字信号可以完整地保留了原始信号中的信息”,所以理论上20KHz的信号至少用40KHz去采样。44.1KHz这个数字按照维基百科的说法是Sony公司在1979年先开始使用,然后被公司慢慢接受了。dt就是fs的倒数,即每两个数据点之间的时间间隔。
%%----------------------------------------------------------------------
T16 = 0.125;
t16 = [0:dt:T16];
t4 = linspace(0,4*T16,4*k);
t8 = linspace(0,2*T16,2*k);
t16, t4, t8都是数组,他们的长度不一样。k表示t16数组的长度,是5513个点,也即44100的八分之一。i和j表示t4和t8数组的长度,分别是44100的二分之一和四分之一,这三个数组定义了每个音符播放的时间。以44100点为一秒钟,5513个点就表示持续八分之一秒的长度。
%%----------------------------------------------------------------------
mod4=(t4.^4).*exp(-30*(t4.^0.5));
mod4=mod4*(1/max(mod4));
mod8=(t8.^4).*exp(-50*(t8.^0.5));
mod8=mod8*(1/max(mod8));
mod16=(t16.^4).*exp(-90*(t16.^0.5));
mod16=mod16*(1/max(mod16));
f0 = 2*146.8; % reference frequency
ScaleTable = [2/3 3/4 5/6 15/16 ...
1 9/8 5/4 4/3 3/2 5/3 9/5 15/8 ...
2 9/4 5/2 8/3 3 10/3 15/4 4 ...
1/2 9/16 5/8];
% 1/4 notes
do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);
这一步相当于是生成一个调幅的包络函数,我们可以单独把mod4画出来看一看。最上面的图形就是mod4的函数图形,中间是cos(2*pi*ScaleTable(21)*f0*t4)的图形,下面是前两个的乘积,也就是do0f的图形。f0的频率是2*146.8 = 293.6Hz,查表是知道是D4,把他当做一个基准频率(我严重怀疑这个频率偏低了,听上去很不舒服,把f0改成880Hz就好听很多)。那么中间的图形是频率为ScaleTable(21)*f0 = 0.5*293.6 = 146.8Hz的正弦波。两个相乘得到了do0f的函数图形。do0f是1/4拍,它是一个22052个元素的数组,表示这个音符的频率是146.8Hz(this is weird!),播放0.5秒长度。
但是,这是一个频率单一的信号,且信号的幅度都一样,音符间的切换都很生硬。你可以动手试一试把每个音符前面相乘的mod4, mod8, mod16注释掉,然后再播放,你会发现真的很难听。如果大伯大妈每天晚上在广场上这个音乐跳舞,环保局的投诉电话肯定打爆了。所以,就用最上面的包络函数和正弦信号相乘,让每个音符柔和的飘过来,再缓缓的离开,这样的音乐就好听很多。
包络函数一般使用一个叫做ADSR的方法,就是把整个包络线分成四段,attack time, decay time, sustain level and relearse time. 每一段都根据需要有各自的函数和参数。
Synthesizer
%%----------------------------------------------------------------------
% 1/4 notes
do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);
re0f = mod4.*cos(2*pi*ScaleTable(22)*f0*t4);
mi0f = mod4.*cos(2*pi*ScaleTable(23)*f0*t4);
......
......
接下去的就是给每个音符定义一个数组,主要的参数就是节拍和频率。懂音乐的同学可以帮忙解释一下频率之间的关系,像我这样的乐盲就只能直接查表。
%%----------------------------------------------------------------------
% Melody by Schau_mal
part0 = [mi1f la0e la0e do1f mi1f ...
re1e re1s mi1s re1e do1e re1e do1e la0f ...
......
......
在接下去的一步是根据乐谱来生成一个大数组。对照着《最炫民族风》的乐谱,一一对应的写到数组里保存。这一步就相当于演唱者把他的声音录在了磁带里存放。下面的图是V1数组最开始的一段,就好比是磁带的一小段,或者说光盘的几圈。如果继续放大图像,看到的就是一个个点连成的折现,每44100个点需要一秒钟的时间播放。
%%----------------------------------------------------------------------
s = v1;
s = s/max(s);
sound(s,fs);
最后把数值归一化到[-1,1]区间。用Matlab自带的sound()函数播放。sound()函数需要两个参数,一个是音频信号的一个数组,另一个采样频率千万不要忘记。同一段信号用44100Hz播放是正常效果,用88200Hz就成了快进播放。
http://www.zhihu.com/question/20248007/answer/21230323
matlab演奏最炫民族风的代码注释的更多相关文章
- Matlab 代码注释
Matlab 代码注释 一直在找类似doxygen一样将程序注释发表成手册的方法,现在发现,Matlab的publish功能自己就能做到. Publish 简介 并非所有注释都能作为文本进行输出,MA ...
- IT荐书|10个最“牛叉”的代码注释
下面是 网友针对“你看到过的最好的代码注释是什么样的?”这个问题给出的回答的前10条: 1. // 亲爱的维护者: // 如果你尝试了对这段程序进行‘优化’, // 并认识到这种企图是大错特错,请增加 ...
- java代码注释规范
java代码注释规范 代码注释是架起程序设计者与程序阅读者之间的通信桥梁,最大限度的提高团队开发合作效率.也是程序代码可维护性的重要环节之一.所以我们不是为写注释而写注释.下面说一下我们在诉求网二 ...
- PHPDocument 代码注释规范总结
PHPDocument 代码注释规范 1. 安装phpDocumentor(不推荐命令行安装)在http://manual.phpdoc.org/下载最新版本的PhpDoc放在web服务器目录下使得通 ...
- [转]java代码注释规范
代码注释是架起程序设计者与程序阅读者之间的通信桥梁,最大限度的提高团队开发合作效率.也是程序代码可维护性的重要环节之一.所以我们不是为写注释而写注释.下面说一下我们在诉求网二期开发中使用的代码注释规范 ...
- MATLAB Coder从MATLAB生成C/C++代码步骤
MATLAB Coder可以从MATLAB代码生成独立的.可读性强.可移植的C/C++代码. 使用MATLAB Coder产生代码的3个步骤: 准备用于产生代码的MATLAB算法: 检查MATLAB代 ...
- vs2010代码注释自动生成api文档
最近做了一些接口,提供其他人调用,要写个api文档,可是我想代码注释已经写了说明,能不能直接把代码注释生成api?于是找到以下方法 环境:vs2010 先下载安装Sandcastle 和Sandcas ...
- 【转】Objective-C代码注释和文档输出的工具和方法
http://blog.xcodev.com/blog/2013/11/01/code-comment-and-doc-gen-tools-for-objc/ 代码注释可以让代码更容易接受和使用,特别 ...
- VVDocumenter - Xcod代码注释工具
刚接触IOS开发时,发现XCODE非常的强大的,后续的代码实践中发现XOCDE的代码文档注释非常的差, 每次都要用手敲,蛋疼至极: 随着不断学习发现XCODE有代码片段内嵌一说(如:for .bloc ...
随机推荐
- 最长公共上升子序列(LICS) 模板
void LICS() { ;i<=n;i++) { ; ;j<=n;j++) { if (a[i]==b[j]) f[i][j]=ma+; ][j]; ][j]>ma) ma=f[ ...
- ubuntu 14.04 上安装有道词典
Ubuntu 14.04用户在安装前要更新系统,即update&dist-upgrade. 下载地址:32/64bits http://codown.youdao.com/cidian/lin ...
- POJ 2992 求组合数的因子个数
求C(n,k)的因子个数 C(n,k) = (n*(n-1)*...*(n-k+1))/(1*2*...*k) = p1^k1 * p2^k2 * ... * pt^kt 这里只要计算出分子中素数因子 ...
- 五大要求让BPM与企业对接
BPM(即业务流程管理)在中国已经有多年的发展历史,但人们经常提到的还是企业对流程的迫切需要,鲜有人讨论什么样的企业才能实施BPM,或者换句话说BPM的本身对企业有什么要求.不是所有的工作都适合BPM ...
- AngularJS结构简介
AngularJS是MVC架构,M是C里面的属性-值,C是js的class,V是DOM 各个关键特性的结构如下图所示: http://my.oschina.net/tommyfok/blog/2970 ...
- win10 用微软账户登录无法访问共享的问题
百度找了一大堆可以解决的,最终最简单的方式(可能是bug): 测试了一下,Win10用微软账户登录的,连局域网共享时,输入用户名的时候,前面加个乱七八糟的域名就可以访问了: 比如: 用户名: ba ...
- grub2的使用
1,添加win 启动项 edit file: /boot/grub2/grub.cfg 插入这几行: menuentry 'Windows XXX' { set root=(hd0,) chainlo ...
- centos ssh 无密码登录
在linux系统中,ssh是远程登录的默认工具,因为该工具的协议使用了RSA/DSA的加密算法.该工具做linux系统的远程管理是非常安全的.telnet,因为其不安全性,在linux系统中被搁置使用 ...
- mysql 批量创建表,利用存储过程
最近根据需求,需要提前创建一批日志表,以日期结尾,每天创建一张,例如XXX20160530,请参考如下: BEGIN DECLARE `sName` VARCHAR(128); DECLAR ...
- Java Sudoku游戏
这几天尝试用Java的swing写图形程序,边学习边摸索写了个简单的数独游戏,在编写的过程中学到了不少关于swing的东西,而且对于图形化程序的编写也有了一点简单的认识: 善其事先利其器,既然写图形化 ...