Python语音增强

news2024/11/15 23:30:08

简介

音频时域波形具有以下特征:音调,响度,质量。我们在进行数据增强时,最好只做一些小改动,使得增强数据和源数据存在较小差异即可,切记不能改变原有数据的结构,不然将产生“脏数据”,通过对音频数据进行数据增强,能有助于我们的模型避免过度拟合并变得更加通用。

经过实验发现对声波的以下改变是有用的:Noise addition(增加噪音)、Add reverb(增加混响)、Time shifting(时移)、Pitch shifting(改变音调)和Time stretching(时间拉伸)。

本文需要使用的python库:

  • matplotlib:绘制图像
  • librosa:音频数据处理
  • numpy:矩阵数据处理

常见的失真有:

  1. 加性声学噪声:加性噪声与期望信号不相干,平稳加性噪声(背景环境声音、嗡嗡声、功放噪音),非平稳加性噪声(媒体干扰、非期望语音干扰和一些电子干扰)
  2. 声学混响:多径反射引起的叠加效应(与期望信号相关)
  3. 卷积信道效应:导致不均匀或带宽限制响应,为了去除信道脉冲响应,做信道均衡时对通信信道没有有效建模
  4. 非线性失真:信号输入时不适当的增益,常出现与幅度限制、麦克风功放等加性宽带电子噪声电器干扰
  5. 编码失真:比如压缩编码
  6. 录音仪器引起的失真:麦克风频率响应不足

先画出原始语音数据的语谱图和波形图:

import librosa
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示符号
fs = 16000

wav_data, _ = librosa.load("/home/gxli/lgx/Data/gather_crop/clean1/2148_farend.wav", sr=fs, mono=True)

# ########### 画图
plt.subplot(2, 2, 1)
plt.title("语谱图", fontsize=15)
plt.specgram(wav_data, Fs=16000, scale_by_freq=True, sides='default', cmap="jet")
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('频率/Hz', fontsize=15)

plt.subplot(2, 2, 2)
plt.title("波形图", fontsize=15)
time = np.arange(0, len(wav_data)) * (1.0 / fs)
plt.plot(time, wav_data)
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('振幅', fontsize=15)

plt.tight_layout()
# plt.savefig("save.png")
plt.show()

img

时域增强

噪声增强

第一种:控制噪声因子

def add_noise1(clean, noise, gain=0.004):
    # gain:噪声增益因子
    noisy = clean + gain * noise
    return noisy

img

第二种:根据SNR生成noisy

通过信噪比的公式推导出噪声的增益系数k。

\[SNR=10*log_{10}(\frac{S^2}{(kN)^2}) \Rightarrow k=\sqrt{\frac{S^2}{N^2*10^{\frac{SNR}{10}}}} \]
def snr2noise(clean, noise, SNR):
    """
    :param clean: 纯净语音
    :param far_echo: 噪音
    :param SER: 指定的SNR
    :return: 根据指定的SNR求带噪语音(纯净语音+噪声)
    """
    p_clean = np.mean(clean ** 2)  # 纯净语音功率
    p_noise = np.mean(noise ** 2)  # 噪声功率

    scalar = np.sqrt(p_clean / (10 ** (SNR / 10)) / (p_noise + np.finfo(np.float32).eps))
    noisy = clean + scalar * noise

    return noisy

第三种:制造鸡尾酒效应的带噪语音

其实并没有那么玄乎,就是将纯净语音和多段带噪语音进行相加,然后控制一下信噪比。

音量增强

语音音量的单位为dB,音量增益可以基于平均音量或者最大瞬时音量,下面公式是基于平均音量推得dB增益:

\[dB=10*log_{10}(kS)^2\Rightarrow k=\sqrt{\frac{10^{\frac{dB}{10}}}{S^2}} \]
def volumeAument1(wav, dB):
    """
    :param wav: 语音
    :param dB: 音量
    :return:返回以指定dB增益后的语音
    """
    power = np.mean(wav ** 2)  # 平均功率
    scalar = np.sqrt(10 ** (dB / 10) / (power + np.finfo(np.float32).eps))
    wav *= scalar
    return wav, scalar
\[dB=20*log_{10}kS\Rightarrow k=\frac{10^{\frac{db}{20}}}{A} \]
def volumeAument2(wav, dB):
    """
    :param wav: 语音
    :param dB: 音量
    :return:返回以指定dB增益后的语音
    """
    rmswav = (wav ** 2).mean() ** 0.5
    scalar = 10 ** (dB / 20) / (rmswav + np.finfo(np.float32).eps)
    wav = wav * scalar
    return wav, scalar

其实这两个函数都可以,都可以达到目的,本质上都一样。

"""
音量增强
"""
import numpy as np
import librosa

