主要内容

端到端深度语音分离

这个例子展示了一个用于与说话者无关的语音分离的端到端深度学习网络。

介绍

语音分离是一项具有挑战性和关键的语音处理任务。最近已经提出了一些基于深度学习的语音分离方法,其中大部分依赖于时域音频混合的时频变换(参见鸡尾酒会源分离使用深度学习网络(音频工具箱)这样一个深度学习系统的实现)。

基于时频方法的解决方案有两个主要的缺点:

  • 将时频表示转换回时域需要相位估计,这会引入误差并导致不完美的重构。

  • 相对较长的窗口需要产生高分辨率的频率表示,这导致了高计算复杂度和无法接受的实时场景延迟。

在本例中,您将探索一个深度学习语音分离网络(基于[1]),它直接作用于音频信号,并绕过时频转换产生的问题。

使用预训练网络分离语音

下载预训练网络

在从头开始训练深度学习网络之前,你会使用预先训练过的网络版本,将两个说话者从一个示例混合信号中分离出来。

首先,下载预训练的网络和示例音频文件。

downloadFolder = matlab.internal.examples.downloadSupportFile (“音频”,“speechSeparation.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) netFolder = fullfile(dataFolder,“speechSeparation”);

准备测试信号

加载对应于两个不同扬声器的两个音频信号。两个信号都在8 kHz采样。

Fs = 8000;s1 = audioread (fullfile (netFolder“speaker1.wav”));s2 = audioread (fullfile (netFolder“speaker2.wav”));

正常信号。

s1 = s1 / max (abs (s1));s2 = s2 / max (abs (s2));

每个信号听几秒钟。

T = 5;声音(s1 (1: T * Fs))暂停(T)
声音(s2 (1: T * Fs))暂停(T)

将两个信号合并为混合信号。

混合= s1 + s2;混合=混合/ max (abs(混合));

听听混音信号的前几秒。

声音(混合(1:T * Fs))暂停(T)

独立的人

加载预训练的语音分离网络参数。

负载(fullfile (netFolder“paramsBest.mat”),“可学的”,“州”)

将混合信号中的两个说话者分开,调用separateSpeakers函数。

(z1 (z2) = separateSpeakers(混合,可学的,州,假);

听第一个估计语音信号的前几秒。

声音(z1 (1: T * Fs))暂停(T)

听第二个估计信号。

声音(z2 (1: T * Fs))暂停(T)

为了说明语音分离的效果,将估计的和原始的分离信号与混合信号一起绘制出来。

s1 = s1(1:长度(z1));s2 = s2(1:长度(z2));混合=混合(1:长度(s1));t =(0:长度(s1) 1) / Fs;图;次要情节(311)情节(t, s1)情节(t, z1)网格传奇('Speaker 1 - Actual','Speaker 1 - Estimated')子图(312)图(t,s2) hold住情节(t, z2)网格传奇('Speaker 2 - Actual',“演讲者2号-估计”) subplot(313) plot(t,mix)网格传奇(“混合”)包含(“时间(s)”)

对比一个时频转换深度学习网络

接下来,你将网络的性能与开发的网络进行比较鸡尾酒会源分离使用深度学习网络(音频工具箱)的例子。这种语音分离网络基于音频混合的传统时频表示(使用短时傅里叶变换,STFT,和短时傅里叶反变换,ISTFT)。

下载预训练的网络。

downloadFolder = matlab.internal.examples.downloadSupportFile (“音频”,“CocktailPartySourceSeparation.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) cocktailNetFolder = fullfile(dataFolder,“CocktailPartySourceSeparation”);

这个函数separateSpeakersTimeFrequency封装使用此网络分离语音所需的步骤该函数执行以下步骤:

  • 计算输入时域混合的量级STFT。

  • 通过传递STFT到网络,计算一个软时频掩码。

  • 通过混合STFT乘以掩码,计算分离信号的STFT。

  • 使用ISTFT重构时域分离信号。使用混合STFT的相位。

指的是鸡尾酒会源分离使用深度学习网络(音频工具箱)例如了解更多关于this network的详细信息。

分开两个音箱。

(y1, y2) = separateSpeakersTimeFrequency(混合,cocktailNetFolder);

听第一个分离信号。

声音(y1 (1: Fs * T))暂停(T)

听第二个分离的信号。

声音(y2 (1: Fs * T))暂停(T)

使用SI-SNR评估网络性能

您将使用尺度不变的源噪声比(SI-SNR)客观度量[1]来比较两个网络。

用端到端网络计算第一个扬声器的SISNR。

首先,将实际信号和估计信号归一化。

S10 = s1 -均值(s1);Z10 = z1 - mean(z1);

计算信噪比的“信号”分量。

T = sum(s10.*z10) .*z10 ./ (sum(z10.^2)+eps);

计算信噪比的“噪声”分量。

N = s1 - t;

现在计算SI-SNR(单位为dB)。

v1 = 20 *日志(√总和(t ^ 2)) + eps)。/√(((n ^ 2)总和)+ eps)) /日志(10);流(“端到端网络- Speaker 1 SISNR: %f dB\n”v1)
端到端网络- Speaker 1 SISNR: 14.316869 dB

