基于Mask的音频降噪

使用python音频信号进行降噪 本文系转在,原文地址请点击 此算法基于(但不是完全重现)Audacity概述的一种降噪效果的算法(链接到C ++代码) 该算法需要两个输入: 包含音频片段原型噪声的噪声音频片段 包含要删除的信号和噪声的信号音频片段 算法步骤 在噪声音频片段上计算FFT 统计信息是通过噪声的FFT计算得出的(频率) 基于噪声的统计信息(和算法的期望灵敏度)计算阈值 通过信号计算FFT 通过将信... 阅读详情

基于Mask的音频降噪

参考代码:Noise reduction using spectral gating in python

算法步骤:

  • 对音频信号进行FFT得到语谱图
  • 用Mask算法对语谱图像素进行降噪处理
  • 进行IFT得到恢复的音频信号

语谱图
音频信号语谱图
选取一个音频信号进行分析和处理,可以看到音频信号的语谱图上有很多白色或接近白色的像素。白色像素表示信号的平均功率或其他统计特性的值为0或者接近0.一般在加性高斯白噪声的情况下,白色像素代表的区域是噪声。

滤波器
音频信号频谱图
如频谱图所示,信号在8kHz处有一个需要被去除的噪声,可以使用一个低通滤波器进行滤波,不影响其他频谱,衰减8kHz处的频谱,得到以下频谱图。
音频信号频谱图
同理,我们如果要通过语谱图达到降噪效果,需要做的就是不影响彩色的有效信号像素,衰减白色或接近白色的噪声像素。就像滤波器把频谱图低频信号保留,抠出高频噪声扔掉,语谱图则是保留彩色像素,抠出浅色像素扔掉。像是一个二维滤波器。

Mask
Mask是图像处理里比较常用的一种抠图算法。简要原理如下图所示(图片有参考)。
Mask原理简述

  • 0:Mask
  • 1:Copy
    可见当mask bitmap区域是0的时候,原图相应区域被操作成为0;mask bitmap区域是1的时候,原图相应区域原封不动被复制。
    达到的效果也就是抠出了原图相应mask bitmap取值1的那些区域。
    *在音频处理中,mask由信号FFT和阈值比较得到。阈值由信号的统计特性和算法所期望的灵敏度决定。如下图所示,是该音频信号的阈值分析。
    mask阈值

平滑处理
如图所示,用于平滑处理mask的滤波器。
平滑处理滤波器
音频降噪的mask的值不只是0和1,通过平滑处理之后取值范围在[0,1]区间。这样恢复的音频更流畅。
应用mask

信号恢复
通过原来的语谱图和mask bitmap做运算得到masked map如图所示。可见相比于原来的语谱图,大量浅色像素被掩蔽。
masked signal
经过恢复得到恢复后信号语谱图。
恢复信号语谱图
做逆运算即可得到信号的时域情况,对比如下。
1.原始音频
原始音频-时域
2.加噪声后音频
加噪声后音频-时域
3.降噪恢复音频
降噪恢复音频-时域
经过播放.WAV文件,加噪信号有明显的噪声干扰,降噪信号几乎没有噪声,恢复效果良好。对于加性噪声,mask降噪具有很不错的效果。

完整代码如下(Google colab):

import IPython
import matplotlib
from prompt_toolkit import output
from scipy.io import wavfile
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
import librosa
from IPython.display import Audio, display
from scipy.fftpack import fft
from google.colab import files

samplerate, data = wavfile.read('audio1.wav') #audio1 is 3sec.
rate = samplerate
original_data = data
data_array_size = len(data)
duration = len(data)/samplerate
time = np.arange(0,duration,1/samplerate) #time vector
plt.plot(time,data)
plt.xlabel('Time(s)')
plt.ylabel('Amplitude')
plt.title('audio1.wav')
plt.show()

frequency = np.linspace(0.0,samplerate/2,int(data_array_size/2))
freq_data = fft(data)
y = 2/data_array_size * np.abs(freq_data[0:int(data_array_size/2)])
plt.plot(frequency, y)
plt.title('Frequency domain Signal')
plt.xlabel('Frequency in Hz')
plt.ylabel('Amplitude')
plt.show()

data = data / 32768

def fftnoise(f):
    f = np.array(f, dtype="complex")
    Np = (len(f) - 1) // 2
    phases = np.random.rand(Np) * 2 * np.pi
    phases = np.cos(phases) + 1j * np.sin(phases)
    f[1: Np + 1] *= phases
    f[-1: -1 - Np: -1] = np.conj(f[1: Np + 1])
    return np.fft.ifft(f).real