EPS = np.finfo(float).eps


def mean_dbfs(sample_data):
    rms = np.sqrt(np.mean(np.square(sample_data, dtype=np.float64)))
    dbfs = 20.0 * np.log10(max(1e-16, rms))
    return dbfs


def volumeAument1(wav, dB):
    """
    :param wav: 语音
    :param dB: 音量
    :return:返回以指定dB增益后的语音
    """
    power = np.mean(wav ** 2)  # 平均功率
    scalar = np.sqrt(10 ** (dB / 10) / (power + np.finfo(np.float32).eps))
    wav *= scalar
    return wav, scalar


def volumeAument2(wav, dB):
    """
    :param wav: 语音
    :param dB: 音量
    :return:返回以指定dB增益后的语音
    """
    rmswav = (wav ** 2).mean() ** 0.5
    scalar = 10 ** (dB / 20) / (rmswav + np.finfo(np.float32).eps)
    wav = wav * scalar
    return wav, scalar


sr = 16000
wav = librosa.load("./wavdata/TIMIT.WAV", sr=sr)[0]  # (46797,)
print(wav.shape)
wav, scalar = volumeAument1(wav, dB=15)
print(mean_dbfs(wav))  # 18.0103004778581

wav, scalar = volumeAument2(wav, 15)
print(mean_dbfs(wav))  # 18.010299731550788

混响增强

我这里使用的是Image Source Method(镜像源方法)来实现语音加混响,我想用两种方法来给大家实现,第一种是直接调用python库—— Pyroomacoustics来实现音频加混响,第二种就是按照公式推导一步一步来实现,两种效果一样,想看细节的可以参考第二种方法,只想开始实现效果的可以只看第一种方法:

方法一: Pyroomacoustics实现音频加混响

首先需要安装 Pyroomacoustics,这个库非常强大,感兴趣也可以多看看其他API接口

pip install  Pyroomacoustics

步骤:

  1. 创建房间(定义房间大小、所需的混响时间、墙面材料、允许的最大反射次数、)
  2. 在房间内创建信号源
  3. 在房间内放置麦克风
  4. 创建房间冲击响应
  5. 模拟声音传播
import pyroomacoustics as pra
import numpy as np
import matplotlib.pyplot as plt
import librosa

# 1、创建房间
# 所需的混响时间和房间的尺寸
rt60_tgt = 0.5  # 所需的混响时间,秒
room_dim = [9, 7.5, 3.5]  # 我们定义了一个9m x 7.5m x 3.5m的房间,米

# 我们可以使用Sabine’s公式来计算壁面能量吸收和达到预期混响时间所需的ISM的最大阶数(RT60,即RIR衰减60分贝所需的时间)
e_absorption, max_order = pra.inverse_sabine(rt60_tgt, room_dim)    # 返回 墙壁吸收的能量 和 允许的反射次数
# 我们还可以自定义 墙壁材料 和 最大反射次数
# m = pra.Material(energy_absorption="hard_surface")    # 定义 墙的材料,我们还可以定义不同墙面的的材料
# max_order = 3

room = pra.ShoeBox(room_dim, fs=16000, materials=pra.Material(e_absorption), max_order=max_order)

# 在房间内创建一个位于[2.5,3.73,1.76]的源,从0.3秒开始向仿真中发出wav文件的内容
audio, _ = librosa.load("speech.wav",sr=16000)  # 导入一个单通道语音作为源信号 source signal
room.add_source([2.5, 3.73, 1.76], signal=audio, delay=0.3)

# 3、在房间放置麦克风
# 定义麦克风的位置:(ndim, nmics) 即每个列包含一个麦克风的坐标
# 在这里我们创建一个带有两个麦克风的数组,
# 分别位于[6.3,4.87,1.2]和[6.3,4.93,1.2]。
mic_locs = np.c_[
    [6.3, 4.87, 1.2],  # mic 1
    [6.3, 4.93, 1.2],  # mic 2
]

room.add_microphone_array(mic_locs)     # 最后将麦克风阵列放在房间里

# 4、创建房间冲击响应(Room Impulse Response)
room.compute_rir()

# 5、模拟声音传播,每个源的信号将与相应的房间脉冲响应进行卷积。卷积的输出将在麦克风上求和。
room.simulate()

# 保存所有的信号到wav文件
room.mic_array.to_wav("./guitar_16k_reverb_ISM.wav", norm=True, bitdepth=np.float32,)

# 测量混响时间
rt60 = room.measure_rt60()
print("The desired RT60 was {}".format(rt60_tgt))
print("The measured RT60 is {}".format(rt60[1, 0]))


