最近整理音频相关的资料,有时候需要根据音频的波形来人为地判断哪一段数据是可取的,哪一段又是该删掉的。这个小问题却连续困扰了我多日:普通的音频播放软件只能流畅的播放音频,却无法显示数据波形. 为此,我利用Matlab编写一个小程序来解决这个问题。
随着音频的播放,窗口中有两个实时显示的图像:
第一个图像为整段音频的波形,红色部分为当前播放处长度为2s的实时波形.
第二个图像聚焦于上图音频中的红色部分,用于查看实时波形的细节.
% w->windows: 帧长
% d->delta: 移动窗
function FunWavflow(filename,t1,t2)
error(nargchk(2, 3, nargin, 'struct'));
[y fs]=audioread(filename);
pt = (length(y)-1)/fs;
if nargin == 2;
t2 = pt;
end
t = [t1 t2];
if length(t)~=2 | t(1) < 0 | t(2) > pt
error('01 - play time.');
return;
end
l1 = round(t(1)*fs+1);
l2 = round(t(2)*fs+1);
if size(y,2) == 2
y = mean(y(l1:l2,:)');
else
y = y(l1:l2)';
end
l = l2-l1+1;
w = 2*fs;
if l <= w
error('02 - short length.')
return;
end
k = floor(1.5e7/(fs*(t2-t1)));
d = floor(w/k);
n = ceil((l-w)/d)+1;
if w+(n-1)*d > l
y = [y zeros(1,w+(n-1)*d+1-l)];
end
for i = 1:n
pw(i,:) = y((i-1)*d+1:w+(i-1)*d);
td(i,:) = t(1)+(i-1)*d/fs+[0:w-1]/fs;
end
figure
lim = max(y(:));
sound(y,fs)
pause(w/fs)
ts = datetime('now');
for i = 1:n
subplot(2,1,1)
plot(t(1)+[0:length(y)-1]/fs,y,'k-')
hold on,plot(td(i,:),pw(i,:),'r-')
set(gca,'ylim',[-lim lim],'xlim',[max(t(1)-2,0),t(2)+2])
grid on;
subplot(2,1,2)
plot(td(i,:),pw(i,:),'k-');
set(gca,'ylim',[-lim lim],'xlim',[td(i,1) td(i,end)])
grid on;
tp = seconds(datetime('now')-ts)+t(1);
pause(td(i,1)-tp)
drawnow;
end
输入参数有三个,分别为音频文件名(filename)、起始播放时间(t1)、终止播放时间(t2);
其中,终止播放时间可省略,此时默认t2为音频的结尾.
帧长及移动窗的大小自由可调. 一般而言,移动窗越小,实时显示的连续感会越好,但是,由于计算机算力的原因,当取值过小时,播放与波形的显示将无法同步. 经过多次探索和调试,将移动窗的长度默认为取样率及音频长度的函数,能够保证计算机在音频播放与波形显示同步条件下的较高运算效率.
2019-08-07