基于频谱处理的音频分离方法

基于频谱处理的音频分离方法

在音频处理领域,音频分离是一个重要的任务,尤其是在语音识别、音乐制作和通信等应用中。音频分离的目标是从混合信号中提取出单独的音频源。通过频谱处理进行音频分离是一种有效的方法,本文将介绍其基本原理、公式以及如何通过降噪作为一个具体的例子来实现音频分离。

1. 频谱处理音频分离的原理

频谱处理音频分离的基本思想是将音频信号从时间域转换到频率域,通过分析频谱中的成分,去除或抑制不需要的成分,从而恢复目标音频信号。常用的频谱分析方法是短时傅里叶变换(STFT)。

1.1 短时傅里叶变换(STFT)

短时傅里叶变换将时间域信号分成多个短时间段,并对每个段进行傅里叶变换。对于离散时间信号 (x[n]),STFT 的离散形式可以表示为:

X [ m , k ] = ∑ n = − ∞ ∞ x [ n ] w [ n − m ] e − j 2 π N k n X[m, k] = \sum_{n=-\infty}^{\infty} x[n] w[n - m] e^{-j \frac{2\pi}{N}kn} X[m,k]=n=x[n]w[nm]ejN2πkn

其中:

  • X [ m , k ] X[m, k] X[m,k] 是在时间帧 (m) 和频率 (k) 的复数频谱。
  • x [ n ] x[n] x[n] 是输入信号。
  • w [ n ] w[n] w[n] 是窗函数,用于限制信号的时间范围。
  • N N N是窗的长度。

1.2 逆短时傅里叶变换(ISTFT)

逆短时傅里叶变换用于将频谱信息转换回时间域信号。对于离散时间信号,ISTFT 的离散形式可以表示为:

x [ n ] = ∑ m = − ∞ ∞ X [ m , k ] w [ n − m ] e j 2 π N k n x[n] = \sum_{m=-\infty}^{\infty} X[m, k] w[n - m] e^{j \frac{2\pi}{N}kn} x[n]=m=X[m,k]w[nm]ejN2πkn

其中:

  • x [ n ] x[n] x[n] 是恢复后的离散时间信号。
  • X [ m , k ] X[m, k] X[m,k]是去噪后的频谱。

1.3 音频分离算法

在频谱域中,音频分离的基本步骤如下:

  1. 计算 STFT:对混合信号(包含多个音源)进行 STFT,得到频谱表示。
  2. 源信号估计:通过分析混合信号的频谱,估计各个源信号的频谱成分。
  3. 频谱相减或掩码:从混合信号的频谱中减去或应用掩码来提取目标音源的频谱。
  4. 逆 STFT:对提取后的频谱进行逆 STFT,恢复到时间域信号。

2. 降噪作为音频分离的例子

降噪是音频分离中的一个具体应用场景。在降噪过程中,我们的目标是从包含噪声的混合信号中提取出干净的音频信号。降噪的基本步骤如下:

2.1 完全降噪

在完全降噪的情况下,我们假设噪声的频谱可以被准确估计并完全从混合信号中去除。此时,频谱相减的公式为:

Y ( f ) = X ( f ) − N ( f ) Y(f) = X(f) - N(f) Y(f)=X(f)N(f)

在这种情况下,重建的音频信号将尽可能接近原始的干净信号。

2.2 不完全降噪

在不完全降噪的情况下,噪声的频谱可能无法完全准确地估计,或者在去噪过程中可能会对语音信号造成一定的抑制。此时,我们可以引入一个随机因子来模拟这种情况:

Y ( f ) = X ( f ) − N ( f ) ⋅ factor Y(f) = X(f) - N(f) \cdot \text{factor} Y(f)=X(f)N(f)factor

其中,factor 是一个在 0.8 到 1.2 之间的随机值。这个因子可以模拟噪声没有完全消除的情况,或者在去噪过程中对语音信号的抑制。
在这里插入图片描述
在这里插入图片描述

3. 代码实现

import numpy as np
import librosa
import matplotlib.pyplot as plt
import soundfile as sf
import librosa.display

