基于深度学习网络的语音去噪

这个例子展示了如何使用深度学习网络去噪语音信号。这个例子比较了应用于同一任务的两种类型的网络:全连接网络和卷积网络。

介绍

语音去噪的目的是去除语音信号中的噪声,同时提高语音的质量和可懂度。此示例展示了使用深度学习网络去除语音信号中的洗衣机噪声。该示例比较了应用于同一任务的两种类型的网络:完全连接网络和卷积网络。

问题摘要

考虑以下以8 kHz采样的语音信号。

[cleanAudio,fs]=音频读取(“SpeechDFT-16-8-mono-5秒波形”); 声音(音频,fs)

将洗衣机噪声添加到语音信号中。设置噪声功率,使信噪比(SNR)为零dB。

噪声=音频读取(“洗衣机-16-8-mono-1000秒波浪”);%从噪波文件中的随机位置提取噪波段= randi(numel(noise) - numel(cleanAudio) + 1,1,1);noiseSegment = noise(ind:ind + numel(cleanAudio) - 1);speechPower =总和(cleanAudio。^ 2);noisePower =总和(noiseSegment。^ 2);noisyAudio = cleanAudio + sqrt(speechPower/noisePower) * noisessegment;

听嘈杂的语音信号。

声音(noisyAudio fs)

将原始信号和噪声信号可视化。