plt.figure()
# 绘制其中一个RIR. both can also be plotted using room.plot_rir()
rir_1_0 = room.rir[1][0]    # 画出 mic 1和 source 0 之间的 RIR
plt.subplot(2, 1, 1)
plt.plot(np.arange(len(rir_1_0)) / room.fs, rir_1_0)
plt.title("The RIR from source 0 to mic 1")
plt.xlabel("Time [s]")

# 绘制 microphone 1 处接收到的信号
plt.subplot(2, 1, 2)
plt.plot(np.arange(len(room.mic_array.signals[1, :])) / room.fs, room.mic_array.signals[1, :])
plt.title("Microphone 1 signal")
plt.xlabel("Time [s]")

plt.tight_layout()
plt.show()

混合ISM/射线跟踪房间模拟器

room = pra.ShoeBox(
    room_dim,
    fs=16000,
    materials=pra.Material(e_absorption),
    max_order=3,
    ray_tracing=True,
    air_absorption=True,
)

# 激活射线追踪
room.set_ray_tracing()

控制信噪比

room.simulate(reference_mic=0, snr=10)      # 控制信噪比

imgimg

方法二:Image Source Method 算法讲解

从这里要讲算法和原理了,

代码参考:matlab版本:RIR-Generator python版本:rir-generator

镜像源法简介:img

将反射面等效为一个虚像,或者说镜像。比如说,在一个开放空间里有一面平整墙面,那么一个声源可以等效为2两个声源;一个开放空间里有两面垂直的平整墙面,那么一个声源可以等效为4个;同理三面的话是8个。原理上就是这样,但是封闭的三维空间里情况有那么点复杂,一般来说,家里的空房间可以一定程度上近似为矩形盒子,假设房间尺寸为:

\[L=\left[x_{r}, y_{r}, z_{r}\right] \]

元素大小分别代表长宽高,而声源的三维坐标为:

\[S=\left[x_{s}, y_{s}, z_{s}\right] \]

麦克风的三维坐标为:

\[M=\left[x_{m}, y_{m}, z_{m}\right] \]

镜像声源\((i,j,k)\)到麦克风距离在三个坐标轴上的位置为

\[x_{i}=(-1)^{i} x_{s}+\left[i+\left(1-(-1)^{i}\right) / 2\right] x_{r}-x_{m} \]
\[y_{j}=(-1)^{j} y_{s}+\left[j+\left(1-(-1)^{j}\right) / 2\right] y_{r}-y_{m} \]
\[z_{k}=(-1)^{k} z_{s}+\left[k+\left(1-(-1)^{k}\right) / 2\right] z_{r}-z_{m} \]

那么声源\((i,j,k)\)距离麦克风的距离为:

\[d_{i j k}=\sqrt{\left(x_{i}^{2}+y_{j}^{2}+z_{k}^{2}\right)} \]

相对于直达声的到达延迟时间为:

\[\tau_{i j k}=\left(d_{i j k}-r\right) / c \]

其中\(c\)为声速,\(r\)为声源到麦克风的直线距离。那么,混响效果等效为不同延迟的信号的叠加,即混响效果可以表示为一个FIR滤波器与信号源卷积的形式,此滤波器可写为如下形式:

\[h(t)=\sum_{i} \sum_{j} \sum_{k}\left[A_{i j k} \delta\left(t-\tau_{i j k}\right)\right] \]

滤波器的抽头系数与镜面的反射系数与距离相关,如果每个面的反射系数不同则形式略复杂。详细代码还是要看RIR-Generator,我这里只做抛转引玉,写一个最简单的。

模拟镜像源:
房间尺寸(m):4 X 4 X 3
声源坐标(m):2 X 2 X 0
麦克风坐标(m):2 X 2 X 1.5
混响时间(s):0.2
RIR长度:512

Image Source方法

clc;clear;
c = 340;                    % 声速 (m/s)
fs = 16000;                 % Sample frequency (samples/s)
r = [2 2 1.5];              % 麦克风位置 [x y z] (m)
s = [2 2 0];              % 扬声器位置 [x y z] (m)
L = [4 4 3];                % 房间大小 [x y z] (m)
beta = 0.2;                 % 混响时间 (s)
n = 512;                   % RIR长度

h = rir_generator(c, fs, r, s, L, beta, n);
disp(size(h))   % (1,4096)

[speech, fs] = audioread("./test_wav/p225_001.wav");
disp(size(speech)); % (46797,1)