def band_limited_noise(min_freq, max_freq, samples=1024, samplerate=1):
    freqs = np.abs(np.fft.fftfreq(samples, 1 / samplerate))
    f = np.zeros(samples)
    f[np.logical_and(freqs >= min_freq, freqs <= max_freq)] = 1
    return fftnoise(f)

IPython.display.Audio(data=data, rate=rate)

# 绘制时域波形图
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(data)
plt.show()

#加噪声
noise_len = 2 #秒
noise = band_limited_noise(min_freq=4000, max_freq = 12000, samples=len(data), samplerate=rate)*10
noise_clip = noise[:rate*noise_len]
audio_clip_band_limited = data+noise

#绘制时域波形图
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(audio_clip_band_limited)
IPython.display.Audio(data=audio_clip_band_limited, rate=rate)
#降噪
import time
from datetime import timedelta as td


def _stft(y, n_fft, hop_length, win_length):
    return librosa.stft(y=y, n_fft=n_fft, hop_length=hop_length, win_length=win_length)


def _istft(y, hop_length, win_length):
    return librosa.istft(y, hop_length, win_length)


def _amp_to_db(x):
    return librosa.core.amplitude_to_db(x, ref=1.0, amin=1e-20, top_db=80.0)


def _db_to_amp(x, ):
    return librosa.core.db_to_amplitude(x, ref=1.0)


def plot_spectrogram(signal, title):
    fig, ax = plt.subplots(figsize=(20, 4))
    cax = ax.matshow(
        signal,
        origin="lower",
        aspect="auto",
        cmap=plt.cm.seismic,
        vmin=-1 * np.max(np.abs(signal)),
        vmax=np.max(np.abs(signal)),
    )
    fig.colorbar(cax)
    ax.set_title(title)
    plt.tight_layout()
    plt.show()


def plot_statistics_and_filter(
        mean_freq_noise, std_freq_noise, noise_thresh, smoothing_filter
):
    fig, ax = plt.subplots(ncols=2, figsize=(20, 4))
    plt_mean, = ax[0].plot(mean_freq_noise, label="Mean power of noise")
    plt_std, = ax[0].plot(std_freq_noise, label="Std. power of noise")
    plt_std, = ax[0].plot(noise_thresh, label="Noise threshold (by frequency)")
    ax[0].set_title("Threshold for mask")
    ax[0].legend()
    cax = ax[1].matshow(smoothing_filter, origin="lower")
    fig.colorbar(cax)
    ax[1].set_title("Filter for smoothing Mask")
    plt.show()