t=(1/fs)*(0:numel(cleanAudio)-1;子地块(2,1,1)地块(t,cleanAudio)标题(“干净的音频”)网格次要情节(2,1,2)情节(t, noisyAudio)标题(“嘈杂的音频”)包含(“时间”)网格

语音去噪的目的是从语音信号中去除洗衣机噪声,同时最小化输出语音中不希望出现的伪影。

检查数据集

本例使用Mozilla通用语音数据集[1]培训和测试深度学习网络。该数据集包含48千赫的短句录音。下载数据集并卸载下载的文件。设置路径数据库到数据的位置。

datafolder=PathToDatabase;

使用音频数据存储为数据集中的所有文件创建数据存储。

ads0=音频数据存储(完整文件(数据文件夹,“剪辑”));

使用可读从培训集中读取与音频文件关联的元数据。元数据包含在列车文件。检查元数据的前几行。

元数据= readtable (fullfile (datafolder“train.tsv”),“文件类型”,“文本”); 总目(元数据)
ans=8×8表client_id路径生成句子up_votes down_votes年龄性别口音  ____________________________________________________________________________________________________________________________________ ________________________________ ____________________________________________________________________________________________ ________ __________{'common_voice_en_19664034.mp3'}{'这些数据组件依次充当数据交换的“构建块”。{' 30 '} {'male'} 0×0 char}{'该教会与犹太复国主义的政治运动没有任何关系。'} 3 0 {' 30s '} {'male'} {0×0 char} {' 4f29be8fe932d773576dd3df5e111929f4e2224223224503695eaa8625a12659cd3e999a061a29ebe71783833bebdc2d0ec6b97e9a648bf6d28979065f85ad '} {'common_voice_en_19664037.mp3'}{'以下表示的架构已在某一点或另一点使用。此外,脉冲输出可以直接通过三个谐振器组中的一个。{' 30 '} {'male'} {0×0 char}{'两个人被一个在赌博中输了的扒手抢劫了。'} 3 0 {' 30s '} {'male'} {0×0 char} {' 4f3b69348cb65923dff20efe0eaef4fbc8797f9c2240447ae48e36fab63867dbf6947bfb8ff623cab4f1d1e185ac79ce3975f98a0f57f90b9ce9bdbbe95fd '} {'common_voice_en_19742944.mp3'}{'它的县所在地是凤凰城。'} 2 0 {0×0 char} {0×0 char} {0×0 char}{'4f3b69348cb65923dff20efe0eaef4fbc8797f9c2240447ae48764e36fab63867dbf6947bfb8ff623cab4f1d1e185ac79ce3975f98a0f57f90b9ce9bdbbe95fd'} {'common_voice_en_19742945.mp3'} {'Consequently, the diocese accumulated millions of dollars in debt.' } 2 0 {0×0 char } {0×0 char} {0×0 char} {'4f3b69348cb65923dff20efe0eaef4fbc8797f9c2240447ae48764e36fab63867dbf6947bfb8ff623cab4f1d1e185ac79ce3975f98a0f57f90b9ce9bdbbe95fd'} {'common_voice_en_19742948.mp3'} {'The song "Kodachrome" is named after the Kodak film of the same name.' } 2 0 {0×0 char } {0×0 char} {0×0 char}

在数据存储中查找与训练集对应的文件。

csvFiles=metadata.path;adsFiles=ads0.Files;[~,adsFiles,ext]=cellfun(@(x)fileparts(x),adsFiles,“UniformOutput”,false);[~,indA]=相交(strcat(adsFiles,ext),csvFiles);

从大数据集创建子集训练集。

ads=子集(ads0,indA);

你将在文件的子集上训练深度学习网络。创建一个包含该数据存储的前1000个文件的数据存储子集。

numFilesInSubset=1000;ads=子集(ads,1:numFilesInSubset);

使用获取数据存储中第一个文件的内容。

[音频,adsInfo]=读取(ads);

听语音信号。

声音(音频、adsInfo.SampleRate)

绘制语音信号。

图t=(1/adsInfo.SampleRate)*(0:numel(音频)-1);绘图(t,音频)标题(“例如语音信号”)包含(“时间”)网格

深度学习系统概述

基本的深度学习训练方案如下图所示。请注意,由于语音通常低于4khz,您首先将干净和嘈杂的音频信号采样到8khz,以减少网络的计算负载。预测器和目标网络信号分别是噪声和纯净音频信号的幅值谱。网络的输出是去噪后信号的幅值谱。回归网络使用预测输入来最小化其输出和输入目标之间的均方误差。去噪后的音频通过输出幅度谱和噪声信号的相位被转换回时域[2].

使用短时傅里叶变换(STFT)将音频变换到频域,窗口长度为256个样本,重叠率为75%,并使用汉明窗口。通过删除对应于负频率的频率样本(因为时域语音信号是真实的,这不会导致任何信息丢失),可以将频谱向量的大小减小到129。预测器输入由8个连续的带噪STFT向量组成,因此每个STFT输出估计是基于当前带噪STFT和7个先前带噪STFT向量计算的。

短期融资目标和预测因素

本节说明如何从一个训练文件生成目标和预测信号。

一、定义系统参数:

windowLength=256;win=hamming(windowLength,“定期”);重叠=圆形(0.75*windowLength);FFT长度=windowLength;inputFs=48e3;fs=8e3;numFeatures=FFT长度/2+1;numSegments=8;

创建一个数字信号处理器对象将48 kHz音频转换为8 kHz。

src=dsp.0转换器(“输入采样器”,输入,...“OutputSampleRate”,财政司司长,...“带宽”,7920);

使用从数据存储中获取音频文件的内容。

音频=读取(广告);

确保音频长度是采样率转换器抽取因子的倍数。

决策系数=输入系数/fs;L=楼层(numel(音频)/决策系数);音频=音频(1:决策系数*L);

将音频信号转换为8 kHz。

音频=src(音频);重置(src)

从洗衣机噪声矢量创建随机噪声段。

Randind = randi(numel(noise) - numel(audio),[1 1]);noise = noise(randind: randind + numel(audio) - 1);

在语音信号中加入噪声,使其信噪比为0 dB。

noisePower =总和(noiseSegment。^ 2);cleanPower =总和(音频。^ 2);* sqrt(cleanPower/noisePower);noisyAudio = audio + noisessegment;

使用stft从原始和噪声音频信号生成幅值STFT向量。

cleanSTFT=stft(音频,“窗口”,赢,“OverlapLength”,重叠,“FFTLength”,fft长度);cleanSTFT=abs(cleanSTFT(numFeatures-1:end,:);noisySTFT=stft(noisyAudio,“窗口”,赢,“OverlapLength”,重叠,“FFTLength”,ffTLength);noisestft=abs(noisestft(numFeatures-1:end,:);

从有噪声的STFT生成8段训练预测信号。连续预测值之间的重叠为7段。

noisestft=[noisestft(:,1:numSegments-1),noisestft];stftSegments=0(numFeatures,numSegments,size(noisestft,2)-numSegments+1);对于索引=1:size(noisySTFT,2)-numSegments+1 stftSegments(:,:,index)=(noisySTFT(:,index:index+numSegments-1));结束

设定目标和预测因素。两个变量的最后一个维度对应于由音频文件生成的不同预测器/目标对的数量。每个预测器是129乘8,每个目标是129乘1。

目标=cleanSTFT;规模(目标)
ans=1×2129 334
预测值=标准时间段;规模(预测因素)
ans=1×3129 8 334

使用高数组提取特征

为了加快处理速度,使用高数组从数据存储中所有音频文件的语音片段中提取特征序列。与内存中的数组不同,在调用聚集此延迟评估使您能够快速处理大型数据集。当您最终使用聚集, MATLAB在可能的情况下结合了排队计算,并获取通过数据的最小次数。如果您有Parallel Computing Toolbox™,您可以在本地MATLAB会话或本地并行池中使用高数组。如果您已经安装了MATLAB®Parallel Server™,您还可以在集群上运行高数组计算。

首先,将数据存储转换为高数组。

重置(ads)T=高度(ads)
使用连接到并行池的“本地”配置文件启动并行池(parpool)(工作线程数:6)。T=M×1高单元阵列{369264×1 double}{129648×1 double}{142320×1 double}{203376×1 double}{213744×1 double}{190704×1 double}{160752×1 double}{193008×1 double}:::

显示表明行数(与数据存储中的文件数相对应)M未知。M是占位符,直到计算完成。

从tall表格中提取目标和预测器幅值STFT。此操作将创建新的tall数组变量以用于后续计算。函数HelperGenerateSpeechDenoisingFeatures执行中已突出显示的步骤短期融资目标和预测因素部分。的赛尔芬命令适用于HelperGenerateSpeechDenoisingFeatures添加到数据存储中每个音频文件的内容。

[targets,predictors]=cellfun(@(x)HelperGenerateSpeechDenoisingFeatures(x,noise,src),T,“统一输出”、假);

使用聚集评估目标和预测值。

[目标,预测值]=聚集(目标,预测值);
使用并行池“local”评估tall表达式:-通过1/1:在50秒内完成评估在1分钟48秒内完成

将所有特征标准化为零均值和统一标准差是一种很好的做法。

分别计算预测值和目标值的平均值和标准偏差,并使用它们来规范化数据。

预测=猫({}):3,预测指标;noisyMean =意味着(预测(:));noisyStd =性病(预测(:));predictors(:) = (predictors(:) - noisyMean)/noisyStd;目标=猫({}):2、目标;cleanMean =意味着(目标(:));cleanStd =性病(目标(:));targets(:) = (targets(:) - cleanMean)/cleanStd;

将预测因素和目标重塑为深度学习网络所期望的维度。

预测=重塑(预测、大小(预测,1),大小(预测,2),1,大小(预测,3));目标=重塑(目标1 1、大小(目标1),大小(目标2));

您将在培训期间使用1%的数据进行验证。验证可用于检测网络过度拟合培训数据的情况。

将数据随机分割为训练集和验证集。

inds=randperm(大小(预测器,4));L=round(0.99*大小(预测器,4));TrainPredicts=Predicts(:,:,:,inds(1:L));trainTargets=targets(:,:,:,:,inds(1:end));validateTargets=targets(:,:,:,inds(1:end));

全连接层语音去噪

首先考虑由完全连接的层组成的去噪网络。完全连接层中的每个神经元都与前一层的所有激活相连接。一个完全连接的层将输入乘以一个权重矩阵,然后添加一个偏置向量。权重矩阵和偏差向量的维数由该层神经元的数量和前一层激活的数量决定。

定义网络的层。将输入大小指定为图像大小NUM特征-借-NumSegments(本例中为129×8)。定义两个隐藏的完全连接层,每个层有1024个神经元。由于是纯线性系统,每个隐藏的完全连接层后面都有一个校正的线性单元(ReLU)层。批量规范化层规范化输出的平均值和标准偏差。添加一个包含129个神经元的完全连接层,然后是回归层。

layers = [imageInputLayer([numFeatures,numSegments]) fulllyconnectedlayer (1024) batchNormalizationLayer relullayer fulllyconnectedlayer (1024) batchNormalizationLayer relullayer fulllyconnectedlayer (numFeatures) regressionLayer];

接下来,指定网络的培训选项。设置最大时代使网络通过训练数据进行3次传递。设置小批量128这样网络一次可以查看128个训练信号。指定阴谋作为“训练进步”生成随迭代次数增加而显示训练进度的绘图。设置冗长的假的禁用将与绘图中显示的数据相对应的表输出打印到命令行窗口。指定洗牌作为“每个时代”在每个历元开始时洗牌训练序列。指定学习进度表“分段”每次经过一定数量的纪元(1)时,将学习率降低指定的系数(0.9)。设置验证数据到验证预测因子和目标。集ValidationFrequency以便每个历元计算一次验证均方误差。这个例子使用自适应矩估计(Adam)求解器。

miniBatchSize = 128;选项=培训选项(“亚当”,...“最大时代”,3,...“初始学习率”1 e-5...“最小批量大小”,小批量,...“洗牌”,“每个时代”,...“情节”,“训练进步”,...“冗长”假的,...“ValidationFrequency”、地板(大小(trainPredictors, 4) / miniBatchSize),...“LearnRateSchedule”,“分段”,...“LearnRateDropFactor”,0.9,...“LearnRateDropPeriod”,1,...“验证数据”,{validatePredictors,validateTargets});

使用指定的培训选项和层体系结构培训网络列车网络. 由于训练集很大,训练过程可能需要几分钟。要加载预先训练的网络而不是从头开始训练网络,请设置溺爱假的

溺爱=真正的;如果doTraining denoiseNetFullyConnected = trainNetwork(trainPredictors,trainTargets,layers,options);其他的s=荷载(“denoisenet.mat”); denoiseNetFullyConnected=s.denoiseNetFullyConnected;cleanMean=s.cleanMean;cleanStd=s.cleanStd;Noisyman=s.Noisyman;noisestd=s.noisestd;结束

计算网络完全连接层中的权重数。

重量=0;对于索引=1:numel(denoiseNetFullyConnected.Layers)如果isa(表示完全连接的层(索引),“nnet.cnn.layer.FullyConnectedLayer”)numWeights=numWeights+nummel(表示完全连接的层(索引).Weights);结束结束fprintf(“权重数为%d。\n”,单位重量);
配重的数量是2237440。

基于卷积层的语音去噪

考虑一个使用卷积层而不是完全连接层的网络[].二维卷积层对输入应用滑动滤波器。该层通过沿输入垂直和水平移动滤波器,计算权重和输入的点积,然后添加偏差项,从而卷积输入。卷积层通常比完全连接层包含更少的参数。

定义中所述的完全卷积网络的层[,由16个卷积层组成。前15个卷积层为3层一组,重复5次,滤波器宽度分别为9、5、9,滤波器数量分别为18、30、8。最后一个卷积层的滤镜宽度为129和1。在该网络中,只在一个方向(沿频率维度)进行卷积,除第一层外,所有层沿时间维度的滤波器宽度均设为1。与全连接网络类似,卷积层之后是ReLu层和批处理归一化层。

images = [imageInputLayer([numFeatures,numSegments]))“跨步”100年[1],“填充”,“相同”)batchNormalizationLayer reluLayer repmat(...30岁的[convolution2dLayer (1 [5]“跨步”100年[1],“填充”,“相同”)batchNormalizationLayer reluLayer卷积2Dlayer([9 1],8,“跨步”100年[1],“填充”,“相同”)batchNormalizationLayer reluLayer卷积2Dlayer([9 1],18,“跨步”100年[1],“填充”,“相同”) batchNormalizationLayer reluLayer],4,1) convolution2dLayer([5 1],30,“跨步”100年[1],“填充”,“相同”)batchNormalizationLayer reluLayer卷积2Dlayer([9 1],8,“跨步”100年[1],“填充”,“相同”)batchNormalizationLayer reluLayer卷积2Dlayer([129 1],1,“跨步”100年[1],“填充”,“相同”) regressionLayer);

训练选项与全连接网络的选项相同,除了验证目标信号的维度被排列成与回归层预期的维度一致。

选项=培训选项(“亚当”,...“最大时代”,3,...“初始学习率”1 e-5...“最小批量大小”,小批量,...“洗牌”,“每个时代”,...“情节”,“训练进步”,...“冗长”假的,...“ValidationFrequency”、地板(大小(trainPredictors, 4) / miniBatchSize),...“LearnRateSchedule”,“分段”,...“LearnRateDropFactor”,0.9,...“LearnRateDropPeriod”,1,...“验证数据”,{validatePredictors,permute(validateTargets,[3 1 2 4])});

使用指定的培训选项和层体系结构培训网络列车网络. 由于训练集很大,训练过程可能需要几分钟。要加载预先训练的网络而不是从头开始训练网络,请设置溺爱假的

溺爱=真正的;如果DotTraining DenoiseFullyConvolutional=列车网络(列车预测器、排列(列车目标[3 1 2 4])、层、选项);其他的s=荷载(“denoisenet.mat”); denoiseNetFullyConvolutional=s.denoiseNetFullyConvolutional;cleanMean=s.cleanMean;cleanStd=s.cleanStd;Noisyman=s.Noisyman;noisestd=s.noisestd;结束

计算网络完全连接层中的权重数。

重量=0;对于索引=1:numel(denoiseNetFullyConvolutional.Layers)如果isa(非完整协同进化层(索引),“nnet.cnn.layer.Convolution2DLayer”)numWeights=numWeights+numel(denoiseNetFullyConvolutional.Layers(index).Weights);结束结束fprintf(“卷积层中的权重数为%d\n”,单位重量);
卷积层中的权重数为31812

测试去噪网络

您将使用与培训数据集相同的方法创建验证数据集可读函数读取与验证文件关联的元数据。

元数据= readtable (fullfile (datafolder“test.tsv”),“文件类型”,“文本”);

在数据存储中找到验证文件。

csvFiles=metadata.path;adsFiles=ads0.Files;[~,adsFiles,ext]=cellfun(@(x)fileparts(x),adsFiles,“UniformOutput”,false);[~,indA]=相交(strcat(adsFiles,ext),csvFiles);

从大型数据存储创建验证数据存储。

ads=子集(ads0,indA);

创建包含数据存储的前100个文件的数据存储子集。

ads=子集(ads,1:100);

洗牌数据存储中的文件。

ads=洗牌(ads);

从数据存储中读取文件的内容。

[cleanAudio,adsInfo]=读取(ads);

确保音频长度是采样率转换器抽取因子的倍数。

L=地板(numel(cleanAudio)/decimationFactor);cleanAudio=cleanAudio(1:decimationFactor*L);

将音频信号转换为8 kHz。

cleanAudio=src(cleanAudio);reset(src)

在此测试阶段,您将使用培训阶段未使用的洗衣机噪音破坏语音。

噪声=音频读取(“洗衣机-16-8-mono-200秒波浪”);

从洗衣机噪声矢量创建随机噪声段。

randind=randi(numel(噪音)-numel(清洁音频),[1]);noiseSegment=noise(randind:randind+numel(清洁音频)-1);

在语音信号中加入噪声,使其信噪比为0 dB。

noisePower=sum(noiseSegment.^2);cleanPower=sum(cleanAudio.^2);noiseSegment=noiseSegment.*sqrt(cleanPower/noisePower);NoiseAudio=cleanAudio+noiseSegment;

使用stft从噪声音频信号生成幅值STFT向量。

noisestft=stft(noiseyaudio,“窗口”,赢,“OverlapLength”,重叠,“FFTLength”,ffTLength);NoisePhase=角度(NoiseStft(numFeatures-1:end,:);NoiseStft=abs(NoiseStft(numFeatures-1:end,:);

从有噪声的STFT生成8段训练预测信号。连续预测值之间的重叠为7段。

noisySTFT = [noisySTFT(:,1:numSegments-1) noisySTFT];predictors = 0 (numFeatures, numSegments, size(noisySTFT,2) - numSegments + 1);对于索引=1:(大小(noisestft,2)-numSegments+1)预测值(:,:,index)=noisestft(:,index:index+numSegments-1);结束

通过在训练阶段计算的平均值和标准偏差对预测值进行标准化。

预测因子(:)=(预测因子(:)-noisyman)/noisyStd;

使用预测通过两个训练有素的网络。

predictors =重塑(predictors, [numFeatures,numSegments,1,size(predictors,3)]);STFTFullyConnected = predict(denoiseNetFullyConnected, predictors);STFTFullyConvolutional = predict(denoiseNetFullyConvolutional, predictors);

根据培训阶段使用的平均值和标准偏差调整输出。

STFTFullyConnected(:)=cleanStd*STFTFullyConnected(:)+cleanMean;STFTFullyConvolutional(:)=清洁标准*STFTFullyConvolutional(:)+清洁平均值;

将单侧短时傅里叶变换为中心短时傅里叶变换。

STFTFullyConnected=STFTFullyConnected.*exp(1j*噪声相位);STFTFullyConnected=[conj(STFTFullyConnected(end-1:-1:2,:);STFTFullyConnected];STFTFullyConvolutional=挤压(STFTFullyConvolutional)。*exp(1j*噪声相位);STFTFullyConvolutional=[conj(STFTFullyConvolutional(end-1:-1:2,:);STFTFullyConvolutional];

计算去噪语音信号。伊斯特夫特执行逆STFT。使用带噪STFT向量的相位重建时域信号。

DenoiseDaudoullyConnected=istft(STFTFullyConnected,...“窗口”,赢,“OverlapLength”,重叠,...“FFTLength”,fft长度,“共轭对称”,对);DenoiseDaudoullyConvolutional=istft(STFTFullyConvolutional,...“窗口”,赢,“OverlapLength”,重叠,...“FFTLength”,fft长度,“共轭对称”,真正的);

绘制干净、嘈杂和去噪的音频信号。

t=(1/fs)*(0:numel(denoisedAudioFullyConnected)-1);图子图(4,1,1)图(t,cleanAudio(1:numel(denoisedAudioFullyConnected)))标题(“干净的演讲》)网格子地块(4,1,2)地块(t,noisyAudio(1:numel(DenoiseDaudoully连通)))名称(“嘈杂的演讲”)网格子地块(4,1,3)地块(t,表示完全连接)名称(“去噪语音(完全连接的层)”)网格子地块(4,1,4)地块(t,DenoiseDaudoullyConvolutional)名称(“去噪语音(卷积层)”)网格xlabel(“时间”)

绘制干净、嘈杂和去噪的光谱图。

h=图;子图(4,1,1)频谱图(cleanAudio、win、overlap、ffTLength、fs);标题(“干净的演讲》)网格子批次(4,1,2)光谱图(“嘈杂的演讲”)网格次要情节(4 1 3)谱图(ffTLength denoisedAudioFullyConnected,赢,重叠,fs);标题(“去噪语音(完全连接的层)”)网格子批次(4,1,4)光谱图(DenoiseDaudoullyConvolutional、win、overlap、ffTLength、fs);标题(“去噪语音(卷积层)”)网格p=get(h,“位置”);设置(h,“位置”,[p(1) 65 p(3) 800]);

听这嘈杂的演讲。

声音(noisyAudio fs)

通过完全连接的层从网络收听经过去噪的语音。

声音(denoisedAudioFullyConnected fs)

通过卷积层收听来自网络的去噪语音。

声音(DenoiseDaudoullyConvolutional,fs)

听干净的演讲。

声音(音频,fs)

您可以通过调用测试去噪网. 该函数生成上面突出显示的时域和频域图,并返回干净、嘈杂和去噪的音频信号。

[cleanAudio, noisyAudio denoisedAudioFullyConnected denoisedAudioFullyConvolutional] = testDenoisingNets(广告、denoiseNetFullyConnected denoiseNetFullyConvolutional、noisyMean noisyStd, cleanMean, cleanStd);

实时应用

上一节的程序将噪声信号的整个频谱传递到预测.这不适用于要求低延迟的实时应用程序。

运行speechDenoisingRealtimeApp例如,如何模拟流式实时版本的去噪网络。该应用程序使用具有完全连接层的网络。音频帧长度等于STFT跃点大小,即0.25*256=64个样本。

speechDenoisingRealtimeApp启动用户界面(UI)设计用于与模拟交互。用户界面允许您调整参数,结果立即反映在模拟中。您还可以启用/禁用对去噪输出进行操作的噪声门,以进一步降低噪声,以及调整噪声门的攻击时间、释放时间和阈值。您可以收听来自用户界面的嘈杂、干净或去噪音频。

示波器绘制干净的、有噪声的和去噪的信号,以及噪声门的增益。

工具书类

[1]https://voice.mozilla.org/en

[2]“基于深度学习的语音去噪实验”,Ding Liu, Paris Smaragdis, Minje Kim, INTERSPEECH, 2014。

[3] “用于语音增强的完全卷积神经网络”,Se Rim Park,李金元,INTERSPEECH,2017年。