y = conv(speech', h);
disp(length(y))


% 开始画图
figure('color','w');    % 背景色设置成白色
subplot(3,1,1)
plot(h)
title("房间冲击响应 RIR","FontSize",14)

subplot(3,2,3)
plot(speech)
title("原语音波形","FontSize",14)

subplot(3,2,4)
plot(y)
title("加混响语音波形","FontSize",14)

subplot(3,2,5)
specgram(speech,512,fs,512,256);
title("原语音频谱","FontSize",14)

subplot(3,2,6)
specgram(y,512,fs,512,256);
title("加混响语音频谱","FontSize",14)

audiowrite("./test_wav/matlab_p225_001_reverber.wav",y,fs)

img

方法三:利用RIR生成混响

def add_pyreverb(wav, rir):
    reverb_wav = signal.fftconvolve(wav, rir, mode="full")
    reverb_wav = reverb_wav[0: wav.shape[0]]  # 使 reverb_wav 和 wav 具有相同的长度
    return reverb_wav

指定SER生成远端语音

SER的公式为:

\[SER=10\log_{10}\frac{E\{s^2(n)\}}{E\{d^2(n)\}} \]

其中E是统计 期望操作,\(s(n)\)是近端语音,\(d(n)\)是远端回声,由于我们需要根据指定的SER求混响信号,并且近端语音和远端混响都是已知的,我们只需要求得一个系数,来调整回声信号的能量大小,与远端混响相乘即可得我们想要的混响语音,即调整后的回声信号为\(kd(n)\)

\[k=\sqrt{\frac{E\{s^2(n)\}}{E\{d^2(n)\}*10^{\frac{SER}{10}}}} \]

根据以上公式,可以推导出\(k\)的值,最终\(kd(n)\)即我们所求的指定SER的混响。

def add_echo_ser(near_speech, far_echo, SER):
    """根据指定的SER求回声
    :param near_speech: 近端语音
    :param far_echo: 远端回声
    :param SER: 指定的SER
    :return: 指定SER的回声
    """
    p_near_speech = np.mean(near_speech ** 2)  # 近端语音功率
    p_far_echo = np.mean(far_echo ** 2)  # 远端回声功率

    k = np.sqrt(p_near_speech / (10 ** (SER / 10)) / p_far_echo)

    return k * far_echo

img

波形位移

语音波形移动使用numpy.roll函数向右移动shift距离

numpy.roll(a, shift, axis=None)

参数:

  • a:数组
  • shift:滚动的长度
  • axis:滚动的维度。0为垂直滚动,1为水平滚动,参数为None时,会先将数组扁平化,进行滚动操作后,恢复原始形状
x = np.arange(10)
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

print(np.roll(x, 2))
# array([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])

波形位移函数:

def time_shift(x, shift):
    # shift:移动的长度
    return np.roll(x, int(shift))
Augmentation = time_shift(wav_data, shift=fs//2)

img

谐波失真

参考自:soundpy

def harmonic_distortion(wav):
    wav = 2 * np.pi * wav
    count = 0
    while count < 5:
        wav = np.sin(wav)
        count += 1
    return wav

img

重采样数据增强

重采样后语音数据会丢失 重采样采样率到源采样值之间的频谱信息。

def augment_resample(wav, sr):
    resample_sr = np.random.uniform(sr)     # 从一个均匀分布中随机采样
    print("target_sr", resample_sr)
    resample = librosa.resample(wav, orig_sr=sr, target_sr=resample_sr)
    resample = librosa.resample(resample, orig_sr=resample_sr, target_sr=sr)
    return resample

img

频域增强

音高增强(Pitch Shifting)

在频率轴上缩放频谱图,从而改变音高。音高修正只改变音高而不影响音速,发现-5到5之间的步数更合适

# sr: 音频采样率
# n_steps: 要移动多少步
# bins_per_octave: 每个八度音阶(半音)多少步
    
# 上移大三度(如果bins_per_octave为12,则4步)
augment = librosa.effects.pitch_shift(wav_data, sr=sr, n_steps=4, bins_per_octave=12)
# 向下移动一个三全音(如果bins_per_octave是 12,则为六步)
augment = librosa.effects.pitch_shift(wav_data, sr=sr, n_steps=-6, bins_per_octave=12)
# 上移 3 个四分音符
augment = librosa.effects.pitch_shift(wav_data, sr=sr, n_steps=3, bins_per_octave=24)

img

速度增强(Tempo)

在时间轴上缩放频谱图,从而改变播放速度。

变速不变调

方法一:ffmpeg

在变速之前我们需要安装 pip install ffmpeg

from ffmpeg import audio

# 加快2倍速度
audio.a_speed("./sample/p225_001.wav",speed=2,out_file="./sample/p225_001_2.wav")

# 放慢2倍速度
audio.a_speed("./sample/p225_001.wav",speed=0.5,out_file="./sample/p225_001_0.5.wav")

ffmpeg是基于fmpeg开发的,Python的这个库不能加载太大的文件,但是原生的fmpeg。或者我们可以直接使用原生的ffmpeg工具包img

我们可以看到变速前后的波形图和语谱图没变,但是他们的时间维度却减少了一半。

方法二:SoundTorch

SoundTouch 是一个开源音频处理库,用于更改音频流或音频文件的速度、音高和播放速率。该库还支持估计音轨的稳定每分钟节拍率。

命令实例见:https://www.surina.net/soundtouch/soundstretch.html

速度增加100%

soundstretch input.wav output.wav -tempo=100

速度降低50%

soundstretch input.wav output.wav -tempo=-50

img

变速变调

方法一:SOX

需要在linux上运行,具体参考https://github.com/rabitt/pysox

import soundfile
import sox

sr = 16000

tfm = sox.Transformer()     # create transformer
tfm.speed(2)                # 变速2倍

# 创建输出文件
# tfm.build_file("./sample/p225_001.wav", "./sample/pysox_2x.wav")

# 内存中以numpy数组的形式获取输出
array_out = tfm.build_array(input_filepath="./sample/p225_001.wav")
soundfile.write("./sample/pysox_2x.wav",data=array_out,samplerate=sr)

或者我们直接使用原生的sox工具包

$ sox input.wav output.wav speed 1.3 #速度变为原来的1.3倍
$ sox input.wav output.wav speed 0.8 #速度变为原来的0.8倍

img

方法二:librosa

按固定速率对音频系列进行时间拉伸。

def time_stretch(x, rate):
    # rate:拉伸的尺寸,
    # rate > 1 加快速度
    # rate < 1 放慢速度
    return librosa.effects.time_stretch(x, rate)

Augmentation = time_stretch(wav_data, rate=2)

img

我们来观察语谱图和波形图,发现形状变了,并且变速后的语音波形振幅降低了,为什么呢?难道变速还会减少语音的音量?求解答

SpecAugment 通过在时间方向上通过在时间方向上扭曲来增强,并屏蔽(多个)连续时间步长(垂直掩模)和 mel 频率通道(水平掩模)的块

  1. 帮助网络在时间方向上的变形、频率信息的部分丢失和输入的小段语音的部分丢失方面具有鲁棒性
  2. 防止网络过度拟合

SpecAugment 中有三种增强策略:

  • 时间扭曲(Time Warping):在时间轴上随机扭曲频谱图。与速度扰动不同,这种方法不会增加或减少持续时间,而是在局部压缩和拉伸频谱图。
  • 频率掩蔽(Frequency Mask):频谱图的 连续频率bin被随机掩蔽
  • 时间掩蔽(Time Mask):频谱图的 连续时间帧被掩蔽

img

paperwithcode:SpecAugment几乎所有的代码都列出来了

  • tensorflow和pytorch实现:SpecAugment
  • numpy实现:SpecAugment_numpy_scipy
  • numpy实现:SpecAugment (很好理解)

扭曲增强(Warp)

将非线性图像扭曲应用于频谱图。这是通过沿时间和频率轴随机移动均匀分布的扭曲点网格来实现的。代码修改自:DeepSpeech

def tf_pick_value_from_range(value, r, clock=None, double_precision=False):
    clock = (tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64) if clock is None
             else tf.maximum(tf.constant(0.0, dtype=tf.float64), tf.minimum(tf.constant(1.0, dtype=tf.float64), clock)))
    value = tf.random.stateless_uniform([],
                                        minval=value - r,
                                        maxval=value + r,
                                        seed=(clock * tf.int32.min, clock * tf.int32.max),
                                        dtype=tf.float64)
    if isinstance(value, int):
        return tf.cast(tf.math.round(value), tf.int64 if double_precision else tf.int32)
    return tf.cast(value, tf.float64 if double_precision else tf.float32)


def Warp(spectrogram, num_t=1, num_f=1, warp_t=0.1, warp_f=0.0, r=0, clock=0.0):
    """
    :param spectrogram: tensor (batch size,t,f)
    :param num_t: 
    :param num_f: 
    :param warp_t: 
    :param warp_f: 
    :param r: 波动范围
    :param clock: 
    :return: 
    """
    size_t, size_f = spectrogram.shape

    seed = (clock * tf.int32.min, clock * tf.int32.max)

    num_t = tf_pick_value_from_range(num_t, r, clock=clock)
    num_f = tf_pick_value_from_range(num_f, r, clock=clock)

    def get_flows(n, size, warp, r):
        warp = tf_pick_value_from_range(warp, range, clock=clock)
        warp = warp * tf.cast(size, dtype=tf.float32) / tf.cast(2 * (n + 1), dtype=tf.float32)
        f = tf.random.stateless_normal([num_t, num_f], seed, mean=0.0, stddev=warp, dtype=tf.float32)
        return tf.pad(f, tf.constant([[1, 1], [1, 1]]), 'CONSTANT')  # zero flow at all edges

    flows = tf.stack([get_flows(num_t, size_t, warp_t, r), get_flows(num_f, size_f, warp_f, r)], axis=2)
    flows = tf.image.resize_bicubic(tf.expand_dims(flows, 0), [size_t, size_f])
    spectrogram_aug = tf.contrib.image.dense_image_warp(tf.expand_dims(spectrogram, -1), flows)
    spectrogram_aug = tf.reshape(spectrogram_aug, shape=(1, -1, size_f))
    return spectrogram_aug

频率掩膜(Frequency Mask)

在幅度谱随机的将频点置零。有关更多详细信息,请参阅 SpecAugment 论文:SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition

def FreqMask(mag, num_mask=1, mask_percentage=0.01):
    """
    :param mag: (F,T)
    :param num_freq_mask: mask的数量
    :param mask_percentage: mask的百分比 0.001~0.015
    """
    F = mag.shape[0]  # 频点数
    mask_width = int(mask_percentage * F)  # mask的宽度
    for i in range(num_mask):
        mask_start = np.random.randint(low=0, high=F - mask_width)  # mask的index
        mag[mask_start: mask_start + mask_width:] = 0   # 掩码F维度
    return mag

img

时间掩码(Time Mask)

在随机位置将增强样本内的时间间隔设置为零(静音)。代码修改自:DeepSpeech

def TimeMask(mag, num_mask=1, mask_percentage=0.01):
    """
    :param mag: (F,T)
    :param num_freq_mask: mask的数量
    :param mask_percentage: mask的百分比 0.001~0.015
    """
    T = mag.shape[1]  # 频点数
    mask_width = int(mask_percentage * T)  # mask的宽度
    for i in range(num_mask):
        mask_start = np.random.randint(low=0, high=T - mask_width)
        mag[:, mask_start:mask_start + mask_width] = 0  # 掩码T维度
    return mag

img

多领域增强

drop增强

将目标数据表示的随机数据点归零。代码修改自:DeepSpeech

def tf_pick_value_from_range(value, r, clock=None, double_precision=False):
    clock = (tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64) if clock is None
             else tf.maximum(tf.constant(0.0, dtype=tf.float64), tf.minimum(tf.constant(1.0, dtype=tf.float64), clock)))
    value = tf.random.stateless_uniform([],
                                        minval=value - r,
                                        maxval=value + r,
                                        seed=(clock * tf.int32.min, clock * tf.int32.max),
                                        dtype=tf.float64)
    if isinstance(value, int):
        return tf.cast(tf.math.round(value), tf.int64 if double_precision else tf.int32)
    return tf.cast(value, tf.float64 if double_precision else tf.float32)