SI-SNR计算步骤封装在函数中SISNR。使用该函数计算第二扬声器端到端网络的SI-SNR。

v2 = SISNR (z2, s2);流('端到端网络- Speaker 2 SISNR: %f dB\n'v2)
端到端网络- Speaker 2 SISNR: 13.706421 dB

接下来,为基于stft的网络计算每个扬声器的SI-SNR。

w1 = SISNR (y1, s1(1:长度(y1)));w2 = SISNR (y2, s2(1:长度(y2)));流('STFT网络-扬声器1 SISNR: %f dB\n'w1)
STFT网络-扬声器1 SISNR: 7.003790 dB
流('STFT网络-扬声器2 SISNR: %f dB\n'w2)
STFT网络- Speaker 2 SISNR: 7.382209 dB

训练语音分离网络

检查网络架构

Capture.PNG

该网络基于[1],由编码、掩码估计或分离和解码三个阶段组成。

  • 编码器使用卷积层将时域输入混合信号转换为中间表示。

  • 掩码估计器计算每个扬声器一个掩码。每个扬声器的中间表示是通过将编码器的输出乘以其各自的掩码得到的。掩码估计器由32块卷积层和归一化层组成,块之间有跳跃式连接。

  • 解码器使用转置卷积层将中间表示转换为时域分离的语音信号。

网络的操作被封装在separateSpeakers

可选地减少数据集大小

用整个数据集训练网络,并达到尽可能高的精度,set .reduceDataset为假。要快速运行此示例,设置reduceDataset为true。这将只在少数文件上运行示例的其余部分。

reduceDataset = true;

下载训练数据集

你使用LibriSpeech数据集[2]的一个子集来训练网络。LibriSpeech数据集是一个在16 kHz采样的大型读英语语音语料库。数据来源于从LibriVox项目中读取的有声读物。

下载LibriSpeech数据集。如果reduceDataset是真的,这一步就跳过了。

downloadDatasetFolder = tempdir;datasetFolder = fullfile (downloadDatasetFolder,“LibriSpeech”,“培训-清洗- 360”);如果~ reduceDataset文件名=“火车——清洁- 360. tar.gz”;url =“http://www.openSLR.org/resources/12/”+文件名;如果~ datasetExists (datasetFolder) gunzip (url, downloadDatasetFolder);unzippedFile = fullfile (downloadDatasetFolder,文件名);解压(unzippedFile {1} (1: end-3) downloadDatasetFolder);结束结束

预处理数据集

LibriSpeech数据集由单个扬声器的大量音频文件组成。它不包含2人或2人以上同时说话的混合信号。

您将处理原始数据集,以创建一个适合训练语音分离网络的新数据集。

创建训练数据集的步骤封装在createTrainingDataset。该函数创建由两个随机说话者的话语组成的混合信号。。该函数返回三个音频数据存储:

  • mixDatastore指向混合文件(两个说话者同时说话)。

  • speaker1Datastore指向包含混合物中第一个说话者的孤立语音的文件。

  • speaker2Datastore指的是包含混合物中第二个说话者的孤立讲话的文件。

