语音增强-谱减法

news/2024/7/7 19:05:35

导入相关包

import librosa
import numpy as np
import matplotlib.pyplot as plt
from playsound import playsound
import soundfile as sf

加载音源 

# 干净的声音
clean_wav_file = 'sf1_cln.wav'
clean, fs = librosa.load(clean_wav_file, sr=None)
# 带噪音的声音
noise_wav_file = 'sf1_n0L.wav'
noise, fs = librosa.load(noise_wav_file, sr=None)
# 播放对比
playsound(clean_wav_file)
playsound(noise_wav_file)

谱减法-简单减

# 计算noise信号的频谱
S_noisy = librosa.stft(noise, n_fft=256, hop_length=128, win_length=256)
D,T = S_noisy.shape
Mag_noisy = np.abs(S_noisy)
Phase_noisy = np.angle(S_noisy)
# 能量谱
Power_noisy = Mag_noisy**2

# 估计噪声信号的能量,由于噪声信号未知,这里假设含噪信号的前30帧为噪声
Mag_noise = np.mean(np.abs(S_noisy[:,:30]), axis=1, keepdims=True)
Power_noise = Mag_noise**2
Power_noise = np.tile(Power_noise, [1,T])

# 能量谱减或者幅度谱减都可以
Power_enhance = Power_noisy - Power_noise
# 保证能量大于0
Power_enhance[Power_enhance < 0] = 0
Mag_enhance = np.sqrt(Power_enhance)

# 对信号进行恢复
S_enhance = Mag_enhance * np.exp(1j * Phase_noisy)
enhance = librosa.istft(S_enhance, hop_length=128, win_length=256)
sf.write('enhance1.wav', enhance, fs)

# 播放对比
playsound(noise_wav_file)
playsound('enhance1.wav')
# 绘制频谱
plt.subplot(3, 1, 1)
plt.specgram(clean, NFFT=256, Fs=fs)
plt.xlabel('clean specgram')

plt.subplot(3, 1, 2)
plt.specgram(noise, NFFT=256, Fs=fs)
plt.xlabel('noise specgram')

plt.subplot(3, 1, 3)
plt.specgram(enhance, NFFT=256, Fs=fs)
plt.xlabel('enhance specgram')

谱减法-过减法 

S_noisy = librosa.stft(noise, n_fft=256, hop_length=128, win_length=256)
D,T = S_noisy.shape
Mag_noisy = np.abs(S_noisy)
Phase_noisy = np.angle(S_noisy)
Power_noisy = Mag_noisy**2
Mag_noise = np.mean(np.abs(S_noisy[:,:30]), axis=1, keepdims=True)
Power_noise = Mag_noise**2
Power_noise = np.tile(Power_noise, [1,T])


alpha = 4
gamma = 1

# 多减点
Power_enhance = np.power(Power_noisy, gamma) - alpha * np.power(Power_noise, gamma)
Power_enhance = np.power(Power_enhance, 1 / gamma)

# 对于过小的值用beta*Power_noise替代
beta=  0.0001
mask= (Power_enhance >= beta * Power_noise) - 0
Power_enhance = mask * Power_enhance + beta * (1 - mask) * Power_noise
Mag_enhance = np.sqrt(Power_enhance)

# 信号恢复
S_enhance = Mag_enhance * np.exp(1j * Phase_noisy)
enhance = librosa.istft(S_enhance, hop_length=128, win_length=256)
sf.write('enhance2.wav', enhance, fs)

plt.specgram(enhance, NFFT=256, Fs=fs)
plt.xlabel('enhance specgram')

谱减法-引入平滑机制(能量谱平滑)

S_noisy = librosa.stft(noise, n_fft=256, hop_length=128, win_length=256)
D,T = S_noisy.shape
Mag_noisy = np.abs(S_noisy)
Phase_noisy = np.angle(S_noisy)
Power_noisy = Mag_noisy**2
Mag_noise = np.mean(np.abs(S_noisy[:,:30]), axis=1, keepdims=True)
Power_noise = Mag_noise**2
Power_noise = np.tile(Power_noise, [1,T])

# 先对幅度谱平滑一次
Mag_noisy_new = np.copy(Mag_noisy)
k = 1
for t in range(k, T-k):
    Mag_noisy_new[:,t] = np.mean(Mag_noisy[:, t-k:t+k+1], axis=1)
Power_noisy = Mag_noisy_new**2