def Dropout(tensor, rate=0.05, r=0, transcript=None, clock=0.0):
    rate = tf_pick_value_from_range(rate, r, clock=clock)
    rate = tf.math.maximum(0.0, rate)
    factors = tf.random.stateless_uniform(tf.shape(tensor),
                                          (clock * tf.int32.min, clock * tf.int32.max),
                                          minval=0.0,
                                          maxval=1.0,
                                          dtype=tf.float32)
    return tensor * tf.math.sign(tf.math.floor(factors + rate))

添加增强

将从正态分布(均值为 0.0)中选取的随机值添加到目标数据表示的所有数据点。代码修改自:DeepSpeech

def tf_pick_value_from_range(value, r, clock=None, double_precision=False):
    clock = (tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64) if clock is None
             else tf.maximum(tf.constant(0.0, dtype=tf.float64), tf.minimum(tf.constant(1.0, dtype=tf.float64), clock)))
    value = tf.random.stateless_uniform([],
                                        minval=value - r,
                                        maxval=value + r,
                                        seed=(clock * tf.int32.min, clock * tf.int32.max),
                                        dtype=tf.float64)
    if isinstance(value, int):
        return tf.cast(tf.math.round(value), tf.int64 if double_precision else tf.int32)
    return tf.cast(value, tf.float64 if double_precision else tf.float32)


