从wav文件,MATLAB中删除噪音

时间:2014-06-12 22:50:41

标签: matlab audio signal-processing wav noise-reduction

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

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

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

1 个答案:

答案 0 :(得分:39)

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

以下是我采取的步骤:

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


    第1步

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

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

    步骤#2

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

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

    步骤#3

    pOrig.play

    stem是一种在MATLAB中绘制离散点的方法。每个时间点都有一个圆绘制的点,从水平轴到该时间点绘制一条垂直线。 subplot是一种在同一窗口中放置多个数字的方法。我在这里没有进入,但您可以通过引用this StackOverflow post I wrote here来详细了解%% 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'); 的工作原理。上面的代码生成如下所示的图:

    signals

    以上代码非常简单。我只是在每个子图中单独绘制每个通道。

    步骤#4

    subplot

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

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

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

    enter image description here

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

    步骤#5

    通过反复试验并查看步骤#5,我发现从700赫兹到下的所有内容都对应于嗡嗡声,而噪声贡献则高于12000赫兹以上。

    步骤#6

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

    butter

    [b,a] = butter(n, [beginFreq, endFreq], 'bandpass'); 标志表示您要设计带通滤波器,bandpassbeginFreq映射到您想要用于带通滤波器的标准化开始和结束频率。就我们而言,那是endFreqbeginFreq = 700 / NyquistendFreq = 12000 / Nyquist是用于过滤器的系数,可帮助您执行此任务。你下一步就需要这些。

    b,a

    步骤#7

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

    您使用filter使用从步骤#6获得的信息来过滤信号。 %% Filter the signal fOut = filter(b, a, f); %% Construct audioplayer object and play p = audioplayer(fOut, fs); p.play; 将是您的过滤信号。如果你想听它播放,你可以根据输出信号以与输入相同的采样频率构造和fOut。然后使用audioplayer在MATLAB中听到它。

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

    祝你好运!