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

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. FFTspectrum = 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. IFFTreconstructed_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 * windowspectrum = 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.rhkb.cn/news/442689.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Git生成SSH密钥教程(附Git常用命令)

一、为什么使用SSH? 使用 Git 的 SSH(安全外壳协议)主要有以下几个原因:1. 安全性:SSH 是一种加密的网络协议,用于在网络中安全地运行网络服务。使用 SSH,所有传输的数据都会被加密&#xff0c…

Mysql高级篇(下)——数据库备份与恢复

Mysql高级篇(下)——数据库备份与恢复 一、物理备份与逻辑备份1、物理备份2、逻辑备份3、对比4、总结 二、mysqldump实现逻辑备份1、mysqldump 常用选项2、mysqldump 逻辑备份语法(1)备份一个数据库(2)备份…

微服务架构---认识Zuul

目录 认识Zuul简单的例子 第一个Zuul程序步骤1:创建父工程zuul-1步骤2:创建HystrixController类步骤3:搭建服务消费者eureka-consumer项目(1)创建一个config包,在config包下新建配置类RestConfig&#xff0…

HCIP-HarmonyOS Application Developer 习题(八)

(填空)1、声明式开发范式中使用装饰器( )装饰的结构体具有组件化能力,能够成为一个自定义组件。 答案:component 分析:component 装饰的struct表示该结构体具有组件化能力,能够成为一个独立的组件&#xff…

基于springboot的篮球竞赛预约平台

作者:计算机搬砖家 开发技术:SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:Java精选实战项…

【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则

文章目录 C 继承详解:初阶理解与实战应用前言第一章:继承的基本概念与定义1.1 继承的概念1.2 继承的定义 第二章:继承中的访问权限2.1 基类成员在派生类中的访问权限2.2 基类与派生类对象的赋值转换2.2.1 派生类对象赋值给基类对象2.2.2 基类…

OkHttp

OkHttp是一个用于Android和Java应用的高效HTTP客户端库。它具有以下优点: 优点 高效连接池: 支持连接复用(Connection Pooling)减少延迟。有效管理HTTP/2多路复用。 透明压缩: 自动处理Gzip压缩,减少传输…

Label Studio 半自动化标注

引言 Label Studio ML 后端是一个 SDK,用于包装您的机器学习代码并将其转换为 Web 服务器。Web 服务器可以连接到正在运行的 Label Studio 实例,以自动执行标记任务。我们提供了一个示例模型库,您可以在自己的工作流程中使用这些模型,也可以根据需要进行扩展和自定义。 1…

dotnet7==windows ZIP方式安装和web demo和打包

下载ZIP Download .NET 7.0 (Linux, macOS, and Windows) 解压 创建项目 mkdir MyWebApp cd MyWebApp "C:\Users\90816\Downloads\dotnet-sdk-7.0.317-win-x64\dotnet.exe" new webapp -n MyWebApp 运行项目 "C:\Users\90816\Downloads\dotnet-sdk-7.0.317-…

k8s的简介和部署

一、k8s简介 在部署应用程序的方式上面,主要经历了三个阶段: 传统部署:互联网早期,会直接将应用程序部署在物理机上优点:简单,不需要其它技术的参与缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源&…

Docker 实践与应用举例

Docker 实践与应用举例 Docker 已经成为现代软件开发和部署中的重要工具,通过容器化技术,开发者可以轻松管理应用的依赖环境、简化部署流程,并实现跨平台兼容性。本篇博客将详细介绍 Docker 的基本概念、实践操作以及应用场景,帮…

【软件部署安装】OpenOffice转换PDF字体乱码

现象与原因分析 执行fc-list查看系统字体 经分析发现,linux默认不带中文字体,因此打开我们本地的windows系统的TTF、TTC字体安装到centos机器上。 安装字体 将Windows的路径: C:\Windows\Fonts 的中文字体,如扩展名为 TTC 与TT…

shell脚本写代码

用简单的test语句来判断是否闰年 #! /bin/bash read -p "sd " yearif [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]thenecho "是润年"elseecho "不是闰年" fi判断一个数是否为偶数 #! /bin/bash read -p "…

LINUX——内核移植、内核编译教程

Linux内核编译是一个将内核源代码转换成可在特定硬件架构上运行的二进制文件的过程。以下是编译Linux内核的一般步骤: 1、准备工作: 确保安装了必要的编译工具,如gcc、make、ncurses库(用于make menuconfig)等。 2、…

数据结构-八大排序之堆排序

堆排序 1.1 基础知识 原理: 1. 利用完全二叉树构建大顶堆 2. 堆顶元素和堆底元素进行交换,除堆底元素之外其余元素继续构建大顶堆 3. 重复2,直到所有元素都不参与构建 整个数组排序完成 完全二叉树: 数据从上到下&#x…

雷池+frp 批量设置proxy_protocol实现真实IP透传

需求 内网部署safeline,通过frp让外网访问内部web网站服务,让safeline记录真实外网攻击IP safeline 跟 frp都部署在同一台服务器:192.168.2.103 frp client 配置 frpc只需要在https上添加transport.proxyProtocolVersion "v2"即…

基于SpringBoot的设备管理系统源码带本地搭建教程

技术框架:SpringBoot mybatis thymeleaf Mysql5.7 Fastjson Druid Shiro 运行环境:jdk8 IntelliJ IDEA maven 宝塔面板 系统功能:登陆,注册,系统用户管理,角色,部门管理,…

软件测试之压力测试

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 压力测试 压力测试是一种软件测试,用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&…

《恋与深空》陷抄袭争议,但不影响它登顶App Store畅销总榜

伴随着《恋与深空》全新混池而来的,是文案疑似抄袭的负面新闻。 9月23日,《恋与深空》上线了第一个国风混池“欲揽旖旎色”,但比玩家的夸奖与反馈更先来的,是男主角之一秦彻的剧情文案抄袭的争议,#恋与深空 抄袭#火速…

渗透测试入门学习——使用python脚本自动跟踪csrf_token实现对网站登录界面的暴力破解

目录 写在前面 使用方法 相关代码 写在前面 最近在学习使用Burp Suite时发现其intruder模块无法实现多种模式的混合使用,就如想要暴力破解账号和口令两个区域并同时跟踪网页的csrf_token时BP似乎不能很方便的实现这一功能,于是自己在练习时就想到了用…