def Add(tensor, stddev=5, r=0, transcript=None, clock=0.0):
    stddev = tf_pick_value_from_range(stddev, r, clock=clock)
    seed = (clock * tf.int32.min, clock * tf.int32.max)
    return tensor + tf.random.stateless_normal(tf.shape(tensor), seed, mean=0.0, stddev=stddev)

乘法增强

将目标数据表示的所有数据点与从正态分布(均值为 1.0)中选取的随机值相乘。代码修改自:DeepSpeech

def tf_pick_value_from_range(value, r, clock=None, double_precision=False):
    clock = (tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64) if clock is None
             else tf.maximum(tf.constant(0.0, dtype=tf.float64), tf.minimum(tf.constant(1.0, dtype=tf.float64), clock)))
    value = tf.random.stateless_uniform([],
                                        minval=value - r,
                                        maxval=value + r,
                                        seed=(clock * tf.int32.min, clock * tf.int32.max),
                                        dtype=tf.float64)
    if isinstance(value, int):
        return tf.cast(tf.math.round(value), tf.int64 if double_precision else tf.int32)
    return tf.cast(value, tf.float64 if double_precision else tf.float32)


def Multiply(self, tensor, stddev=5, r=0, transcript=None, clock=0.0):
    stddev = tf_pick_value_from_range(stddev, r=0, clock=clock)
    seed = (clock * tf.int32.min, clock * tf.int32.max)
    return tensor * tf.random.stateless_normal(tf.shape(tensor), seed, mean=1.0, stddev=stddev)