# 1. 读取两个文件并进行时域混合
def load_and_mix(audio_file, noise_file, duration):
    audio, sr_audio = librosa.load(audio_file, sr=None)
    noise, sr_noise = librosa.load(noise_file, sr=None)

    if sr_audio != sr_noise:
        raise ValueError("Sampling rates of the audio and noise files must be the same.")

    min_length = min(len(audio), len(noise), duration * sr_audio)
    audio = audio[:min_length]
    noise = noise[:min_length]

    mixed_signal = audio + noise
    return audio, noise, mixed_signal, sr_audio

# 2. 计算 STFT
def compute_stft(signal):
    return librosa.stft(signal)

# 3. 计算噪声的 STFT
def compute_noise_stft(noise):
    return librosa.stft(noise)

# 4. 频谱相减
def subtract_stft(mixed_stft, noise_stft, factor):
    return mixed_stft - (noise_stft * factor)

# 5. ISTFT 重新生成语音
def reconstruct_audio(subtracted_stft):
    return librosa.istft(subtracted_stft)

# 6. 可视化过程
def visualize_process(original, noise, mixed, reconstructed_best, reconstructed_partial, sr):
    plt.figure(figsize=(12, 10))

    plt.subplot(5, 1, 1)
    plt.title('Original Audio Signal')
    librosa.display.waveshow(original, sr=sr, alpha=1)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')

    plt.subplot(5, 1, 2)
    plt.title('Noise Signal')
    librosa.display.waveshow(noise, sr=sr, alpha=1)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')

    plt.subplot(5, 1, 3)
    plt.title('Mixed Audio Signal')
    librosa.display.waveshow(mixed, sr=sr, alpha=1)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')

    plt.subplot(5, 1, 4)
    plt.title('Reconstructed Audio Signal (Best Case)')
    librosa.display.waveshow(reconstructed_best, sr=sr, alpha=1)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')

    plt.subplot(5, 1, 5)
    plt.title('Reconstructed Audio Signal (Partial Case)')
    librosa.display.waveshow(reconstructed_partial, sr=sr, alpha=1)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')

    plt.tight_layout()
    plt.show()

    # 绘制语谱图
    plt.figure(figsize=(12, 10))

    original_stft = compute_stft(original)
    noise_stft = compute_noise_stft(noise)
    mixed_stft = compute_stft(mixed)
    reconstructed_best_stft = compute_stft(reconstructed_best)
    reconstructed_partial_stft = compute_stft(reconstructed_partial)

    plt.subplot(5, 1, 1)
    plt.title('Original Audio Spectrogram')
    librosa.display.specshow(librosa.amplitude_to_db(np.abs(original_stft), ref=np.max), sr=sr, y_axis='log', x_axis='time')
    plt.colorbar(format='%+2.0f dB')

    plt.subplot(5, 1, 2)
    plt.title('Noise Spectrogram')
    librosa.display.specshow(librosa.amplitude_to_db(np.abs(noise_stft), ref=np.max), sr=sr, y_axis='log', x_axis='time')
    plt.colorbar(format='%+2.0f dB')

    plt.subplot(5, 1, 3)
    plt.title('Mixed Audio Spectrogram')
    librosa.display.specshow(librosa.amplitude_to_db(np.abs(mixed_stft), ref=np.max), sr=sr, y_axis='log', x_axis='time')
    plt.colorbar(format='%+2.0f dB')

    plt.subplot(5, 1, 4)
    plt.title('Reconstructed Audio Spectrogram (Best Case)')
    librosa.display.specshow(librosa.amplitude_to_db(np.abs(reconstructed_best_stft), ref=np.max), sr=sr, y_axis='log', x_axis='time')
    plt.colorbar(format='%+2.0f dB')

    plt.subplot(5, 1, 5)
    plt.title('Reconstructed Audio Spectrogram (Partial Case)')
    librosa.display.specshow(librosa.amplitude_to_db(np.abs(reconstructed_partial_stft), ref=np.max), sr=sr, y_axis='log', x_axis='time')
    plt.colorbar(format='%+2.0f dB')

    plt.tight_layout()
    plt.show()