定义小批量大小和最大训练信号长度(以样本数量为单位)。

miniBatchSize = 2;时间= 2 * 8000;

创建训练数据集。

[mixDatastore, speaker1Datastore speaker2Datastore] = createTrainingDataset (netFolder、datasetFolder downloadDatasetFolder, reduceDataset, miniBatchSize,持续时间);
启动并行池(parpool)使用“本地”配置文件…连接到平行池(工人人数:6)。

结合数据存储。这可以确保当你在训练循环中每个新历的开始打乱文件时,它们保持正确的顺序。

ds =结合(mixDatastore speaker1Datastore speaker2Datastore);

从数据存储中创建一个小批处理队列。

mqueue = minibatchqueue (ds,“MiniBatchSize”miniBatchSize,“OutputEnvironment”,“cpu”,“OutputAsDlarray”、假);

指定培训选项

定义训练参数。

训练10个时代。

如果reducedatset numEpochs = 1;其他的numEpochs = 10;% #好吧结束

指定Adam优化的选项。设置初始学习率为1e-3。使用0.9的梯度衰减因子和0.999的平方梯度衰减因子。

learnRate = 1 e - 3;averageGrad = [];averageSqGrad = [];gradDecay = 0.9;sqGradDecay = 0.999;

在GPU上训练,如果有的话。使用GPU需要并行计算工具箱™。

executionEnvironment =“汽车”;%更改为“cpu”,在cpu上进行训练。

设置验证数据

您将使用之前使用的测试信号来测试预训练的网络,以在训练期间定期计算验证SI-SNR。

如果有可用的GPU,将验证信号移动到该GPU上。

= dlarray(混合,混合“渣打银行”);如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”混合= gpuArray(混合);结束

定义验证SI-SNR计算之间的迭代次数。

numIterPerValidation = 50;

定义一个向量来保存每次迭代的验证SI-SNR。

valSNR = [];

定义一个变量来保存最佳验证SI-SNR。

bestSNR =无穷;

定义一个变量来保存发生最佳验证分数的纪元。

bestEpoch = 1;

初始化网络

初始化网络参数。可学的是一个包含来自网络层的可学习参数的结构。是包含来自归一化层的状态的结构。

(可学的,州)= initializeNetworkParams;

培训网络

执行训练循环。这可能要花好几个小时。

请注意,没有一种先验方法来将估计的输出说话人信号与预期的说话人信号关联起来。这是通过使用话语级排列不变训练(uPIT)[1]来解决的。损失是基于计算SI-SNR。uPIT将输出和目标之间的所有排列的损失最小化。它在函数中定义uPIT

验证SI-SNR定期计算。如果SI-SNR是迄今为止最好的值,则网络参数保存为params.mat

迭代= 0;%遍历epoch。jj = 1: numEpochs%洗牌数据洗牌(mqueue);hasdata (mqueue)%定期计算验证损耗/信噪比如果mod(迭代,numIterPerValidation)==0 [z1,z2] = separateSpeakers(mix, learnables,states,false);l = uPIT (z2 z1, s1, s2);valSNR结束(+ 1)= l;% #好吧如果l > bestSNR bestSNR = l;bestEpoch = jj;文件名=“params.mat”;保存(文件名,“可学的”,“州”);结束结束迭代=迭代+ 1;%获取新的一批训练数据[mixBatch, x1Batch x2Batch] =下一个(mqueue);mixBatch =重塑(mixBatch,[duration 1 miniBatchSize]);x1Batch =重塑(x1Batch,[duration 1 miniBatchSize]);x2Batch =重塑(x2Batch,[duration 1 miniBatchSize]);mixBatch = dlarray (mixBatch,“渣打银行”);x1Batch = dlarray (x1Batch,“渣打银行”);x2Batch = dlarray (x2Batch,“渣打银行”);如果(executionEnvironment = =“汽车”&& canUseGPU) || executionEnvironment ==“图形”x1Batch = gpuArray (x1Batch);x2Batch = gpuArray (x2Batch);mixBatch = gpuArray (mixBatch);结束%使用dlfeval和modelLoss函数评估模型梯度和状态。[~、渐变州]= dlfeval (@modelLoss、mixBatch x1Batch, x2Batch,可学的,州,miniBatchSize);%使用ADAM优化器更新网络参数。[可学的,averageGrad averageSqGrad] = adamupdate(可学的、渐变averageGrad averageSqGrad,迭代,learnRate, gradDecay, sqGradDecay);结束%如果验证准确率没有提高,则降低学习率%在epoch期间如果bestEpoch ~= jj learnRate = learnRate/2;结束结束