def removeNoise(
        audio_clip,
        noise_clip,
        n_grad_freq=2,
        n_grad_time=4,
        n_fft=2048,
        win_length=2048,
        hop_length=512,
        n_std_thresh=1.5,
        prop_decrease=1.0,
        verbose=False,
        visual=False,
):

    if verbose:
        start = time.time()
    # 噪声的STFT
    noise_stft = _stft(noise_clip, n_fft, hop_length, win_length)
    noise_stft_db = _amp_to_db(np.abs(noise_stft))  # convert to dB
    # Calculate statistics over noise
    mean_freq_noise = np.mean(noise_stft_db, axis=1)
    std_freq_noise = np.std(noise_stft_db, axis=1)
    noise_thresh = mean_freq_noise + std_freq_noise * n_std_thresh
    if verbose:
        print("STFT on noise:", td(seconds=time.time() - start))
        start = time.time()
    # 信号的STFT
    if verbose:
        start = time.time()
    sig_stft = _stft(audio_clip, n_fft, hop_length, win_length)
    sig_stft_db = _amp_to_db(np.abs(sig_stft))
    if verbose:
        print("STFT on signal:", td(seconds=time.time() - start))
        start = time.time()
    # 计算掩码
    mask_gain_dB = np.min(_amp_to_db(np.abs(sig_stft)))
    print(noise_thresh, mask_gain_dB)
    # Create a smoothing filter for the mask in time and frequency
    smoothing_filter = np.outer(
        np.concatenate(
            [
                np.linspace(0, 1, n_grad_freq + 1, endpoint=False),
                np.linspace(1, 0, n_grad_freq + 2),
            ]
        )[1:-1],
        np.concatenate(
            [
                np.linspace(0, 1, n_grad_time + 1, endpoint=False),
                np.linspace(1, 0, n_grad_time + 2),
            ]
        )[1:-1],
    )
    smoothing_filter = smoothing_filter / np.sum(smoothing_filter)
    # 计算阈值
    db_thresh = np.repeat(
        np.reshape(noise_thresh, [1, len(mean_freq_noise)]),
        np.shape(sig_stft_db)[1],
        axis=0,
    ).T
    # 阈值比较确定掩码
    sig_mask = sig_stft_db < db_thresh
    if verbose:
        print("Masking:", td(seconds=time.time() - start))
        start = time.time()
    # 平滑处理
    sig_mask = scipy.signal.fftconvolve(sig_mask, smoothing_filter, mode="same")
    sig_mask = sig_mask * prop_decrease
    if verbose:
        print("Mask convolution:", td(seconds=time.time() - start))
        start = time.time()
    # 在信号上应用掩码
    sig_stft_db_masked = (
            sig_stft_db * (1 - sig_mask)
            + np.ones(np.shape(mask_gain_dB)) * mask_gain_dB * sig_mask
    )
    sig_imag_masked = np.imag(sig_stft) * (1 - sig_mask)
    sig_stft_amp = (_db_to_amp(sig_stft_db_masked) * np.sign(sig_stft)) + (
            1j * sig_imag_masked
    )
    if verbose:
        print("Mask application:", td(seconds=time.time() - start))
        start = time.time()
    # 恢复信号
    recovered_signal = _istft(sig_stft_amp, hop_length, win_length)
    recovered_spec = _amp_to_db(
        np.abs(_stft(recovered_signal, n_fft, hop_length, win_length))
    )
    if verbose:
        print("Signal recovery:", td(seconds=time.time() - start))
    if visual:
        plot_spectrogram(noise_stft_db, title="Noise")
    if visual:
        plot_statistics_and_filter(
            mean_freq_noise, std_freq_noise, noise_thresh, smoothing_filter
        )
    if visual:
        plot_spectrogram(sig_stft_db, title="Signal")
    if visual:
        plot_spectrogram(sig_mask, title="Mask applied")
    if visual:
        plot_spectrogram(sig_stft_db_masked, title="Masked signal")
    if visual:
        plot_spectrogram(recovered_spec, title="Recovered spectrogram")
    return recovered_signal


output = removeNoise(audio_clip=audio_clip_band_limited, noise_clip=noise_clip,verbose=True, visual=True)

#绘制时域波形图
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 4))
plt.plot(output, color='black')
ax.set_xlim((0, len(output)))
plt.show()

original_data = audio_clip_band_limited * 32768
new_original_data = original_data.astype(np.int16)
filtered_data = output * 32768
new_filtered_data = filtered_data.astype(np.int16)
# 播放音频
wavfile.write('original_audio1_with_noise.wav', samplerate, new_original_data)
display(Audio('original_audio1_with_noise.wav', autoplay=True))
files.download('original_audio1_with_noise.wav')
wavfile.write('filtered_audio1.wav', samplerate, new_filtered_data)
display(Audio('filtered_audio1.wav', autoplay=True))
files.download('filtered_audio1.wav')
基于工业音频降噪算法 本文主要是介绍工业音频的数据处理方式,跟语音的处理方式有些许的不同。工业上常见的噪声包括但不限于一下:设备报警声音、人声、排风扇声、杂物托运和设备检修等等,当我们采集目标音频时,这些都会噪声都会成为一定的干扰,对工业上监控设备运行状态、产品质量具有很大的挑战。文献上对工业音频异常分析相对较少,因此,本文针对以上问题,先简单介绍一下一个比较实用的音频降噪算法。 阅读详情

相关推荐

潜入浅出--通信中的频带利用率,以MASK.MPSK作为例子

潜入浅出--通信中的频带利用率,以MASK.MPSK作为例子

whereisqiqi的博客 1万+

5G NR TDD系统中的频谱掩码(Spectrum Mask)分析与优化

在无线通信系统中,频谱掩码(Spectrum Mask)用于描述系统信号在不同频率偏移下的允许功率水平。它帮助确保设备发射信号不会对相邻频谱造成过度干扰,特别是在高频带宽和大数据传输速率的环境下。频谱掩码的要求随着带宽的增加和频率的变化而变化,精确的频谱掩码能够确保通信系统的稳定性和频谱资源的有效使用。以下是针对的频谱掩码要求的详细分析,包括偏移频率与对应的允许功率值。

weixin_43199439的博客 395

基于Mask语音分离

