[简单实践]Noisy Print - 自制基于加性噪声模型的简易降噪器

news2024/12/23 5:51:08

NoisyPrint

最近在学习的过程中,突然想起一个在Adobe Audition中用过的功能。

为什么会想到这个功能呢,因为在我使用DeepFilter的过程中,我发现对于一些低信噪比的信号来说,DeepFilter很容易出现过拟合现象,导致音源的过度失真。那么有没有什么好办法解决这个问题呢?答案当然是有的,就是这个采样部分噪音,然后在频域上进行相减的方法。

项目地址,持续更新欢迎Star Github : LeventureQys/NoisyPrint

原理

1. 加性噪声模型

在信号处理领域,含噪声的信号通常可以被建模为:

x ( t ) = s ( t ) + n ( t ) x(t) = s(t) + n(t) x(t)=s(t)+n(t)

  • x(t):观测到的含噪声信号
  • s(t):原始干净信号
  • n(t):噪声信号

这个模型假设噪声是加性的,并且与原始信号不相关。

2. 频域中的表示

通过短时傅里叶变换(STFT),将时域信号转换到频域:

X ( ω ) = S ( ω ) + N ( ω ) X(\omega) = S(\omega) + N(\omega) X(ω)=S(ω)+N(ω)

  • X ( ω ) X(\omega) X(ω):含噪声信号的频谱
  • S ( ω ) S(\omega) S(ω): 原始信号的频谱
  • N ( ω ) N(\omega) N(ω): 噪声信号的频谱

这意味着在频域中,信号的频谱是线性叠加的。

综上

我们可以直接反过来计算,得到我们的 S ( ω ) S(\omega) S(ω) 然后在进行反傅里叶变换,获得时域信息。

总结流程:

  • 1.采集噪声样本并建立噪声频谱模型
  • 2.将含噪声的音频信号分帧处理
  • 3.对每一帧进行窗函数处理
  • 4.对窗化后的帧进行快速傅里叶变换(FFT)
  • 5.从信号的频谱中减去噪声频谱
  • 6.处理频谱减法后的负值和伪影
  • 7.进行逆快速傅里叶变换(IFFT)重建时域信号
  • 8.通过重叠相加(Overlap-Add)方法重建完整的信号
  • 9.后处理,如频谱平滑

实操:

1.采集噪声样本并建立噪声频谱模型

这一段我直接使用Audition进行的,具体不表,总之是两段音频,分别是全音频和纯噪音

原始音频:

纯噪音:

可以看得到,这音频中明显是有比较强烈的噪音的。

2. 3. 4.

这部分暂且不表,详情见下方代码:

import numpy as np
import scipy.io.wavfile as wav
import matplotlib.pyplot as plt
from scipy.signal import get_window
from scipy.fftpack import fft, ifft

# 1. 读取纯噪声信号,建立噪声频谱模型
noise_rate, noise_data = wav.read('./AudioSource/Noisy.wav')
# 如果噪声是立体声,转换为单声道
if len(noise_data.shape) > 1:
    noise_data = noise_data.mean(axis=1)

# 计算噪声频谱模型
frame_size = 1024
overlap = 512
noise_frames = []
for i in range(0, len(noise_data) - frame_size, overlap):
    frame = noise_data[i:i+frame_size]
    windowed_frame = frame * get_window('hamming', frame_size)
    spectrum = fft(windowed_frame)
    noise_frames.append(np.abs(spectrum))
# 计算平均噪声频谱
noise_spectrum = np.mean(noise_frames, axis=0)

# 2. 读取需要降噪的音频信号
rate, data = wav.read('./AudioSource/Source.wav')
if len(data.shape) > 1:
    data = data.mean(axis=1)

# 保存降噪前的频谱,用于后续对比
original_spectrum = []

# 进行降噪处理
output_data = np.zeros(len(data))
window = get_window('hamming', frame_size)
for i in range(0, len(data) - frame_size, overlap):
    # 2. 分帧
    frame = data[i:i+frame_size]
    # 3. 窗函数处理
    windowed_frame = frame * window
    # 4. FFT
    spectrum = fft(windowed_frame)
    # 保存原始频谱
    original_spectrum.append(np.abs(spectrum))

    # 5. 频谱减法
    magnitude = np.abs(spectrum)
    phase = np.angle(spectrum)
    subtracted_magnitude = magnitude - noise_spectrum
    # 6. 处理负值和伪影
    subtracted_magnitude = np.maximum(subtracted_magnitude, 0.0)

    # 7. IFFT
    reconstructed_spectrum = subtracted_magnitude * np.exp(1j * phase)
    reconstructed_frame = np.real(ifft(reconstructed_spectrum))
    # 8. Overlap-Add 重建信号
    output_data[i:i+frame_size] += reconstructed_frame * window