参考

【python 音频处理库】

  • librosa
  • Pyroomacoustics
  • PythonAudioEffects:专注音效
  • WavAugment
  • Audiogmenter:一个用于音频数据增强的MATLAB工具箱
  • audiomentations:我愿称他为最强王者,专门的数据增强库,很全面,没事可以多看看

【知乎文章】简单地为语音加混响

【国际音频实验室EmanuëlHabets提供的代码】International Audio Laboratories Erlangen

【Image-source method】Image-source method for room acoustics

【Image-source 原理讲解】Image-source Model

【CSDN】变速变调原理与方法总结

【CSDN】音频倍速(变速不变调)的实现

【CSDN】音频变调算法小结

【CSDN】python 音频变调不变速方法

【论文】用于语音识别的音频增强

【论文】SpecAugment:一种简单的自动语音识别数据增强方法

【CSDN】SoX 音频处理工具使用方法

本文转载自作者:凌逆战,地址:https://www.cnblogs.com/LXP-Never/p/13404523.html

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

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

相关文章

3.0 响应式系统的设计与实现

1、Proxy代理对象 Proxy用于对一个普通对象代理&#xff0c;实现对象的拦截和自定义&#xff0c;如拦截其赋值、枚举、函数调用等。里面包含了很多组捕获器&#xff08;trap&#xff09;&#xff0c;在代理对象执行相应的操作时捕获&#xff0c;然后在内部实现自定义。 const…

将PDF文件转换为JPG格式图片的3种简单方法

如何在线将PDF文件转换成图片格式&#xff1f;如果您在使用PDF文件时只需要其中一页或几页的内容&#xff0c;将PDF转换为图片可以使您更方便地使用这些内容。下面介绍三种简单易用的PDF转图片的方法。 方法一&#xff1a;记灵在线工具 记灵在线工具是一个免费的在线PDF转换工…

方太也造车?

听说方太也造车了&#xff1f; 造车闹剧层出不穷 近年来&#xff0c;随着智能汽车概念的风行&#xff0c;各大品牌也掀起了一股造车的热潮。一时间&#xff0c;互联网、房地产、家电、手机……各行各业的企业都纷纷粉墨登场&#xff0c;各种造车闹剧层出不穷。 然而很快人们就发…

【三十天精通Vue 3】第二十七天 如何用Vue 3和TensorFlow.js实现人脸识别Web应用?

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、项目简介1.1 概述1.2 功能特点1.3 技术栈二、准备工作2.1 环境搭建2.2 项目初始化2.3 引入依赖

Bus动态刷新

Bus动态刷新全局广播配置实现 启动 EurekaMain7001ConfigcenterMain3344ConfigclientMain3355ConfigclicntMain3366 运维工程师 修改Gitee上配置文件内容&#xff0c;增加版本号发送POST请求curl -X POST "http://localhost:3344/actuator/bus-refresh" —次发送…

【C++进阶之路】第二篇:多态 抽象类 单继承和多继承关系中的虚函数表

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;多态的概念&#xff0c;多态的构成条件&#xff0c;虚函数重写&#xff0c;C11final和overrid&#xff0c;重…

谈谈我对Edge浏览器分屏功能的使用感受

谈谈我对Edge浏览器分屏功能的使用感受 前言 最近&#xff0c;微软为 Microsoft Edge 浏览器的稳定版本带来了分屏浏览 (Split Screen) 这个新玩意儿&#xff0c;这个功能允许用户在同一个页面以左右视图的形式并排打开两个标签页&#xff0c;类似于软件的分屏。 各位看官如果想…

将经纬度坐标在ArcGIS软件中生成系列矢量数据

