目录

带有 torchaudio 的 MVDR

作者 倪兆恒

概述

这是有关如何使用 torchaudio 应用 MVDR 波束成形的教程。

步骤

  • 理想比率掩码 (IRM) 是通过除以清洁/噪声来生成的 magnitude 按混合大小。

  • 我们测试所有三种解决方案 (、 、 ) 的 torchaudio 的 MVDR 模块。ref_channelstv_evdstv_power

  • 我们测试了用于 MVDR 波束成形的单通道和多通道掩模。 在计算时,多通道掩码沿通道维度进行平均 分别是语音和噪声的协方差矩阵。

制备

首先,我们导入必要的包并检索数据。

多通道音频示例选自 ConferencingSpeech 数据集。

原始文件名为

SSB07200001\#noise-sound-bible-0038\#7.86_6.16_3.00_3.14_4.84_134.5285_191.7899_0.4735\#15217\#25.16333303751458\#0.2101221178590021.wav

它是用 生成的;

  • SSB07200001.wav来自 AISHELL-3 (Apache 许可证 v.2.0)

  • noise-sound-bible-0038.wav来自 MUSAN (署名 4.0 国际 — CC BY 4.0)

import os
import requests
import torch
import torchaudio
import IPython.display as ipd

torch.random.manual_seed(0)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print(torch.__version__)
print(torchaudio.__version__)
print(device)

filenames = [
    'mix.wav',
    'reverb_clean.wav',
    'clean.wav',
]
base_url = 'https://download.pytorch.org/torchaudio/tutorial-assets/mvdr'

for filename in filenames:
    os.makedirs('_assets', exist_ok=True)
    if not os.path.exists(filename):
        with open(f'_assets/{filename}', 'wb') as file:
            file.write(requests.get(f'{base_url}/{filename}').content)

外:

1.10.0+cpu
0.10.0+cpu
cpu

生成理想比率掩码 (IRM)

加载音频数据

mix, sr = torchaudio.load('_assets/mix.wav')
reverb_clean, sr2 = torchaudio.load('_assets/reverb_clean.wav')
clean, sr3 = torchaudio.load('_assets/clean.wav')
assert sr == sr2

noise = mix - reverb_clean

注意

MVDR 模块需要 dtype 来产生嘈杂的 STFT。 我们需要将波形的 dtype 转换为torch.cdoubletorch.double

mix = mix.to(torch.double)
noise = noise.to(torch.double)
clean = clean.to(torch.double)
reverb_clean = reverb_clean.to(torch.double)

计算 STFT

stft = torchaudio.transforms.Spectrogram(
    n_fft=1024,
    hop_length=256,
    power=None,
)
istft = torchaudio.transforms.InverseSpectrogram(n_fft=1024, hop_length=256)

spec_mix = stft(mix)
spec_clean = stft(clean)
spec_reverb_clean = stft(reverb_clean)
spec_noise = stft(noise)

生成理想比率掩码 (IRM)

注意

我们发现直接使用掩码比使用 的平方根。这与 IRM 的定义略有不同。

def get_irms(spec_clean, spec_noise, spec_mix):
    mag_mix = spec_mix.abs() ** 2
    mag_clean = spec_clean.abs() ** 2
    mag_noise = spec_noise.abs() ** 2
    irm_speech = mag_clean / (mag_clean + mag_noise)
    irm_noise = mag_noise / (mag_clean + mag_noise)

    return irm_speech, irm_noise

注意

我们在这里使用混响干净的语音作为目标, 您还可以将其设置为 Dry clean Speech。

应用 MVDR

使用多通道掩码应用 MVDR 波束成形

results_multi = {}
for solution in ['ref_channel', 'stv_evd', 'stv_power']:
    mvdr = torchaudio.transforms.MVDR(ref_channel=0, solution=solution, multi_mask=True)
    stft_est = mvdr(spec_mix, irm_speech, irm_noise)
    est = istft(stft_est, length=mix.shape[-1])
    results_multi[solution] = est

使用单通道掩码应用 MVDR 波束成形

我们以第 1 个通道为例。 通道选择可能取决于麦克风阵列的设计

results_single = {}
for solution in ['ref_channel', 'stv_evd', 'stv_power']:
    mvdr = torchaudio.transforms.MVDR(ref_channel=0, solution=solution, multi_mask=False)
    stft_est = mvdr(spec_mix, irm_speech[0], irm_noise[0])
    est = istft(stft_est, length=mix.shape[-1])
    results_single[solution] = est

计算 Si-SDR 分数

def si_sdr(estimate, reference, epsilon=1e-8):
    estimate = estimate - estimate.mean()
    reference = reference - reference.mean()
    reference_pow = reference.pow(2).mean(axis=1, keepdim=True)
    mix_pow = (estimate * reference).mean(axis=1, keepdim=True)
    scale = mix_pow / (reference_pow + epsilon)

    reference = scale * reference
    error = estimate - reference

    reference_pow = reference.pow(2)
    error_pow = error.pow(2)

    reference_pow = reference_pow.mean(axis=1)
    error_pow = error_pow.mean(axis=1)

    sisdr = 10 * torch.log10(reference_pow) - 10 * torch.log10(error_pow)
    return sisdr.item()

结果

单通道蒙版结果

for solution in results_single:
    print(solution+": ", si_sdr(results_single[solution][None,...], reverb_clean[0:1]))

外:

ref_channel:  15.035907456985868
stv_evd:  16.563734673832553
stv_power:  17.820481909929907

多通道蒙版结果

for solution in results_multi:
    print(solution+": ", si_sdr(results_multi[solution][None,...], reverb_clean[0:1]))

外:

ref_channel:  13.177373866143256
stv_evd:  12.433610809532858
stv_power:  12.897505397104673

原始音频

混合语音

ipd.Audio(mix[0], rate=16000)


噪声

ipd.Audio(noise[0], rate=16000)


干净的语音

ipd.Audio(clean[0], rate=16000)


增强的音频

多通道掩模,ref_channel解决方案

ipd.Audio(results_multi['ref_channel'], rate=16000)


多通道遮罩,stv_evd解决方案

ipd.Audio(results_multi['stv_evd'], rate=16000)


多通道掩模,stv_power解决方案

ipd.Audio(results_multi['stv_power'], rate=16000)


单通道掩模,ref_channel解决方案

ipd.Audio(results_single['ref_channel'], rate=16000)


单通道掩模stv_evd解决方案

ipd.Audio(results_single['stv_evd'], rate=16000)


单通道掩模,stv_power解决方案

ipd.Audio(results_single['stv_power'], rate=16000)


脚本总运行时间:(0 分 0.841 秒)

由 Sphinx-Gallery 生成的图库

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源