14

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

wav在下面的链接中有一个文件,其中有人声和背景中的一些噪音。我想消除噪音。有没有人可以告诉我如何在MATLAB中做到这一点?

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

4

1 回答 1

44

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

以下是我执行的步骤:

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

那我们走吧!


步骤1

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

audioread将为您读入一个音频文件。只需在''. 此外,请确保将工作目录设置为存储此文件的位置。 clearvars, close all只是为我们打扫卫生。它关闭我们所有的窗口(如果有的话),并清除我们在 MATLAB 工作区中的所有变量。 f将是读入 MATLAB 的信号,fs而是信号的采样频率。 f这是一个二维矩阵。第一列是左声道,第二列是右声道。通常,音频文件中的通道总数由通过 读取的此矩阵中的总列数表示audioread

第2步

%% Play original file
pOrig = audioplayer(f,fs);
pOrig.play;

此步骤将允许您创建一个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');

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));

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

我们fft用来查看信号的频谱。您可以fft通过将所需的输入信号指定为第一个参数来调用,然后将第二个参数指定为要评估的点数。通常将 FFT 中的点数指定为信号的长度。我通过检查我们的声音矩阵中有多少行来做到这一点。当您绘制频谱时,我只取了一个通道以使事情变得简单,因为另一个通道是相同的。这是第一个输入到fft. 另外,请记住,我除以N因为这是标准化信号的正确方法。但是,因为我们只是想对频域的样子进行快照,所以您实际上并不需要这样做。但是,如果您打算稍后使用它来计算某些东西,那么您肯定需要这样做。

我写了一些额外的代码,因为默认情况下频谱是未居中的。我使用fftshift这样中心映射到 0 Hz,而左侧从 0 到 -24000Hz,而右侧从 0 到 24000 Hz。这就是我直观地看到频谱的方式。您可以将负频率视为以相反方向传播的频率。理想情况下,负频率的频率分布应该等于正频率。当您绘制频谱时,它会告诉您该频率对输出的贡献有多大。这是由信号的幅度定义的。您可以通过使用该abs功能找到这一点。您得到的输出如下所示。

在此处输入图像描述

如果您查看该图,则在低频范围内有很多尖峰。这对应于您的嗡嗡声,而声音可能映射到更高的频率范围,并且没有那么多,因为没有听到太多的声音。

步骤#5

通过反复试验并查看第 5 步,我发现 700 Hz 及以下的所有内容都对应于嗡嗡声,而更高的噪声贡献来自 12000 Hz 及更高。

步骤#6

您可以使用butterSignal Processing Toolbox 中的函数来帮助您设计带通滤波器。但是,如果您没有此工具箱,请参阅此 StackOverflow 帖子,了解如何实现相同目的的用户制作功能。但是,该过滤器的顺序只有 2。假设您有butter可用的功能,您需要弄清楚您想要过滤器的顺序。顺序越高,它会做的工作就越多。我选择n = 7开始。您还需要标准化您的频率,以便 Nyquist 频率映射到 1,而其他所有频率都映射在 0 和 1 之间。一旦你这样做了,你可以butter这样调用:

[b,a] = butter(n, [beginFreq, endFreq], 'bandpass');

bandpass标志表示您想要设计一个带通滤波器,beginFreqendFreq映射到您想要用于带通滤波器的标准化开始和结束频率。在我们的例子中,那是beginFreq = 700 / NyquistendFreq = 12000 / Nyquistb,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');

步骤 #7

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

%% Construct audioplayer object and play
p = audioplayer(fOut, fs);
p.play;

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

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

祝你好运!

于 2014-06-13T01:28:30.657 回答