MATLAB环境下一种音频降噪优化方法—基于时频正则化重叠群收缩

news2024/11/17 5:32:45

语音增强是语音信号处理领域中的一个重大分支,这一分支已经得到国内外学者的广泛研究。当今时代,随着近六十年来的不断发展,己经产生了许多有效的语音增强算法。根据语音增强过程中是否利用语音和噪声的先验信息,语音增强算法一般被归类为两类, 一类是无先验信息的语音增强算法,另外一类则是具有先验信息的语音增强算法。在第一类无先验信息语音增强算法中,比较常用的语音增强算法有谱减算法、基于统计模型的算法、基于信号子空间的算法、维纳滤波算法之类。这些算法对于平稳噪声具有很好的增强效果,但是对于特征很快变化的非平稳噪声,降噪性能经常无法满足需求。与上面的无先验信息语音增强算法相比,有先验信息语音增强算法能够弥补上述的缺点,能够有效的处理于非平稳噪声,达到合适的效果。有先验信息语音增强算法主要有隐马尔科夫模型语音增强算法以及码数驱动的语音增强算法。有先验信息语音增强算法能够通过线下提取语音和噪声的先验信息,然后利用HMM或者码数分别对获取的语音和噪声先验信息进行建模,结合线上语音和噪声的先验HMM 或者码数估计的语音谱和噪声谱,并构建维纳滤波器增强声音中的语音部分。由于利用到了语音和噪声的先验信息,这类算法能够很好地追踪线上语音和噪声特征的变化,实现对非平稳噪声很好的降噪效果。语音增强的主要目包含两个方面:1. 降低含噪语音中的噪音;2 尽量保留甚至增强原语音的质量。

提出一种基于时频正则化重叠群收缩的音频降噪优化方法,该方法使用可分解凸优化问题的预定结构知识对语音信号进行降噪,利用语音谱图观察聚类特性,使用混合范数惩罚项迭代地获得稀疏干净的语音信号。并在重叠群收缩算法基础上,在代价函数中引入时频权值。

% Reading in our audio files
[clean_signal, clean_speech_rate] = audioread("data/speech_files/sp01.wav");
[noise_signal, noise_signal_rate] = audioread("data/noise_files/keyboard_noise.wav");
noise_signal = noise_signal'; clean_signal = clean_signal';

% Ensuring noise signal length matches clean signl length through reptition and cropping
noise_signal = noise_signal(mod(0:length(clean_signal)-1, numel(noise_signal)) + 1);
assert(length(clean_signal) == length(noise_signal));

% Combining to create noisy signal
SNR = -10; % in dB
noisy_signal = clean_signal + (noise_signal / norm(noise_signal) * norm(clean_signal) / 10.0^(0.05*SNR));
% Uncomment the following line following line for using gaussian noise
%noisy_signal = awgn(clean_signal, SNR, "measured");

% Setting this changes what we take the STFT of
yo = noisy_signal;

% Some parameters for our test
noise_type = "impulsive"; % Noise types are impulsive, clean, stationary, used for weighting
lambda = 30; % Higher values when using both T & F weightings
Nit = 6;
K1 = 2;
K2 = 8;
window = sqrt(hann(256, 'periodic')); 
overlap_length = 128;
fft_length = 512;

%% Preprocess Data
% Take STFT
% ensure to use both a cola compliant window and overlap length and k needs to
% be an int in this eq. k = (length(yo) - overlap_length) / (length(window) - overlap_length)
% otherwise we can pad signal to make k an integer and remove padded 0's
% from our output
if (~iscola(window, overlap_length))
    error("COLA noncompliant parameters, imperfect reconstruction");
end
k = (length(yo) - overlap_length) / (length(window) - overlap_length);
if (k ~= floor(k))
    warning("Padding signal to provide sample reconstruction post istft, results may be off for groups that stretch across to these padded zeros");
    padding = ceil(k) * overlap_length + overlap_length - length(noisy_signal);
    yo = [yo zeros(1, padding)];
else
    padding = 0;