目录 1. 时频掩蔽 2. 语音分离 ​Mask这个单词有的地方翻译成掩蔽有的地方翻译成掩膜,我个人倾向于掩蔽这个翻译,本文就用掩蔽来作为Mask的翻译。 1. 时频掩蔽 我们都知道语音信号可以通过时域波形或者频域的各种频谱来表示,此外语谱图可以同时展示时域和频域的信息,因此被广泛应用,如下图所示。 现在我们假设有两段语音信号,一段是音乐信号,另一段是噪声,它们混合在一起了,时域波形和对应的语谱图分别如下图所示: 如果我们想将音乐信号从混合信号中抽离(这个过程叫语音分离..

学如不及,犹恐失之 1万+

数字频带传输——多进制数字调制及MATLAB仿真

数字频带信号通常也称为数字调制信号,其信号频谱通常是带通型的,适合于在带通型信道中传输。数字调制是将基带数字信号变换成适合带通型信道传输的一种信号处理方式,正如模拟通信中的一样,可以通过对基带信号的频谱搬移来适应信道特性,也到同样的目的可以采用频率调制、相位调制的方式来达到同样的目的。本文将主要通过 Matlab 来学习多进制的调制解调方式,包括 QPSK、OQPSK,并分析和仿真这些调制系统在 AWGN 信道下的性能。

明天你好的博客 2208

什么是图像中的掩膜(Mask),如何使用掩码

图像中的掩膜(Mask)是什么_bitcarmanlee的博客-CSDN博客_掩膜

Turn life into a dream, and then turn dreams into reality 3万+

深入浅出:频谱掩码 Spectral Masking —— 噪音消除利器

语音处理领域,噪声是一个常见的敌人。无论是语音通话、语音识别,还是语音合成,噪声都会大大降低语音的质量和可理解性。它最初是为图像分割设计的,但由于其强大的特征提取能力,很快被引入到语音处理领域。Spectral Masking 是一种非常强大的语音增强技术,它通过从带噪信号的频谱中估计掩码,从而分离出干净语音。因为 UNet 的编码器-解码器结构可以有效地提取和恢复频谱的细节信息,而跳跃连接则帮助保留低频特征,确保生成的掩码更加准确。的任务是通过神经网络,从带噪语音的幅度谱中估计出一个掩码。

qq_38961840的博客 1895

直播场景音频降噪,传统算法 VS AI 算法对比和实践

将幅度谱信息经 Noise Estimator(噪音估计模块)对噪音进行估计,然后经过 Gain Estimator 进行最终 Gain 值计算,将含噪语音的幅度谱与 Gain 值相乘得到最终的增强语音幅度谱,再将其与含噪语音的相位谱结合,进行 iSTFT,从而得到增强语音。这样做的原因是,Mask 不能完全反映语音与原始语音的拟合程度,同样的 Loss 情况下,Mask 有多种可能性,基于不同 Mask 得到的语音也不是唯一的,因此用语音作为 Loss 的计算会更加贴合真实目标。

梅逊雪——记录科学研究 1102

FRCRN语音降噪工具入门指南:理解模型输出CIRM掩码的实际意义

本文介绍了如何在星图GPU平台上自动化部署FRCRN 语音降噪工具 (单麦-16k)镜像,实现高效语音降噪处理。该工具采用CIRM掩码技术,特别适用于会议录音、客服通话等场景,能有效消除背景噪声,提升语音清晰度。通过星图GPU平台,用户可快速搭建专业级语音处理环境,优化音频质量。

weixin_42594427的博客 434

深度解析 noisereduce:开源音频降噪库实践

是一个基于 Python 的开源音频降噪库,专注于为科研、工程和日常应用提供简单高效的噪声抑制工具。该项目由 Tim Sainburg 维护,核心算法基于频谱减法(Spectral Gating),无需深度学习或复杂训练,适合快速集成到音频处理、语音识别、播客后期、科学实验等多种场景。零门槛:无需训练,直接调用即可降噪兼容性强:支持 numpy 数组、wav 文件等多种输入可调节参数丰富,适应不同噪声环境支持单通道和多通道音频Python 实现,依赖少,易于集成。

kakaZhui的博客 1015

音频降噪技术:从原理到工具的完整指南(scipy librosa noisereduce soundfile pedalboard)

音频降噪:从原理到实践 本文系统讲解了音频降噪的技术原理和实现方法。首先揭示了降噪的本质是将声音从时域转换到频域,通过傅里叶变换识别和分离噪声特征。核心在于区分噪声(如稳定的空调声)和人声(300-3000Hz变化频率)的频谱特征。文章提出了降噪的"不可能三角":降噪强度、音质保留和计算效率三者不可兼得,需要根据场景权衡。详细介绍了稳态和非稳态两种降噪策略,以及关键参数设置技巧。

开源AI 专属 UI——papyrai-ui。《千界明彻录》(故事形式构建元思维)——胡说小说。更多思辨内容在公众号。 1566

PyTorch-CUDA镜像实现音频降噪增强

本文介绍如何利用PyTorch与CUDA加速音频降噪模型的训练与部署,通过容器化镜像实现高效、可移植的AI音频处理流程,涵盖技术栈解析、代码实现、性能优化及生产部署要点。

weixin_29859471的博客 444

深度学习音频降噪

降噪,或者语音增强,经过近50年的研究发展,涌现出了很多优秀的降噪算法,从最简单的谱减法,到维纳滤波,再到子空间的方法以及基于统计模型的MMSE估计器,然而传统信号处理的降噪算法在imcra-omlsa出现之后发就展趋于平缓。值得注意的是,如果单独使用SI-SDR,可能会导致模型估计输出与输入之间的幅值不稳定,并且如果训练数据中存在0值时,单独使用SISDR时会出现问题,公式计算不稳定,SNR的值都会爆炸,所以一般会结合一定尺度的MSE loss一起使用。,这一期我们介绍下AI降噪的一些损失函数。

chumingqian的博客 2203

数字图像处理第四次作业——空域滤波与边缘检测

学习冈萨雷斯《数字图像处理》第四次作业。本次作业主要是对灰度图像的空域滤波和边缘检测。包括中值滤波、高斯滤波、Unsharp Masking、Sobel边缘检测、Laplacian边缘检测、Canny边缘检测算法

虚宇宸轩 3615

通信中的频谱效率:以MASK.MPSK为例

MASK.MPSK(Maximum Average Signal-to-Noise Ratio MPSK)是一种调制方式,它通过在调制过程中优化信号到噪声比(SNR)来提高频谱效率。本文将以MASK.MPSK作为例子,详细介绍频谱效率的概念以及如何利用调制方式来提高频谱效率。频谱效率是指在给定的频谱带宽内,传输的比特数或符号数的数量。频谱效率越高,表示在有限的频谱资源下传输更多的信息量。此外,还可以采用其他调制方式和调制技术来进一步提高频谱效率,如正交频分复用(OFDM)、多载波调制(MCM)等。

ReElixir的博客 805

深度回声消除模型中,Mask 的设置

在深度学习的音频信号处理领域,回声消除是一个重要的研究方向。回声消除模型的性能在很大程度上依赖于输入信号的特性以及掩码(mask)的设计。本文将介绍深度回声消除模型中的各种信号、训练和推理过程中的信号与掩码的关系,以及引入额外掩码的好处。在深度回声消除模型中,主要涉及以下几种信号:麦克风信号 ():这是模型的输入信号,包含了目标语音、背景噪声和回声。麦克风信号是我们希望处理的主要信号。远端信号 ():这是来自远端的信号,通常是清晰的语音信号。远端信号用于生成回声,帮助模型学习如何去除回声成分。目标语音 ()

AI 音频小牛的博客 1249

详细解析RNNoise:基于深度学习的语音噪声抑制技术

RNNoise(Recurrent Neural Network for Noise Suppression)是一种基于递归神经网络(RNN)和深度学习技术的语音噪声抑制算法。其主要目标是通过学习语音信号中的噪声特征,基于输入的噪声信号来生成干净的语音信号。与传统的基于谱减法(Spectral Subtraction)或维纳滤波(Wiener Filter)等方法的噪声抑制技术不同,RNNoise不依赖于手工特征,而是通过训练神经网络来自动提取和去除噪声。

weixin_52734695的博客 5518

训练语音降噪模型的一些感想

当前基于深度学习的语音降噪方法主要分为两个类: 基于TF时频域的方法 (有两大类:基于mask和非基于mask的方法) 基于时域的方法,就我自己的实验结果来说,基于时域的方法比基于TFmask的方法要差一些,可能这样方法的trick更多一些吧。 基于时频域方法中的基于mask的方法更常见一些,主要的是对语音提取频域特征,通过计算干净音频和对应的加噪音频的频域特征计算一个频域的mas...

哈哈哈博客 1671
下一篇: 实操BPSK载波调制解调笔记(matlab)
雷香回
博客等级 码龄6年 6粉丝 2原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值