# 主程序
def main():
    audio_file = '1.wav'  # 语音文件
    noise_file = '3.wav'  # 噪声文件
    duration = 20  # 取样长度(秒)

    original_audio, noise, mixed_signal, sr = load_and_mix(audio_file, noise_file, duration)

    mixed_stft = compute_stft(mixed_signal)
    noise_stft = compute_noise_stft(noise)

    # 完全降噪
    subtracted_stft_best = subtract_stft(mixed_stft, noise_stft, factor=np.ones_like(noise_stft))
    reconstructed_best_audio = reconstruct_audio(subtracted_stft_best)

    # 不完全降噪
    random_factor = np.random.uniform(0.8, 1.2, noise_stft.shape)
    subtracted_stft_partial = subtract_stft(mixed_stft, noise_stft, factor=random_factor)
    reconstructed_partial_audio = reconstruct_audio(subtracted_stft_partial)

    sf.write('mixed_signal.wav', mixed_signal, sr)
    sf.write('reconstructed_audio_best.wav', reconstructed_best_audio, sr)
    sf.write('reconstructed_audio_partial.wav', reconstructed_partial_audio, sr)

    visualize_process(original_audio, noise, mixed_signal, reconstructed_best_audio, reconstructed_partial_audio, sr)

if __name__ == "__main__":
    main()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣-图论-1【算法学习day.51】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…

工业—使用Flink处理Kafka中的数据_ChangeRecord2

使用 Flink 消费 Kafka 中 ChangeRecord 主题的数据,每隔 1 分钟输出最近 3 分钟的预警次数最多的 设备,将结果存入Redis 中, key 值为

PortSwigger 原型污染

一、什么是原型污染 原型污染是一种 JavaScript 漏洞,它使攻击者能够向全局对象原型添加任意属性,然后这些属性可能被用户定义的对象继承。 二、JavaScript 原型和继承基础 1、原型 JavaScript 中的每个对象都链接到某种类型的另一个对象,称…

AMEYA360:上海永铭电子全新高压牛角型铝电解电容IDC3系列,助力AI服务器电源高效运转

随着数据中心和云计算的高速发展,AI服务器的能效要求日益提高。如何在有限空间内实现更高的功率密度和稳定的电源管理,成为AI服务器电源设计的一大挑战。永铭推出全新高压牛角型铝电解电容IDC3系列,以大容量、小尺寸的创新特性,为…

jmeter基础_打开1个jmeter脚本(.jmx文件)

课程大纲 方法1.菜单栏“打开” 菜单栏“文件” - “打开” (或快捷键,mac为“⌘ O”),打开文件选择窗口 - 选择脚本文件,点击“open”,即可打开脚本。 方法2.工具栏“打开”图标 工具栏点击“打开”图标&…

基于微信小程序的教学质量评价系统

​ 私信我获取源码和万字论文,制作不易,感谢点赞支持。 基于微信小程序的教学质量评价系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的教学质量评价系统的开发全过…

数据结构-最小生成树

一.最小生成树的定义 从V个顶点的图里生成的一颗树,这颗树有V个顶点是连通的,有V-1条边,并且边的权值和是最小的,而且不能有回路 二.Prim算法 Prim算法又叫加点法,算法比较适合稠密图 每次把边权最小的顶点加入到树中&#xff0…

增量预训练网络安全大模型的一次尝试

一、背景 探索使用网络安全知识,对开源基模型进行增强,评估是否能使基模型在网络安全领域表现出更好地专业度。 项目基于云起无垠SecGPT开源项目,在hugeface开源数据集的基础上,增加了自有预训练数据,进行增量预训练…

从零开始配置 Docker 网络:快速掌握各类型网络的设置与使用场景

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 Docker 网络类型概述🎯 Bridge 驱动🎯 Host 驱动🎯 None 驱动🎯 Overlay 驱动🎯 Macvlan 驱动🔖 获取网络接口📝 总结:选择合适的网络类型⚓️ 相关链接 ⚓️📖 介绍 📖 如果你曾经在搭建…

C语言(一维数组练习)