end
tf = stft(yo, noise_signal_rate, 'Window', window, 'OverlapLength', overlap_length, 'FFTLength', fft_length);

%% Creating our frequency weighting 
% For noise with varying energy across the bands
if noise_type == "clean" || noise_type == "impulsive" || noise_type == "stationary"
    [N, Fo, Ao, W] = firpmord([4000, 6000]/(noise_signal_rate/2), [1 0.8], [0.01, 0.01]);
    b = firpm(10, Fo, Ao, W);
    [filter_magnitudes, ~] = freqz(b, 1, size(tf, 1));
    filter_magnitudes = abs(filter_magnitudes);
elseif noise_type == "stationary"
    filter_magnitudes = ones(fft_length, 1);
end
frequency_weighting = repmat(filter_magnitudes, [1, size(tf, 2)]);

%% Denoising Signal
% Running algorithm
[tf_denoised, cost, weights, energy_ratios] = tfs(tf, K1, K2, lambda, Nit, frequency_weighting);
denoised_signal = real(istft(tf_denoised, noise_signal_rate, 'Window', window, 'OverlapLength', overlap_length, 'FFTLength', fft_length)');

% Undoing the padding if any was necessary
if (padding ~= 0)
    yo = yo(1:length(yo)-padding);
    denoised_signal = denoised_signal(1:length(denoised_signal)-padding);
end

%% Plots, SNR Readout & Playing Denoised Signal
time = (1:length(denoised_signal))/noise_signal_rate;
figure(1)
clf;
subplot(3,3,1);
hold on;
plot(time, denoised_signal, 'Color', [1, 0, 0, 0.2]);
plot(time, clean_signal, 'Color', [0, 1, 0, 0.05]);
axis tight;
hold off;
title("Clean vs Denoised Signal");
legend("Denoised Signal", "Clean Signal");

subplot(3,3,2);
plot(time, clean_signal - denoised_signal, 'Color', [1, 0, 0, 1]);
axis tight;
title("Delta of Clean vs Denoised");

subplot(3,3,3);
hold on;
plot(time, denoised_signal, 'Color', [1, 0, 0, 0.2]);
plot(time, noisy_signal, 'Color', [0, 1, 0, 0.05]);
axis tight;
hold off;
title("Noisy vs Denoised Signal");
legend("Denoised Signal", "Noisy Signal");

subplot(3,3,4);
plot(cost)
title("Cost Per Iteration");
legend("Cost");

subplot(3, 3, 5);
mesh(mag2db(weights));
c = colorbar;
c.Label.String = "Power/Frequency db/Hz";
shading interp;
view(0, 90);
xlim([0 size(weights, 2)])
ylim([0 size(weights, 1)])
title ("Time & Frequency Attenutation Weighting");

subplot(3, 3, 6);
spectrogram(clean_signal, window, overlap_length, fft_length, noise_signal_rate, 'yaxis');
title("Spectrogram of Clean Signal");

subplot(3, 3, 7);
spectrogram(noisy_signal, window, overlap_length, fft_length, noise_signal_rate, 'yaxis');
title("Spectrogram of Noisy Signal");

subplot(3, 3, 8);
spectrogram(denoised_signal, window, overlap_length, fft_length, noise_signal_rate, 'yaxis');
title("Spectrogram of Denoised Signal");

subplot(3, 3, 9);
spectrogram(clean_signal - denoised_signal, window, overlap_length, fft_length, noise_signal_rate, 'yaxis');
title("Spectrogram of Delta Between Clean & Denoised Signal");

if noise_type ~= "stationary"
    figure(2)
    freqz(b, 1, size(tf, 1));
end

figure(3)
subplot(2, 1, 1);
plot((1:fft_length).*(noise_signal_rate/2)/fft_length, smooth(filter_magnitudes));
xlabel("Frequency Hz");
ylabel("Weight");
title("Frequency Weights")

subplot(2, 1, 2);
plot(energy_ratios);
axis tight;
xlabel("Time");
ylabel("Weight");
title("Time Weights")

% Get the SNR and play the denoised signal
if (sum(clean_signal(:).^2) == 0) || (sum((clean_signal(:)-yo(:)).^2) == 0)
    preSNR = 0;
else
    preSNR = 10*log10(sum(clean_signal(:).^2) / (sum((clean_signal(:)-yo(:)).^2)));
end

if (sum(clean_signal(:).^2) == 0) || (sum((clean_signal(:)-denoised_signal(:)).^2) == 0)
    postSNR = 0;
else
    postSNR = 10*log10(sum(clean_signal(:).^2) / (sum((clean_signal(:)-denoised_signal(:)).^2)));
end
fprintf("SNR Pre-Denoising: %.2f SNR Post-Denoising: %.2f dB\n", preSNR, postSNR);
sound(denoised_signal, noise_signal_rate);

工学博士,担任《Mechanical System and Signal Processing》审稿专家,担任《中国电机工程学报》优秀审稿专家,《控制与决策》,《系统工程与电子技术》,《电力系统保护与控制》,《宇航学报》等EI期刊审稿专家,担任《计算机科学》,《电子器件》 , 《现代制造过程》 ,《电源学报》,《船舶工程》 ,《轴承》 ,《工矿自动化》 ,《重庆理工大学学报》 ,《噪声与振动控制》 ,《机械传动》 ,《机械强度》 ,《机械科学与技术》 ,《机床与液压》,《声学技术》,《应用声学》,《石油机械》,《西安工业大学学报》等中文核心审稿专家。

擅长领域:现代信号处理,机器学习,深度学习,数字孪生,时间序列分析,设备缺陷检测、设备异常检测、设备智能故障诊断与健康管理PHM等。

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

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

相关文章

Linux shell编程学习笔记42:hdparm命令

ChatGPT 和文心一言哪个更好用? 从智能回复、语言准确性、知识库丰富度等方面比较,两大AI助手哪个更胜一筹?快来和我们分享一下你的看法吧~ 0 前言 获取硬盘序列号是信息资产管理和信息安全检测中经常要收集的信息,对于Linux来说…

2.数据结构 顺序表(自留笔记)

文章目录 一.静态顺序表:长度固定二.动态顺序表1.下面证明原地扩容和异地扩容代码如下:2.下面是写一段Print,打印数字看看:3.头插4.尾删5.头删6.越界一定会报错吗7.下标插入8.下标删除9.查找数字10.应用:利用顺序表写一…

云原生 - 微信小程序 COS 对象存储图片缓存强制更新解决方案

问题描述 遇到一个这样的情况:在微信小程序里图片缓存十分麻烦,网上很多说在腾讯云里的 COS 存储对象服务里设置对应的图片缓存(Header 头 Cache-Contorl),说实话真不好用,一会儿生效,一会儿没…

使用宝塔面板部署Node.js+Mysql服务和Vue3-Admin项目到云服务器上

准备工作 一台云服务器,可以先用免费试用一个月的服务器进行练手;我这里选择的是腾讯云的轻量云服务器; 1、在云服务器上安装宝塔面板 宝塔面板官网地址:https://www.kancloud.cn/chudong/bt2017/424209 1.1 安装Xshell脚本工…

SpringCloud Aliba-Seata【下】-从入门到学废【8】

目录 1.数据库创建 1.seata_account库下建表 2.seata_order库下建表 3.seata_storage库下建表 4.在每个库下创建回滚日志 2.创建订单模块 2.1建工程 2.2加pom 2.3改yml 2.4file.conf 2.5registry.conf 2.6domain 2.7Dao 2.8Service 2.9controller 2.10confi…

cidp环境启动步骤及注意事项

1、导入项目 选择file——》import…——》Generate——》Exiting Projects into Workspace——》选择要导入的项目 2、添加tomcat 1)点击Serves——》No servers are available. Click this link to create a new server… 2)点击“Add…” 3&…

