Matlab:实时播放音频并显示波形

目录标题

  • 写在前面
  • 先看效果
  • 函数代码

写在前面

最近整理音频相关的资料,有时候需要根据音频的波形来人为地判断哪一段数据是可取的,哪一段又是该删掉的。这个小问题却连续困扰了我多日:普通的音频播放软件只能流畅的播放音频,却无法显示数据波形. 为此,我利用Matlab编写一个小程序来解决这个问题。

先看效果

如图所示:
Matlab:实时播放音频并显示波形_第1张图片Matlab:实时播放音频并显示波形_第2张图片

随着音频的播放,窗口中有两个实时显示的图像:
第一个图像为整段音频的波形,红色部分为当前播放处长度为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

你可能感兴趣的:(Matlab:实时播放音频并显示波形)