# 超减法去噪
alpha = 4
gamma = 1
Power_enhance = np.power(Power_noisy, gamma) - alpha * np.power(Power_noise, gamma)
Power_enhance = np.power(Power_enhance, 1 / gamma)
# 对于过小的值用beta*Power_noise替代
beta=  0.0001
mask= (Power_enhance >= beta * Power_noise) - 0
Power_enhance = mask * Power_enhance + beta * (1 - mask) * Power_noise
Mag_enhance = np.sqrt(Power_enhance)


Mag_enhance_new = np.copy(Mag_enhance)
# 计算最大噪声残差
maxnr = np.max(np.abs(S_noisy[:,:31]) - Mag_noise, axis=1)
# 平滑
k = 1
for t in range(k, T-k):
    index = np.where(Mag_enhance[:, t] < maxnr)[0]
    temp = np.min(Mag_enhance[:, t-k:t+k+1], axis=1)
    Mag_enhance_new[index, t] = temp[index]
    
# 信号恢复
S_enhance = Mag_enhance * np.exp(1j * Phase_noisy)
enhance = librosa.istft(S_enhance, hop_length=128, win_length=256)
sf.write('enhance3.wav', enhance, fs)

plt.specgram(enhance, NFFT=256, Fs=fs)
plt.xlabel('enhance specgram')

参考:语音增强-谱减法-1_哔哩哔哩_bilibili

 课件及资料:SpeechProcessing: 语音处理 - Gitee.com


http://lihuaxi.xjx100.cn/news/1518632.html

相关文章

使用maven idea环境

创建模块工程后 idea三种方式执行maven命令 想在哪个工程模块上执行就点开哪一个 如果觉得双击完clean再双击install麻烦&#xff0c;可以 如果有需要还可以给命令后面加参数 ​​​ 第三种&#xff0c;在终端中打开&#xff0c;相当于通过idea进入了命令行 工程导入 导入模块…

L1和L2正则

L1和L2正则 L1正则常被用来进行特征选择&#xff0c;主要原因在于L1正则化会使得较多的参数为0&#xff0c;从而产生稀疏解&#xff0c;我们可以将0对应的特征遗弃&#xff0c;进而用来选择特征。一定程度上L1正则也可以防止模型过拟合。 L2正则&#xff1a; L1损失函数相比于…

SecureCRT 解决Log加时间设置

SecureCRT相比putty、MobaXTerm等调试工具有一个突出的优点&#xff0c;它的log功能非常好用&#xff0c;可以在每行log都加入时间戳&#xff0c;精确到毫秒&#xff0c;以下是CRT的log配置设置: 一: 打开Options Global Options–>Default Session–>Edit Default Set…

尼康D90使用心得

文章目录 规格参数快速指南相机机身模式拨盘控制面板取景器拍摄信息展示 核心功能指令拨盘拍摄模式自动模式场景模式快门速度和光圈 固件、软件、驱动升级更多细节参考 规格参数 型号尼康D90发布日期2008年08月机身特性APS-C规格数码单反产品定位中端单反传感器类型CMOS传感器…

javascript将数组中的数字类型元素保留两位小数

如果你想要将数组中的数字类型元素保留两位小数&#xff0c;你可以使用以下的方法。假设你的数组是JavaScript的数组&#xff0c;代码可能是这样的&#xff1a; var array [123.456, 456.789, 321.123]; // 原始数组 var newArray [];for (var i 0; i < array.length; i…

大数据课程K21——Spark的SparkSQL基础语法

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Spark的SparkSQL通过方法来使用; ⚪ 掌握Spark的SparkSQL通过sql语句来调用; 一、SparkSQL基础语法——通过方法来使用 1. 查询 df.select("id","name").show()…

STM32屏幕计时器

目录 一、最终效果二、实现思想三、实现过程3.1 屏幕显示3.2 中断处理 一、最终效果 显示屏显示计时时间&#xff0c;格式为 00:00:00&#xff0c;依次为 时:分:秒&#xff0c;程序运行之后自动计时&#xff0c;当按下按键&#xff0c;计时清零&#xff0c;按下按键采用外部中…

Powershell模拟实现Linux下的tree命令

Powershell模拟实现Linux下的tree命令 代码 环境&#xff1a; P o w e r s h e l l 7 Powershell\ 7 Powershell 7 function Get-Tree {param([string]$directory ".",[int]$d 1,[switch]$f)$absolutePath Resolve-Path -Relative $directoryWrite-Host $absol…