大家坐好,我要编故事了。
这两天又看了《我不是药神》(这是豆瓣介绍)这部电影,虽然已经知道故事是如何发展的,不过情节又一次拨动了我的心弦。好多情节翻来覆去在脑袋里出现:老阿婆求情,印度兄弟义无反顾的支持,机场送儿子走,入狱时众人相送。脑袋里总是出现一个声音:不该啊~ 看完电影,意犹未尽,于是找到了主题曲《只要平凡》,一直循环播放。
今天早上突发奇想,想看看matlab能和这个mp3文件擦出什么样的火花,于是就开始了今天这个“让matlab唱歌”的实验之旅。
搜到了这样一个帮助说明文档:
貌似这个audioread靠谱,上手试一试他给的例子:读取、播放音频文件。
上面例子里通过load handel.mat 文件,载入了两个变量:
用plot 命令把y画出来看一看:
可以用 audiowrite 将音频数据文件写入文件,用 audioread 读取音频文件。但是最重要的是:可以用sound 函数播放读入的音频数据。
% matlab脚本
clear,clc
load handel.mat % 加载handel.mat中的数据
plot(y) % 把音频采样值y画出来看看
max(y) %看看y的最大值
min(y) %看看y的最小值
filename = 'handel.wav';
audiowrite(filename,y,Fs); % 将音频采样信号写入文件 handel.wav
clear y,Fs; % 这是为了下面重新读入音频数据,暂时清除工作空间载入的两个变量。
[y,Fs] = audioread('handel.wav'); % 读取 handel.wav,还是获得音频数据y,采样率Fs
sound(y,Fs); % 播放音频文件,到这句,你就可以听见matlab在播放这首曲子。
一个无关紧要知识点:这里的handel.mat中的“Handel”指的是:乔治·弗里德里希·亨德尔。
嗯,我是从网上下载的这个mp3文件,想让matlab唱这首歌给我听
先看一下这个文件的信息,使用audioinfo这个函数:
clear all
filename = 'D:\myMatlab\只要平凡.mp3'
info = audioinfo(filename)
看到这个文件的文件名, 压缩格式,音频声道数量(NumChannels),采样率(SampleRate),采样点数(TotalSamples),时长(Duration),音频文件的BitRate千位/秒 (kbit/s) 数。
这首歌,时长246.1秒,每秒128Kbits,所以文件大小差不多有:246.1*128/8/1024=3.8M。(嗯,差不多,差不多)
当我们读入这个文件的时候,我们要用到的是采样率和通道数。
[data,Fs] = audioread(filename);
其中 Fs 为 44100,data是一个 10852464 * 2 的矩阵,二维double类型的矩阵,应该表示两个声道。试着用sound播放一下这首歌,
% 千万不要尝试不带Fs参数运行sound,没有Fs参数,将会按照默认的采样率 8192 播放音频。
% 想这首歌,如果原始采样率是44100,不带Fs参数时,相当于将歌曲放慢了 44100/8192=5.4倍,
% 听起来像动物低吼,很难听~
% sound(data)
sound(data,Fs) ; %这样就直接开始播放文件,要想停止,可以在命令行中执行下面的命令。
% clear sound %停止播放
% 如果你在一个脚本中执行了多个sound命令,感觉他好像会启动多个线程,一起播放声音。一个clear将会终止所有的播放。
嗯,上面我们看到,sound函数有两个参数就可以播放声音,第一个参数是一个矩阵,第二个参数是描述矩阵的参数。如果我们可以构造这个矩阵,就可以用sound让matlab唱出声音。
先搜索一下,do,re,mi 三个音的频率是多少:
分别是 261.63Hz,293.66Hz,329.63Hz。我们构造时间长度为一秒的do,每秒8192个采样点:
Fs = 8192;
t=0:1/(Fs-1):1; % 因为是从0s到1s,除去两个点,还要8190个点。
y1 =sin(2*pi*261.63*t); % 中央C,do,频率261.63Hz,时间从0到1秒,一共8192个采样点。
sound(y1,Fs); % 对你可以听到do了。
重复上面的步骤,构造re和mi,
Fs = 8192;
t=0:1/(Fs-1):1; % 因为是从0s到1s,除去两个点,还要8190个点。
y1 =sin(2*pi*261.63*t); % 中央C,do,频率261.63Hz,时间从0到1秒,一共8192个采样点。
y2 =sin(2*pi*293.66*t); % re
y3 =sin(2*pi*329.63*t); % mi
y = [y1,y2,y3]; % 三个音拼在一起,do re mi
sound(y,Fs)
这就让matlab唱出了do re mi,不过在两个音之间,会听到’哒’一声。看看这一声是怎么来的。这篇讨论中,高人解释了一下为什么会有’哒‘一声。我理解是:在y1和y2相接的时候,由于两个音有变化,所以产生了更多其他频率的分量,这个分量的声音就是’哒‘那一声。
如果这样,是不是就可以将乐谱写成矩阵,然后播放这个矩阵,就可以听见matlab了!对吧!
嗯,可能还有几个问题:
1、如何将乐谱变成一个数组?
2、如何消除两个音之间’哒‘这一声?
3、如何表现出不同乐器的音色?(多个泛音)