从wav文件,MATLAB中删除噪音

use*_*501 14 audio matlab signal-processing wav noise-reduction

我只使用MATLAB作为计算器,所以我不太熟悉这个程序.我希望一个善良的人可以指导我,因为谷歌目前不是我的朋友.

wav在下面的链接中有一个文件,其中有人声和背景中的一些噪音.我希望去除噪音.有谁能告诉我如何在MATLAB中做到这一点?

https://www.dropbox.com/s/3vtd5ehjt2zfuj7/Hold.wav

ray*_*ica 41

这是一个非常不完美的解决方案,特别是因为一些噪声嵌入在与您在文件中听到的语音相同的频率范围内,但这里什么都没有.我所谈论的频谱是,如果你听到声音,背景噪音的嗡嗡声很低.这属于频谱的低频范围,而语音具有更高的频率.因此,我们可以应用带通滤波器来消除低噪声,捕获大部分语音,并且较高侧的任何噪声频率也将被取消.

以下是我所做的步骤:

  1. 使用读入音频文件audioread.
  2. 播放原始声音,这样我就可以听到它的声音.通过创建audioplayer对象来完成此操作.
  3. 绘制左右声道以查看时域中的声音信号......如果它提供了任何线索.看看这些频道,它们看起来都是一样的,所以看起来只是一个麦克风被映射到两个频道.
  4. 我采用了傅立叶变换并观察了频率分布.
  5. 使用(4)我想出了应该切断频率的粗略近似值.
  6. 设计了一个带通滤波器,可以切断这些频率.
  7. 过滤信号然后通过构建另一个audioplayer对象来播放它.

我们走吧!


步骤1

%% Read in the file
clearvars;
close all;
[f,fs] = audioread('Hold.wav');
Run Code Online (Sandbox Code Playgroud)

audioread将为您读入音频文件.只需指定您想要的文件''.此外,请确保将工作目录设置为存储此文件的位置. clearvars, close all只是为我们清理.它会关闭所有窗口(如果有的话),并清除MATLAB工作区中的所有变量. f将信号读入MATLAB,同时fs是信号的采样频率. f这是一个2D矩阵.第一列是左声道,第二列是右声道.通常,音频文件中的通道总数由此矩阵中的总列数来表示audioread.

第2步

%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;
Run Code Online (Sandbox Code Playgroud)

此步骤将允许您创建一个audioplayer对象,该对象接收您在(f)中读取的信号,具有采样频率fs并输出存储的对象pOrig.然后pOrig.play,您可以在MATLAB中播放该文件,以便您可以听到它.

第3步

%% Plot both audio channels
N = size(f,1); % Determine total number of samples in audio file
figure;
subplot(2,1,1);
stem(1:N, f(:,1));
title('Left Channel');
subplot(2,1,2);
stem(1:N, f(:,2));
title('Right Channel');
Run Code Online (Sandbox Code Playgroud)

stem是一种在MATLAB中绘制离散点的方法.每个时间点都有一个圆绘制的点,从水平轴到该时间点绘制一条垂直线. subplot是一种在同一窗口中放置多个数字的方法.我不会在这里介绍它,但是你可以subplot通过参考我在这里写的这篇StackOverflow文章来详细了解它是如何工作的.上面的代码生成如下所示的图:

信号

上面的代码很简单.我只是在每个子图中单独绘制每个通道.

第4步

%% Plot the spectrum
df = fs / N;
w = (-(N/2):(N/2)-1)*df;
y = fft(f(:,1), N) / N; % For normalizing, but not needed for our analysis
y2 = fftshift(y);
figure;
plot(w,abs(y2));
Run Code Online (Sandbox Code Playgroud)

看起来最可怕的代码是上面的代码.如果您从信号和系统中回想起来,我们信号中表示的最大频率是采样频率除以2.这称为奈奎斯特频率.音频文件的采样频率为48000 Hz,这意味着音频文件中表示的最大频率为24000 Hz.fft代表快速傅立叶变换.可以将其视为计算傅里叶变换的一种非常有效的方法.传统公式要求您对输出中的每个元素执行多个求和.FFT将通过要求少得多的操作来有效地计算这一点,并且仍然可以给出相同的结果.

我们用fft来看一下信号的频谱.您可以fft通过指定所需的输入信号作为第一个参数进行调用,然后使用第二个参数指定要评估的点数.通常,您将FFT中的点数指定为信号的长度.我这样做是通过检查我们的声音矩阵中有多少行.当你绘制频谱时,我只用了一个通道来简化,因为另一个通道是相同的.这是第一个输入fft.另外,请记住,我除以N它是正确化信号的正确方法.但是,因为我们只想拍摄频域的样子,所以你真的不需要这样做.但是,如果您计划以后使用它来计算某些内容,那么您肯定需要.

我写了一些额外的代码,因为默认情况下光谱是未经验证的.我用fftshift这样的中心映射到0赫兹,而左边从0跨越至-24000Hz而右边的跨度是从0到24000赫兹.这是我直观地看到频谱的方式.您可以将负频率视为以相反方向传播的频率.理想情况下,负频率的频率分布应等于正频率.绘制频谱时,它会告诉您频率对输出的贡献.这是由信号的大小来定义的.你通过这个abs功能找到了这个.您获得的输出如下所示.

在此输入图像描述

如果你看一下情节,低频范围周围会有很多尖峰.这对应于你的嗡嗡声,而声音可能映射到更高的频率范围,并没有那么多,因为听不到那么多的声音.

第五步

通过反复试验并查看步骤#5,我认为从700赫兹到下的所有内容都对应于嗡嗡声,而较高的噪音贡献则来自12000赫兹及更高.

第6步

您可以使用butter信号处理工具箱中的功能来帮助您设计带通滤波器.但是,如果您没有此工具箱,请参阅此StackOverflow文章,了解用户制作的功能如何实现相同的功能.但是,该过滤器的顺序仅为2.假设您具有butter可用功能,则需要确定您希望过滤器的顺序.订单越高,它的工作就越多.我选择n = 7开始.您还需要对频率进行标准化,使奈奎斯特频率映射到1,而其他所有频率都映射到0和1之间.一旦这样做,您可以这样调用butter:

[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');
Run Code Online (Sandbox Code Playgroud)

bandpass标志表示您要设计带通滤波器,beginFreqendFreq映射到带通滤波器所需的标准化开始和结束频率.在我们的例子中,那是beginFreq = 700 / NyquistendFreq = 12000 / Nyquist. b,a是用于过滤器的系数,可帮助您执行此任务.你需要这些用于下一步.

%% Design a bandpass filter that filters out between 700 to 12000 Hz
n = 7;
beginFreq = 700 / (fs/2);
endFreq = 12000 / (fs/2);
[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');
Run Code Online (Sandbox Code Playgroud)

第7步

%% Filter the signal
fOut = filter(b, a, f);

%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;
Run Code Online (Sandbox Code Playgroud)

您可以使用filter从步骤#6获得的信息来过滤信号. fOut将是你的过滤信号.如果您想听到它播放,您可以audioplayer以与输入相同的采样频率构建并基于此输出信号.然后用p.play它在MATLAB中听到它.

试一试,看看它是如何工作的.你可能需要在第6步和第7步中尽情玩耍.这不是一个完美的解决方案,但足以让你开始我希望.

祝好运!