# 保存降噪后的频谱,用于对比
denoised_spectrum = []
for i in range(0, len(output_data) - frame_size, overlap):
    frame = output_data[i:i+frame_size]
    windowed_frame = frame * window
    spectrum = fft(windowed_frame)
    denoised_spectrum.append(np.abs(spectrum))

# 9. 后处理(可选,这里暂不实现)

# 保存降噪后的音频
wav.write('./AudioSource/Denosed.wav', rate, output_data.astype(np.int16))

# 绘制频谱对比
# 计算平均频谱
original_spectrum_mean = np.mean(original_spectrum, axis=0)
denoised_spectrum_mean = np.mean(denoised_spectrum, axis=0)
freqs = np.linspace(0, rate, frame_size)

plt.figure(figsize=(12,6))
plt.plot(freqs[:frame_size//2], 20*np.log10(original_spectrum_mean[:frame_size//2]), label='Original')
plt.plot(freqs[:frame_size//2], 20*np.log10(denoised_spectrum_mean[:frame_size//2]), label='Processed')
plt.xlabel('频率 (Hz)')
plt.ylabel('幅度 (dB)')
plt.title('降噪前后频谱对比')
plt.legend()
plt.show()

测试效果

这个库还有很多可以优化的空间,可以参考Audition下的控制面板,可以简单窥见可以优化的空间:

  • 1.优化曲线频域相减对于频域下不同值的曲线增益因子 r \mathcal{r} r在这里是没有考虑的,在实际的使用中是可以进行考虑的。

  • 2.这里是直接简单粗暴的直接减掉了所有的频域内容,实际上可以不那么生硬地进行剪辑。

  • 3.可以使用小范围的 FFT来进行实时性音频降噪的尝试。

  • 4.进行C++的移植,实际上这些库都有。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2198081.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据毕业设计选题推荐-电影票房数据分析系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇…

Linux云计算 |【第四阶段】RDBMS2-DAY1

主要内容: MySQL主从同步(概述、原理、构建主从同步)、主从同步结构类型(主多从、主从从、主主)、复制模式(异步、半同步)、启用半同步复制 一、MySQL主从同步 MySQL 主从同步(Mas…

工控风云 | 科东软件受邀参加2024 CCF工控“风云论坛”并做演讲

近日,CCF工业控制计算机专委会首届“风云论坛”在苏州CCF业务总部&学术交流中心成功召开。作为国内工业操作系统领军企业,科东软件受邀参加本次大会,并做“鸿道(Intewell)新型工业操作系统”主题演讲。 “要打好科技仪器设备、操作系统…

自动驾驶系列—超声波雷达技术详解:自动驾驶中的短距离感知利器

🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…

知识改变命运 数据结构【优先级队列(堆)】

优先级队列(堆) 1:堆概念2:堆的创建(以小根堆为例)3:堆的插入与删除3.1 堆的插入3.2堆的删除 4:oj练习5:堆排序6接口介绍(底层代码的查看)6.1常用三种构造方法 前言:队列…

Flutter-->Namespace not specified.

更新Android gradle 7.5.0之后, 运行项目会出现Namespace not specified.问题, 这里出一个我的解决方案. 由于很多库都不可能及时更新适配gradle 7.5.0, 所以可以等pub get将子库拉取到本地之后, 在本地手动添加namespace属性,即可解决本文问题. 作为程序猿,那肯定不可能手动修…

Elasticsearch、Kibana学习

系列文章目录 JavaSE基础知识、数据类型学习万年历项目代码逻辑训练习题代码逻辑训练习题方法、数组学习图书管理系统项目面向对象编程:封装、继承、多态学习封装继承多态习题常用类、包装类、异常处理机制学习集合学习IO流、多线程学习仓库管理系统JavaSE项目员工…

鸿蒙--知乎评论

这里我们将采用组件化的思想进行开发 拆解组件 pages下,新建ZhiHu的文件pages下,新建components, 里面新建 HmNavBar和HmCommentItem components/HmNavBar.ets Entry Component struct HmNavBar {title: string 标题build() {Row() {// 返回键Row() {I…

数据湖数据仓库数据集市数据清理以及DataOps

一提到大数据我们就知道是海量数据,但是我们并不了解需要从哪些维度去考虑这些数据的存储。比如 数据湖、数据仓库、数据集市,以及数据自动化应用DataOps有哪些实现方式和实际应用,这篇文章将浅显的做一次介绍。 数据湖 数据湖是一种以自然…

Spring Boot 学习之路 -- Thymeleaf 模板引擎

前言 最近因为业务需要,被拉去研究后端的项目,代码框架基于 Spring Boot,后端对我来说完全小白,需要重新学习研究…出于个人习惯,会以 Blog 文章的方式做一些记录,文章内容基本来源于「 Spring Boot 从入门…

Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式 常用的匹配模式 \d # 匹配任意一个数字 \D # 匹配任意一个非数字 \w # 匹配任意一个单词字符(数字、字母、下划线) \W # 匹配任意一个非单词字符 . # 匹配任意一个字符(除了换行符) [a-z] # 匹配任意一个小写字母 […

获取淘宝直播间弹幕数据的技术探索实践方法

在数字时代,直播已成为电商营销的重要渠道之一,而弹幕作为直播互动的核心元素,蕴含着丰富的用户行为和情感数据。本文将详细介绍如何获取淘宝直播间弹幕数据的技术方法和步骤,同时分析不同工具和方法的优缺点,并提供实…

夜莺监控的机器支持挂载到多个业务组了

夜莺开源项目于国庆前夕发布了 v7.4.1 版本,修复了一些 bug,同时也带来了一些新功能。其中最重要的一个功能是:机器支持挂载到多个业务组了。本文将介绍几个重要的变更。 所有变更点 feat: 左侧栏业务组新设计feat: 机器支持了绑定到多个业…

GAN(Generative Adversarial Nets)

GAN(Generative Adversarial Nets) 引言 GAN由Ian J. Goodfellow等人提出,是Ian J. Goodfellow的代表作之一,他还出版了大家耳熟能详的花书(Deep Learning深度学习),GAN主要的思想是同时训练两个模型,生成…

CentOS 7 安装并部署 Mysql

安装 Mysql 下载并添加库 sudo yum localinstall https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm安装 Mysql 包(一路键入y即可) yum -y install mysql mysql-server --nogpgcheck- -nogpgcheck 作用为 禁掉GPG验证检查 配…

Serilog文档翻译系列(七) - 应用设置、调试和诊断、开发接收器

01应用设置 Serilog 支持在 App.config 和 Web.config 文件中使用简单的 配置语法,以设置最低日志级别、为事件添加额外属性以及控制日志输出。 Serilog 主要通过代码进行配置,设置支持旨在作为补充功能。虽然不是全面的,但大多数日志记录配…

SpringBoot3实战:实现接口签名验证

有时候我们要把自己的服务暴露给第三方去调用,为了防止接口不被授权访问,我们一般采用接口签名的方式去保护接口。 接下来松哥和大家聊一聊这个话题。 一 场景分析 什么时候需要接口签名? 接口签名是一种重要的安全机制,用于确…

Jmeter链接数据库、分布式

目录 一、Jmeter链接数据库 连接准备 有两种添加驱动的方法 第一种: 第二种: 连接方法: 1.先添加一个配置元件中的jdbc connection configuration 2、配置内容 使用: 二、Jmeter做分布式操作 1、准备多台电脑 2、多台电…

顶象生僻字点选模型识别

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 该文章模型已经上线ocr识别网站,欢迎测试!!,地址:http://yxlocr.nat300.top/ocr/textclick/5 某网站使用顶象的生僻字点选模型,部分数据集如下: 这种数据集…

【Vue3 + TS + Vite】从0到1搭建后台管理系统

前言 没搭建过Vue3的项目,从0开始搭建一下,记录一下自己的步骤。 技术栈: vue3 ts scss pinia vite 我尽量写的详细一些,后续也会记录我在项目过程中,遇到的一些问题。 文章目录 前言环境搭建一、创建项目1. 使用…