绘制验证信噪比值。

如果~reduceDataset valIterNum = 0:长度(valSNR)-1;图semilogx (valSNR numIterPerValidation * (valIterNum-1),“b * - - - - - -”网格)包含(“迭代#”) ylabel ('验证SINR (dB) ') valFig。可见=“上”;结束

参考文献

[1] Yi Luo, Nima Mesgarani,“Conv-tasnet:超越语音分离的理想时频幅度掩蔽”,2019 IEEE/ACM音频、语音和语言处理会刊,第29卷,第8期,第1256-1266页。

[2] V. Panayotov, G. Chen, D. Povey和S. Khudanpur,“Librispeech:基于公共领域音频图书的ASR语料库”,2015年IEEE声学、语音和信号处理国际会议(ICASSP),布里斯班,QLD, 2015年,第5206-5210页,doi: 10.1109/ICASSP.2015.7178964

支持功能

函数[mixDatastore, speaker1Datastore speaker2Datastore] = createTrainingDataset (netFolder、datasetFolder downloadDatasetFolder, reduceDataset, miniBatchSize,持续时间)createTrainingDataset创建训练数据集newDatasetPath = fullfile (downloadDatasetFolder,“speech-sep-dataset”);%创建新的数据集文件夹。如果isfolder (newDatasetPath)删除文件夹(newDatasetPath,“年代”)结束mkdir (newDatasetPath);mkdir ([newDatasetPath' / sp1 ']);mkdir ([newDatasetPath' / sp2 ']);mkdir ([newDatasetPath/混合的]);%创建一个指向LibriSpeech数据集的audioDatastore。如果reduceDataset netFolder = char(netFolder);广告= audioDatastore ([repmat ({fullfile netFolder,“speaker1.wav”)}, 1、4)repmat ({fullfile (netFolder“speaker2.wav”)}、1、4)]);其他的广告= audioDatastore (datasetFolder,“IncludeSubfolders”,真正的);结束% LibriSpeech数据集由来自不同扬声器的信号组成。%唯一的扬声器ID编码在音频文件名中。%从文件名中提取演讲者id。如果reduceDataset ads.Labels = categorical([repmat({' 1 '} 1 4), repmat ({' 2 '} 1 4)]);其他的ads.Labels =分类(extractBetween (ads.Files fullfile (datasetFolder filesep) filesep));结束您将创建由两个随机说话者的话语组成的混合信号。随机化所有发言人的id。名称=独特(ads.Labels);名称=名称(randperm(长度(名字)));%在本例中,您基于400个扬声器创建训练信号。你%生成混合信号基于组合200对的%扬声器。定义两组说话者。。numPairs = min(200年,地板(元素个数(名)/ 2));n1 =名字(1:numPairs);n2 =姓名(numPairs + 1:2 * numPairs);%创建新的数据集。对于每对演讲者:% *使用子集创建两个音频数据存储,每个包含文件%对应于各自的扬声器。% *调整数据存储,使它们拥有相同数量的文件。% *使用Combine将两个数据存储合并。% *使用writeall对合并数据存储的文件进行预处理并写入%新的结果信号到磁盘。%在写入之前为创建信号而执行的预处理步骤%它们被封装在函数createTrainingFiles中。为%每对信号:% *将信号从16 kHz降至8 kHz。% *从每个下采样信号中随机选择4秒。% *通过添加2个信号块来创建混合物。% *你调整信号功率,以实现随机选择%信噪比值在[-5,5]dB范围内。% *你写3个信号(对应于第一个扬声器,第二个%扬声器,和混合物,分别)到磁盘。parforindex=1:length(n1) spkInd1 = n1(index);spkInd2 = n2(指数);spk1ds =子集(广告,ads.Labels = = spkInd1);spk2ds =子集(广告,ads.Labels = = spkInd2);L = min(长度(spk1ds.Files), (spk2ds.Files));L = floor(L/miniBatchSize) * miniBatchSize;spk1ds =子集(spk1ds, 1: L);spk2ds =子集(spk2ds, 1: L);pairds =结合(spk1ds spk2ds);writeall (pairds newDatasetPath,“FolderLayout”,“平”,“WriteFcn”@(数据、writeInfo outputFmt) createTrainingFiles(数据、writeInfo outputFmt reduceDataset,持续时间));结束%创建音频数据存储,指向对应于单个扬声器和混合物的文件。mixDatastore = audioDatastore (fullfile (newDatasetPath“混合”));speaker1Datastore = audioDatastore (fullfile (newDatasetPath“sp1”));speaker2Datastore = audioDatastore (fullfile (newDatasetPathsp2的));结束函数混合= createTrainingFiles(数据、writeInfo ~变长度输入宗量)% createTrainingFiles -预处理训练信号并将其写入磁盘reduceDataset =变长度输入宗量{1};时间=变长度输入宗量{2};x1 ={1}数据;x2 ={2}数据;% Resample from 16 kHz to 8 kHz如果~reduceDataset x1 = resample(x1,1,2);x2 =重新取样(x2, 1、2);结束从第一个扬声器信号中读取一个chunk如果长度(x1)<=duration x1 = [x1;zeros(duration- Length (x1),1)];其他的startInd = randi([1 length(x1)-duration],1);endInd = startInd + duration - 1;x1 = x1 (startInd: endInd);结束%从第二个扬声器信号中读取一个chunk如果Length (x2)<=duration x2 = [x2;zeros(duration- Length (x2),1)];其他的startInd = randi([1 length(x2)-duration],1);endInd = startInd + duration - 1;x2 = x2 (startInd: endInd);结束x1 = x1. / max (abs (x1));x2 = x2. / max (abs (x2));%信噪比[-5 5]dBs =信噪比(x1, x2);targetSNR = 10 * (rand - 0.5);x1b = 10^((targetSNR-s)/20) * x1;Mix = x1b + x2;混合= mix. / max (abs(混合));如果reducedatset [~,n] = fileparts(tempname);name = sprintf (“% s.wav”n);其他的(~ s1) = fileparts (writeInfo.ReadInfo {1} .FileName);(~ s2) = fileparts (writeInfo.ReadInfo {2} .FileName);name = sprintf (“% s - % s.wav”, s1, s2);结束audiowrite (sprintf (' % s 'fullfile (writeInfo。的位置,“sp1”名字)),x1, 8000);audiowrite (sprintf (' % s 'fullfile (writeInfo。的位置,sp2的名字)),x2, 8000);audiowrite (sprintf (' % s 'fullfile (writeInfo。的位置,“混合”、名称))混合,8000);结束函数(损失、渐变州)= modelLoss(混合,x1, x2,可学的,州,miniBatchSize)% modelLoss计算模型损失、梯度和状态(y1、y2、州)= separateSpeakers(混合,可学的,,真的);m = uPIT (x1, y1, x2, y2);l = (m)之和;损失= l / miniBatchSize;梯度= dlgradient(损失,可学的);结束函数m = uPIT (x1, y1, x2, y2)% uPIT -计算话语级置换不变训练v1 = SISNR (y1, x1);v2 = SISNR (y2 x2);m1 =意味着((v1、v2));v1 = SISNR (y2, x1);v2 = SISNR (y1, x2);m2 =意味着((v1、v2));m = max (m1、m2);结束函数z = SISNR (x, y)% SISNR -计算SI-SNRX = X -均值(X);Y = Y - mean(Y);T = sum(x.*y) .*y ./ (sum(y.^2)+eps);N = x - t;z = 20 *日志(√总和(t ^ 2)) + eps)。/√(((n ^ 2)总和)+ eps)) /日志(10);结束函数(可学的,州)= initializeNetworkParams初始化的可学习对象和状态%网络可学的。Conv1W = initializeGlorot (1256);可学的。Conv1B = dlarray(0(256年1“单一”));可学的。ln_weight = dlarray(的(1256“单一”));可学的。ln_bias = dlarray (0 (1256“单一”));可学的。Conv2W = initializeGlorot (1256256);可学的。Conv2B = dlarray(0(256年1“单一”));Index =1:32 BLK = [];黑色。Conv1W = initializeGlorot (1256512);黑色。Conv1B = dlarray(0(512年1“单一”));黑色。Prelu1 = dlarray(单(0.25));黑色。BN1Offset = dlarray(0(512年1“单一”));黑色。BN1Scale = dlarray((512年1“单一”));黑色。Conv2W = initializeGlorot (1512);黑色。Conv2W =重塑(黑色。Conv2W,[3 1 1 512]);黑色。Conv2B = dlarray(0(512年1“单一”));黑色。Prelu2 = dlarray(单(0.25));黑色。BN2Offset = dlarray(0(512年1“单一”));黑色。BN2Scale = dlarray((512年1“单一”));黑色。Conv3W = initializeGlorot (1512256);黑色。Conv3B = dlarray((256年1“单一”));learnables.Blocks(指数)=黑色;s = [];s.BN1Mean = dlarray(0(512年1“单一”));s.BN1Var = dlarray((512年1“单一”));s.BN2Mean = dlarray(0(512年1“单一”));s.BN2Var = dlarray((512年1“单一”));州(指数)= s;% #好吧结束可学的。Conv3W = initializeGlorot (1256512);可学的。Conv3B = dlarray(0(512年1“单一”));可学的。TransConv1W = initializeGlorot (1256);可学的。TransConv1B = dlarray (0 (1, - 1,“单一”));结束函数重量= initializeGlorot (filterSize numChannels numFilters)% initializeGlorot -执行荣耀初始化sz = [filterSize numChannels numFilters];numOut = prod(filterSize) * numFilters;numIn = prod(filterSize) * numFilters;Z = 2 *兰德(深圳,“单一”) - 1;bound = sqrt(6 / (numIn + numOut));weights = bound * Z;重量= dlarray(重量);结束函数[output1, output2, states] = separateSpeakers(input, learnables, states, training)% separateSpeakers -从混合输入中分离两个扬声器信号如果~ isa(输入,“dlarray”)输入= dlarray(输入,“渣打银行”);结束重量= learnables.Conv1W;偏见= learnables.Conv1B;X = dlconv(输入,权重,偏差,“步”10);x = relu (x);x0 = x;X = X -mean(X, 2);x = x /√意味着(x。^2, 2) + 1e-5);x = x。*可学的。ln_weight + learnables.ln_bias;重量= learnables.Conv2W;偏见= learnables.Conv2B;encoderOut = dlconv(x,权重,偏差);index = 1:32 [encoderOut,s] = convBlock(encoderOut, index-1, learnabables . blocks (index),states(index),training);州(指数)= s;结束重量= learnables.Conv3W;偏见= learnables.Conv3B;masks = dlconv(encoderOut, weights, bias);面具= relu(面具);1:256, mask1 =面具(::);257:512, mask2 =面具(::);Out1 = x0 .* mask1;Out2 = x0 .* mask2;重量= learnables.TransConv1W;偏见= learnables.TransConv1B; output2 = dltranspconv(out1, weights, bias,“步”10);Output1 = dltranspconv(out2,权重,偏差,“步”10);如果~training output1 = gather(extractdata(output1));output2 =收集(extractdata (output2));output1 = output1. / max (abs (output1));output2 = output2. / max (abs (output2));结束结束函数[output,state] = convBlock(input, count,learnables,state,training)% Conv:重量= learnables.Conv1W;偏见= learnables.Conv1B;conv1Out = dlconv(输入,权重,偏差);% PRelu:conv1Out = relu(conv1Out) - learables . prelu1 .*relu(-conv1Out);% BatchNormalization:抵消= learnables.BN1Offset;规模= learnables.BN1Scale;datasetMean = state.BN1Mean;datasetVariance = state.BN1Var;如果training [batchOut, dsmean, dsvar] = batchnorm(conv1Out, offset, scale, datasetMean, datasetVariance);状态。BN1Mean = dsmean;状态。BN1Var = dsvar;其他的batchOut = batchnorm(conv1Out, offset, scale, datasetMean, datasetVariance);结束% Conv:重量= learnables.Conv2W;偏见= learnables.Conv2B;Padding = [1 1] * 2^(mod(count,8));dilationFactor = 2 ^ (mod(统计,8));convOut = dlconv(batchOut, weights, bias,“DilationFactor”dilationFactor,“填充”、填充);% PRelu:convOut = relu(convOut) - learnabables . prelu2 .*relu(-convOut);% BatchNormalization:抵消= learnables.BN2Offset;规模= learnables.BN2Scale;datasetMean = state.BN2Mean;datasetVariance = state.BN2Var;如果training [batchOut, dsmean, dsvar] = batchnorm(convOut, offset, scale, datasetMean, datasetVariance);状态。BN2Mean = dsmean;状态。BN2Var = dsvar;其他的batchOut = batchnorm(convOut, offset, scale, datasetMean, datasetVariance);结束% Conv:重量= learnables.Conv3W;偏见= learnables.Conv3B;output = dlconv(batchOut, weights, bias);%跳过连接输出=输出+输入;结束函数[speaker1, speaker2] = separateSpeakersTimeFrequency(混合,pathToNet)% separateSpeakersTimeFrequency -基于stft的扬声器分离功能WindowLength = 128;FFTLength = 128;OverlapLength = 128 - 1;赢得=损害(WindowLength,“周期”);%下采样至4千赫混合=重新取样(混合,1、2);P0 = stft(混合,“窗口”,赢了,“OverlapLength”OverlapLength,“FFTLength”FFTLength,“FrequencyRange”,“单向的”);P = log(abs(P0) + eps);议员=意味着(P (:));SP =性病(P (:));P = (P-MP) / SP;seqLen = 20;seq = 0 (1 + FFTLength/2,seqLen,1,0);seqOverlap = seqLen;loc = 1;loc <大小(P, 2) -seqLen PSeq(::,:,结束+ 1)= P (:, loc: loc + seqLen-1);% #好吧loc = loc + seqOverlap;结束psq =重塑(psq, [1 1 (1 + FFTLength/2) * seqLen size(psq,4)]);s =加载(fullfile (pathToNet“CocktailPartyNet.mat”));CocktailPartyNet = s.CocktailPartyNet;estimatedMasks =预测(CocktailPartyNet PSeq);estimatedMasks = estimatedMasks。”;estimatedMasks =重塑(estimatedMasks,1 + FFTLength/2,numel(estimatedMasks)/(1 + FFTLength/2));mask1 = estimatedMasks;Mask2 = 1 - mask1;P0 = P0(:, 1:尺寸(mask1 2));P_speaker1 = P0 .* mask1;speaker1 = istft (P_speaker1,“窗口”,赢了,“OverlapLength”OverlapLength,“FFTLength”FFTLength,“ConjugateSymmetric”,真的,“FrequencyRange”,“单向的”);Speaker1 = Speaker1 / max(abs(Speaker1)));P_speaker2 = P0 .* mask2;speaker2 = istft (P_speaker2,“窗口”,赢了,“OverlapLength”OverlapLength,“FFTLength”FFTLength,“ConjugateSymmetric”,真的,“FrequencyRange”,“单向的”);Speaker2 = Speaker2 / max(Speaker2);speaker1 =重新取样(双(speaker1)、2、1);speaker2 =重新取样(双(speaker2)、2、1);结束
Baidu
map