阿里巴巴Java开发手册(详尽版)

点击下载 阿里巴巴Java开发手册

C++输入输出流

输入/输出流类:iostream---------i input(输入) o output(输出) stream:流 iostream: istream类:输入流类-------------cin:输入流类的对象 ostre…

【java面试】常见问题(超详细)

目录 一、java常见问题JDK和JRE的区别是什么?Java中的String类是可变的还是不可变的?Java中的equals方法和hashCode方法有什么关系?Java中什么是重载【Overloading】?什么是覆盖【Overriding】?它们有什么区别&#xf…

React进阶 - 14(说一说”虚拟DOM“中的”Diff算法“)

本章内容 目录 一、了解 Diff 算法二、key 值的重要性三、为什么不建议使用 index 做 key 值 上一节我们初步了解了 React中的”虚拟 DOM“ ,本节我们来说一说”虚拟DOM“中的”Diff算法“ 一、了解 Diff 算法 在上一篇中,我们有讲到:当 st…

【Computer Networks】FDM、TDM、WDM、CDM

目录 FDM TDM ​WDM CDM FDM TDM WDM CDM

C语言每日一题(47)两数相加II

力扣 445 两数相加II 题目描述 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 示例1: 输入&#xff…

Java如何对OSS存储引擎的Bucket进行创建【OSS学习】

