这篇文章我们来看下如何用Matlab和Python产生录制音频、播放音频、导入音频文件,并查看音频文件的波形图。
首先来看下Matlab中如何操作。Matlab提供了audio*
一系列函数来对音频信号进行处理,下面我们来一一讲解。
audiorecorder(Fs, NBITS, NCHANS, ID)
该函数用于产生一个audiorecorder
的对象,可以用来录制音频信号;其中Fs
表示采样率,常用的采样率有:8000, 11025, 22050, 44100, 48000和 96000 HzNBITS
表示采样位数,可以选择8、16、24NCHANS
表示声道数,只能是1或2,表示单声道或双声道ID
表示录音设备,不指定或者-1表示默认的录音设备 该函数配合recordblocking()
函数,一起完成录音功能。使用play()
函数来播放该刚刚录制的音频信号。
fs = 44100;
r = audiorecorder(fs, 16, 1);
disp('Start speaking.')
recordblocking(r, 2); % 录音2秒
disp('End of Recording.');
play(r);
如果要获取audiorecorder
对象中的音频数据,可以使用getaudiodata()
函数
mySpeech = getaudiodata(r, 'int16'); % get data as int16 array
figure;plot(mySpeech);
将录制的音频信号保存成文件,使用audiowrite()
函数,直接音频对象、保存文件名和采样率即可。
%% save file
filename = 'mySpeech.wav';
audiowrite(filename, mySpeech, fs);
对于先用的音频文件,使用audioread()
函数将其读入到workspace中,使用sound()
函数可以将该数据进行播放,如果要倍速或者慢速,调节sound()
函数中的采样率即可。
%% load file
r_data = audioread(filename);
%% play file data
sound(r_data, fs);
下面来看Python中如何完成上面的操作,在Python中,需要用到pyaudio
和wave
库,其中pyaudio
在安装时,使用conda install pyaudio
来完成,如果使用pip install pyaudio
是不行的,因为pyaudio
库需要PortAudio
的支持,PortAudio是一个免费、跨平台、开源的音频I/O库,这并不是一个python的库函数,因此不能使用pip
来进行安装,至于为什么用conda
安装是可以的,请自行搜索pip install
和conda install
的区别。
前面我们指定4个参数,分别是缓冲区帧数、采样位宽、声道数和采样率,跟Matlab中唯一的区别就是多了个缓冲区帧数,这个参数在我们录制和回放音频时会用到,由于每次录制/回放的点数都是有限的,因此在录制/回放时都是循环进行的,即每录制/回放完当前缓冲区的数据,再去重新取最新的数据进行录制/回放,Matlab中该过程不需要我们手动设置,Matlab的系统函数已经做好了。
在录制文件时,参数input=True
,在回放文件时,参数output=True
;如果回放文件时进行倍速或慢速,修改p.open()
中的参数rate
即可。在load_wave()
函数中通过str_data = wf.readframes(nframes)
读上来的都是字符串类型,因此我们又通过np.fromstring
转成了np.short
类型。
import pyaudio
import wave
import numpy as np
import matplotlib.pyplot as plt
CHUNK = 1024 # 每个缓冲区的帧数
FORMAT = pyaudio.paInt16 # 采样位数
CHANNELS = 1 # 单声道
RATE = 44100 # 采样率
def record_audio(wave_out_path, record_second):
""" 录音功能 """
p = pyaudio.PyAudio() # 实例化对象
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK) # 打开流,传入响应参数
wf = wave.open(wave_out_path, 'wb') # 打开 wav 文件。
wf.setnchannels(CHANNELS) # 设置单声道
wf.setsampwidth(p.get_sample_size(FORMAT))# 设置采样位宽为16bits
wf.setframerate(RATE) # 设置采样率
print('Start speaking for %dsn' % record_second)
for _ in range(0, int(RATE * record_second / CHUNK)):
data = stream.read(CHUNK)
wf.writeframes(data) # 写入数据
stream.stop_stream()
stream.close()
print('End of Recording.')
p.terminate()
wf.close()
def play_audio(wave_input_path):
p = pyaudio.PyAudio() # 实例化对象
wf = wave.open(wave_input_path, 'rb') # 读 wav 文件
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
data = wf.readframes(CHUNK) # 读数据
print('Play back audio.n')
while len(data) > 0:
stream.write(data)
data = wf.readframes(CHUNK)
stream.stop_stream()
stream.close()
p.terminate()
def load_wav(wave_input_path):
wf = wave.open(wave_input_path, 'rb') # 读 wav 文件
params = wf.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
str_data = wf.readframes(nframes)
wf.close()
wave_data = np.fromstring(str_data, dtype=np.short)
plt.figure()
plt.plot(wave_data)
plt.show()
if __name__ == '__main__':
record_audio('test.wav', 2)
play_audio('test.wav')
load_wav('test.wav')