写在前面
以前的版本会出现音频播放与波形显示不同步的情况,且还需手动调整步长,并不能算是严格意义上的播放器。为此,在新版本中添加了定时器功能。
“最近整理音频相关的资料,有时候需要根据音频的波形来人为地判断哪一段数据是可取的,哪一段又是该删掉的。这个小问题却连续困扰了我多日:普通的音频播放软件只能流畅的播放音频,却无法显示数据波形. 为此,我利用Matlab编写一个小程序来解决这个问题。”
先看效果
如图所示:
随着音频的播放,窗口中有两个实时显示的图像:
第一个图像为整段音频的波形,红色部分为当前播放处的实时波形.
第二个图像聚焦于上图音频中的红色部分,用于查看实时波形的细节.
函数代码
两个子程序:
第一个为定时器结构;第二个为播放器。
% 定时器:播放窗口设置
function sound_timer(signal,player,half_space)
% 计算片段左右侧索引
left = player.CurrentSample - half_space;
right = player.CurrentSample + half_space;
left = max(1,left);
right = min(right,length(signal));
fragment = signal(left:right);
t = ([left:right]-1)/player.SampleRate;
if left<=1
fragment = [zeros(1,right-left+1),fragment];
t = [(2*left-right-1:left-1)/player.SampleRate,t];
end
if right>=length(signal)
fragment = [fragment,zeros(1,right-left+1)];
t = [t,(right+1:2*right-left+1)/player.SampleRate];
end
subplot(2,1,1)
plot(([1:length(signal)]-1)/player.SampleRate,signal,'k-')
hold on,plot(t,fragment,'r-')
set(gca,'xlim',([1 length(signal)]+[-1 1]*half_space)/player.SampleRate,'ylim',[min(signal) max(signal)]);
xlabel('时间/s')
ylabel('幅值')
subplot(2,1,2)
plot(t,fragment,'r-')
set(gca,'xlim',[t(1),t(end)],'ylim',[min(signal) max(signal)]);
xlabel('时间/s')
ylabel('幅值')
end
% 播放器
function sound_play(signal,fs,fragment)
warning off
if nargin<4
fragment = length(signal)/fs/50;
end
player = audioplayer(signal,fs);
half_space = round(fragment*fs/2);
figure,set(gcf,'position',[680 673 683 305]);
subplot(2,1,1)
plot(([1:length(signal)]-1)/fs,signal,'k-')
set(gca,'xlim',([1 length(signal)]+[-1 1]*half_space)/fs,'ylim',[min(signal) max(signal)]);
xlabel('时间/s')
ylabel('幅值')
subplot(2,1,2)
set(gca,'xlim',([1 length(signal)]+[-1 1]*half_space)/fs,'ylim',[min(signal) max(signal)]);
xlabel('时间/s')
ylabel('幅值')
pause(fragment);
play(player);
my_timer = timer('BusyMode','drop','ExecutionMode', 'fixedSpacing', 'Period', fragment);
my_timer.StartDelay = 0;
my_timer.TimerFcn = @(~,~) sound_timer(signal,player,half_space);
start(my_timer)
pause(length(signal)/fs+2)
delete(my_timer)
end
运行示例:
clear;clc;close all;warning off
fs = 20000;
signal = sin(2*pi*1000*[0:4*fs]/fs)+randn(1,4*fs+1);
sound_play(signal,fs,0.1);
输入参数有三个,分别为音频信号(signal)、采样率(fs)、定时器时间(fragment);
其中,定时器时间可省略,定时器的时间设置越小,看起来越流畅,但对计算机内存的占用也越多.
2021/01/11