键盘录入一组数列&#xff0c;利用冒泡排序将数据由大到小排序 #include <stdio.h>int main(int argc,char *argv[]) {int i,j,tmep;int arr[10];printf("请输入10个测试整数&#xff1a;\n");int lensizeof(arr)/sizeof(arr[0]);for(i0;i<len;i){scanf(&q…

PostgreSQL实现透视表查询

PostgreSQL 8.3版本发布时&#xff0c;引入了一个名为tablefunc的新扩展。这个扩展提供了一组非常有趣的函数。其中之一是交叉表函数&#xff0c;用于创建数据透视表。这就是我们将在本文中讨论的内容。 需求说明 解释此函数如何工作的最简单方法是使用带有数据透视表的示例…

消息中间件-Kafka1-实现原理

消息中间件-Kafka 一、kafka简介 1、概念 Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、支持分区&#xff08;partition&#xff09;、多副本的&#xff08;replica&#xff09;&#xff0c;基于zookeeper协调的分布式消息系统&#xff0c;它的最大的特性就是可以…

protobuf实现Hbase数据压缩

目录 前置HBase数据压缩效果获取数据(反序列化) 前置 安装说明 使用说明 HBaseDDL和DML操作 HBase数据压缩 问题 在上文的datain中原文 每次写入数据会写入4个单元格的内容&#xff0c;现在希望能对其进行筛减&#xff0c;合并成1格&#xff0c;减少存储空间&#xff08;序列…

爬虫专栏第二篇:Requests 库实战:从基础 GET 到 POST 登录全攻略

简介&#xff1a;本文聚焦 Requests 库的强大功能与应用实战。首先介绍其安装步骤及版本选择要点&#xff0c;随后深入讲解 GET 请求&#xff0c;以百度页面为例&#xff0c;展示如何发起基本 GET 请求、巧妙添加 headers 与参数以精准搜索&#xff0c;以及正确设置 encoding 避…

【Leetcode】19. 删除链表的第N个节点

【Leetcode】19. 删除链表的第N个节点 1. 题目介绍2. 方法一&#xff1a;计算链表长度逻辑流程:代码复杂度分析 1. 题目介绍 题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,…

工业齐套管理虚拟现实仿真模拟软件

工业齐套管理虚拟现实仿真模拟软件是与法国最大的汽车制造商合作开发的一款虚拟现实仿真模拟软件&#xff0c;借助身临其境的虚拟现实环境&#xff0c;无需停止生产线&#xff0c;即可模拟仓库和提货区域。 工业齐套管理虚拟现实仿真模拟软件不仅适用于汽车工业&#xff0c;安全…

【嘟嘟早教卡】 小程序源码分享带后台管理

【嘟嘟早教卡】是专门为 3-6 岁婴幼儿童学习普通话、英语研发的早教启蒙认知识字的小程序 小程序由 Taro 及 Tailwind CSS 构建而成&#xff0c;后台管理使用 Laravel 及 Tailwind CSS 想法源于小时候玩的认知卡片&#xff0c;基本大部分家庭都买过认知卡片&#xff0c;我按照…

概率论相关知识随记

作为基础知识的补充&#xff0c;随学随记&#xff0c;方便以后查阅。 概率论相关知识随记 期望&#xff08;Expectation&#xff09;期望的定义离散型随机变量的期望示例&#xff1a;掷骰子的期望 连续型随机变量的期望示例&#xff1a;均匀分布的期望 期望的性质线性性质期望的…

FastAPI 响应状态码:管理和自定义 HTTP Status Code

FastAPI 响应状态码&#xff1a;管理和自定义 HTTP Status Code 本文介绍了如何在 FastAPI 中声明、使用和修改 HTTP 状态码&#xff0c;涵盖了常见的 HTTP 状态码分类&#xff0c;如信息响应&#xff08;1xx&#xff09;、成功状态&#xff08;2xx&#xff09;、客户端错误&a…

oracle 11g中如何快速设置表分区的自动增加

在很多业务系统中&#xff0c;一些大表一般通过分区表的形式来实现数据的分离管理&#xff0c;进而加快数据查询的速度。分区表运维管理的时候&#xff0c;由于人为操作容易忘记添加分区&#xff0c;导致业务数据写入报错。所以我们一般通过配置脚本或者利用oracle内置功能实现…