在前面学会了如何开通OSS,对OSS的一些基本操作,接下来记录一下如何通过Java代码通过SDK对OSS存储引擎里面的Bucket存储空间进行创建。 目录 1、先看看OSS: 2、代码编写: 3、运行效果: 1、先看看OSS: 此…

FPGA高端项目:Xilinx Zynq7020系列FPGA多路视频拼接 工程解决方案 提供6套工程源码和技术支持

目录 1、前言版本更新说明给读者的一封信FPGA就业高端项目培训计划免责声明 2、相关方案推荐我已有的FPGA视频拼接叠加融合方案本方案在Xilinx Kintex7 系列FPGA上的应用本方案在Xilinx Artix7 系列FPGA上的应用 3、设计思路框架视频源选择ov5640 i2c配置及采集动态彩条多路视频…

实用工具合集(持续更新...)

一、搜索引擎 1.1、小白盘 网站:https://www.xiaobaipan.com 度盘资源搜索的网站,能够搜索电影、电视剧、小说、音乐等资源(注意:评论区很多小伙伴说小白盘有毒,我用谷歌浏览器搜索过几次并无大碍,请慎用…

JeecgBoot集成TiDB,打造高效可靠的数据存储解决方案

TiDB简介 TiDB是PingCAP公司自主设计、研发的开源分布式关系型数据库,同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 的融合型分布式数据库产品,具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生…

三篇论文联合复现:高比例新能源下考虑需求侧响应和智能软开关的配电网重构程序代码!

适用平台:MatlabYalmipCplex 程序在高比例新能源接入的情况下提出了考虑需求响应(DR)和智能软开关(SOP)的多时段主动配电网重构策略,进一步降低配电系统重构费用,减少弃风率和弃光率&#xff1…

CSS自适应分辨率 postcss-pxtorem(适用于 Vite)

前言 此篇是基于 Vite Vu3 项目的 CSS 自适应分辨率! 如果想知道基于 Webpack Vue2 可移步 《CSS自适应分辨率 amfe-flexible 和 postcss-pxtorem(适用于 Webpack)》 项目对应的主要插件版本如下: "vite": "^4…

PMU || PMIC(Power management IC):电源管理集成电路

1、PMU(电源管理芯片)是一种高度集成化的电源管理方案,可以简单理解为集成多路的LDO和DC-DC,以及相应的检测和控制电路,其核心结构通常是PWM控制器和MOSFET。高集成度的PMU器件可以有效减小电路板占用面积和器件数量&a…

谷歌出品!读懂 QUIC 协议:更快、更高效的通信协议

QUIC结构 QUIC协议模型如下图所示,其放弃了TCP∕IP网络中使用五元组(源IP,源端口,目的IP,目的端口,协议标识符)来唯一标识一条连接的方式,而使用一个全局唯一的随机生成的ID(即Connection ID) 来标识一条连接。 由低向上分层讨论QUIC协议: •UDP层:在U…