目录 环境介绍&#xff1a; 操作内容&#xff1a; 操作步骤&#xff1a; 1、将经纬度坐标值编辑在excel中&#xff0c;注意x、y对应的分别是经度和纬度 2、打开ArcMap软件&#xff0c;加载.xls数据 3、需要选择地理坐标系 4、点矢量数据生成 5、线矢量数据生成 6、面矢量…

2.1 Linux命令行

系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…

Linux多路IO复用:select

1. 多路IO复用 内核监听多个socket文件描述符读写缓冲区属性的变化&#xff0c;若某个文件描述符的读缓冲区有变化&#xff0c;则将该事件告诉应用层。 内核提供多路IO复用的API&#xff1a;select、poll&#xff08;使用较少&#xff09;、epoll。 2. select select原理 用…

设置让Windows每天在指定时间自动关机

其实我们的电脑是可以设置每天在指定的时间点自动关机的&#xff0c;具体操作方法&#xff1a; 1、开打电脑&#xff0c;点击电脑系统左下角windows图标&#xff0c;选择“控制面板”并进入&#xff1b;如图 2、在控制面板界面找到“管理工具”&#xff0c;点击开打&#xff1b…

idea2021.3.x激活教程

第一步: 下载最新的 IDEA 2021.3.3 版本安装包 先从 IDEA 官网下载 IDEA 2021.3.3 版本的安装包&#xff0c;下载链接可以自行百度IDEA官网。 点击下载&#xff0c;耐心等待下载完成。 第二步: 开始安装(已安装可跳过此步骤) 指定安装目录。 勾选创建桌面快捷方式&#xff0…

springboot+java共享厨房租赁信息系统

功能介绍开发环境 springboot是基于spring的快速开发框架, 相比于原生的spring而言, 它通过大量的java config来避免了大量的xml文件, 只需要简单的生成器便能生成一个可以运行的javaweb项目, 是目前最火热的java开发框架 开发语言&#xff1a;Java 框架&#xff1a;springb…

浪潮盒子IPBS9505-多遥控版-S905L/M2芯片-安卓4.4.2-线刷固件包

浪潮盒子IPBS9505-多遥控版-S905L&#xff0f;M2芯片-安卓4.4.2-线刷固件包-内有教程和短接点-当贝纯净桌面。 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&…

微机原理 || 第六章 I/O接口 测试题(答案+解析)

1、下列设备与CPU相连不需要通过接口的是()。 A内存条 B键盘 C U盘. D 硬盘 2、I/O接口电路通常具有()三种端口。 A 数据端口、控制端口、状态端口 (信息分类) 3、以下叙述中&#xff0c;不属于接口功能的是()。 A 提供接口的状态&#xff0c;以便CPU查询 B实现数据格式…

基于vue的毕业生研究生大学生交流学习平台

下面进行系统的功能需求分析。 1.前台功能模块&#xff1a;可以在前台Web浏览器中查看这些功能。 用户注册模块&#xff1a;将用户信息记录到用户表。 用户登录模块&#xff1a;用来区分三种用户&#xff0c;普通用户、普通管理员和超级管理员。 个人信息管理&#xff1a;用户登…

【Linux】Linux安装Maven(图文解说详细版)

文章目录 前言1.去官网下载2.下载完成上传到/opt目录下3.解压缩4.配置环境变量5.刷新配置文件使得配置文件生效6.然后我们运行mvn -v查看是否成功7.出现错误&#xff0c;接下来全程高能带你刨析这个错误&#xff01;8.这里又出现一个坑&#xff0c;就是每次重新进终端的时候mvn…

学习笔记——new关键字在底层究竟做了什么

new关键字&#xff08;操作符&#xff09;在底层究竟做了什么&#xff1f; 一、概念理解 函数调用之前带有关键字new&#xff0c;它就构成了构造函数调用。 与普通函数调用在实参处理、调用上下文、返回值方面不同。 一&#xff09;实参处理 相同点&#xff1a;如果有实参&…

【无标题】每天一道算法练习题--Day24 第一章 --算法专题 --- ----------平衡二叉树专题

力扣关于平衡二叉树的题目还是有一些的&#xff0c;并且都非常经典&#xff0c;推荐大家练习。今天给大家精选了 4 道题&#xff0c;如果你彻底搞明白了这几道题&#xff0c;碰到其他的平衡二叉树的题目应该不至于没有思路。当你领会了我的思路之后&#xff0c; 建议再找几个题…

一文搞懂linux的proc文件

目录 proc文件夹是干嘛用&#xff1f; proc下都有什么系统信息? /proc/bus /proc/buddyinfo /proc/cgroups /proc/cmdline /proc/consoles /proc/cpuinfo /proc/crypto /proc/devices /proc/diskstats /proc/execdomains /proc/fb /proc/filesystems …