主要内容

基于深度学习的噪声中语音活动检测

这个例子展示了如何使用深度学习在低信噪比环境中检测语音区域。该示例使用语音命令数据集来训练双向长短期记忆(BiLSTM)网络来检测语音活动。

简介

语音活动检测是许多音频系统的重要组成部分,如自动语音识别和说话人识别。在低信噪比(SNR)情况下,语音活动检测尤其具有挑战性,因为语音被噪声阻碍。

本例使用长短期记忆(LSTM)网络,它是一种循环神经网络(RNN),非常适合研究序列和时间序列数据。LSTM网络可以学习序列时间步长之间的长期依赖关系。LSTM层(lstmLayer(深度学习工具箱))可以向前看时间序列,而双向LSTM层(bilstmLayer(深度学习工具箱))可以从正反两个方向查看时间序列。本例使用双向LSTM层。

本例训练了一个具有频谱特征特征序列和谐波比度量的语音活动检测双向LSTM网络。

在高信噪比的场景下,传统的语音检测算法表现良好。读入一个由单词之间有停顿的单词组成的音频文件。将音频重采样为16 kHz。听录音。

Fs = 16e3;[speech,fileFs] = audioread(“Counting-16-44p1-mono-15secs.wav”);speech = resample(speech,fs,fileFs);Speech = Speech /max(abs(Speech));声音(演讲中,fs)

使用detectSpeech定位语音区域的功能。的detectSpeech功能正确识别所有语音区域。

赢=汉明(50e-3 * fs,“周期”);detectSpeech(演讲、fs、“窗口”,赢了)

用- 20db信噪比的洗衣机噪音破坏音频信号。收听损坏的音频。

[noise,fileFs] = audioread(“洗衣机- 16 - 8 mono - 200 secs.mp3”);noise = resample(noise,fs,fileFs);信噪比= -20;噪声增益= 10^(-信噪比/20)*范数(语音)/范数(噪声);noisySpeech =语音+噪声增益*噪声(1:数字(语音));noisySpeech = noisySpeech./max(abs(noisySpeech));声音(noisySpeech fs)

调用detectSpeech有噪声的音频信号。由于信噪比非常低,该函数无法检测到语音区域。

detectSpeech (noisySpeech fs,“窗口”,赢了)

下载并加载预先训练好的网络和配置好的网络audioFeatureExtractor对象。该网络被训练来检测低信噪比环境下的语音audioFeatureExtractor对象。

url =“http://ssd.mathworks.com/金宝appsupportfiles/audio/VoiceActivityDetection.zip”;downloadNetFolder = tempdir;netFolder = fullfile(下载netFolder,“VoiceActivityDetection”);如果~存在(netFolder“dir”) disp (下载预训练的网络(1个文件- 8 MB)…解压缩(url, downloadNetFolder)结束负载(fullfile (netFolder“voiceActivityDetectionExample.mat”));
speechDetectNet
speechDetectNet = SeriesNetwork with properties: Layers: [6×1 nnet.cnn.layer.Layer] InputNames: {'sequenceinput'} OutputNames: {'classoutput'}
afe
afe = audioFeatureExtractor with properties: properties Window: [256×1 double] OverlapLength: 128 SampleRate: 16000 FFTLength: [] SpectralDescriptorInput:'linearSpectrum'启用特征spectralCentroid, spectralCrest, spectralEntropy, spectralFlux, spectral峰度,spectralRolloffPoint spectralSkewness, spectralSlope, harmonicRatio禁用特征linearSpectrum, melSpectrum, barkSpectrum, erbSpectrum, mfcc, mfccDelta mfccDeltaDelta, gtcc, gtccDelta, gtccDeltaDelta, spectralreduce, spectralFlatness spectralSpread, pitch提取一个特征,将相应的属性设置为true。例如,obj。MFCC = true,将MFCC添加到启用的特性列表中。

从语音数据中提取特征并进行归一化处理。定位特征,使时间跨列。

features = extract(afe,noisySpeech);Features = (Features - mean(Features,1)) ./ std(Features,[],1);Features = Features ';

将特征通过语音检测网络,对每个特征向量进行分类,判断是否属于某个语音帧。

decisionsCategorical =分类(语音检测网,特征);

对象分析的一个分析窗口对应于每个决策audioFeatureExtractor.复制决策,使它们与音频样本一一对应。将演讲、嘈杂的演讲和VAD决策绘制出来。

decisionsWindow = 1.2*(double(decisionsCategorical)-1);decisionsSample = [repelem(decisionsWindow(1),numel(afe.Window)),...repelem (decisionsWindow(2:结束),元素个数(afe.Window) -afe.OverlapLength)];t = (0:numel(decisionsSample)-1)/afe.SampleRate;情节(t, noisySpeech(1:元素个数(t)),...t,演讲(1:元素个数(t)),...t, decisionsSample);包含(“时间(s)”) ylabel (“振幅”)传说(的嘈杂的演讲“演讲”“监督”“位置”“西南”

您还可以在流环境中使用经过训练的VAD网络。为了模拟流环境,首先将语音和噪声信号保存为WAV文件。为了模拟流输入,您将从文件中读取帧,并以所需的信噪比混合它们。

audiowrite (“Speech.wav”演讲中,fs) audiowrite (“Noise.wav”、噪音、fs)

为了将VAD网络应用于流媒体音频,您必须在延迟和准确性之间进行权衡。定义噪声演示中流语音活动检测的参数。您可以设置测试的持续时间、输入网络的序列长度、序列跳长和要测试的信噪比。通常,增加序列长度会增加精度,但也会增加滞后。您也可以选择输出到您的设备的信号为原始信号或噪声信号。

testDuration =20.;sequenceLength =400;sequenceHop =20.;信噪比=-20年;噪声增益= 10^(-信噪比/20)*范数(语音)/范数(噪声);signalToListenTo =“吵”

调用流演示助手函数来观察VAD网络在流音频上的性能。使用实时控件设置的参数不会中断流示例。在流演示完成后,您可以修改演示的参数,然后再次运行流演示。流媒体演示的代码可以在金宝app支持功能

helperStreamingDemo (afe speechDetectNet,...“Speech.wav”“Noise.wav”...testDuration、sequenceLength sequenceHop、signalToListenTo noiseGain);

示例的其余部分介绍了VAD网络的训练和评估。

培训和评估VAD网络

培训:

  1. 创建一个audioDatastore指向用于训练LSTM网络的音频语音文件。

  2. 创建一个由不同持续时间的沉默片段分隔的语音片段组成的训练信号。

  3. 用洗衣机噪声(信噪比= -10 dB)破坏语音加静音信号。

  4. 从噪声信号中提取由频谱特征和谐波比组成的特征序列。

  5. 使用特征序列训练LSTM网络来识别语音活动区域。

预测:

  1. 创建一个audioDatastore的语音文件,用于测试训练的网络,并创建由沉默段分开的语音组成的测试信号。

  2. 用洗衣机噪声(信噪比= -10 dB)破坏测试信号。

  3. 从有噪声的测试信号中提取特征序列。

  4. 通过经过训练的网络通过测试特征来识别语音活动的区域。

  5. 将网络的准确性与来自信号加沉默测试信号的语音活动基线进行比较。

这里是训练过程的草图。

下面是预测过程的草图。你使用训练过的网络进行预测。

加载语音命令数据集

下载并提取谷歌语音命令数据集[1]

url =“https://ssd.mathworks.com/金宝appsupportfiles/audio/google_speech.zip”;downloadFolder = tempdir;datasetFolder = fullfile(下载文件夹,“google_speech”);如果~存在(datasetFolder“dir”) disp (正在下载谷歌语音命令数据集(1.9 GB)…解压缩(url, downloadFolder)结束
下载谷歌语音命令数据集(1.9 GB)…

创建一个audioDatastore它指向训练数据集。

adsTrain = audioDatastore(fullfile(datasetFolder,“火车”),“Includesubfolders”,真正的);

创建一个audioDatastore它指向验证数据集。

adsValidation = audioDatastore(fullfile(datasetFolder),“验证”),“Includesubfolders”,真正的);

创建语音加静音训练信号

读取音频文件的内容.得到抽样率adsInfo结构体。

[data,adsInfo] = read(adsTrain);Fs = adsInfo.SampleRate;

使用sound命令收听音频信号。

声音(数据、Fs)

绘制音频信号。

timeVector = (1/Fs) *(0:数字(数据)-1);情节(timeVector、数据)ylabel (“振幅”)包含(“时间(s)”)标题(“音频样本”网格)

信号有非语音部分(静音、背景噪声等),不包含有用的语音信息。属性删除静默detectSpeech函数。

提取数据中有用的部分。定义一个50毫秒的周期汉明窗口进行分析。调用detectSpeech没有输出参数来绘制检测到的语音区域。调用detectSpeech再次返回检测到的语音的索引。隔离检测到的语音区域,然后使用声音命令收听音频。

赢=汉明(50e-3 * f,“周期”);detectSpeech(数据、Fs、“窗口”,赢了);

speech hinices = detectSpeech(data,Fs,“窗口”,赢了);声音(数据(speechIndices (1,1): speechIndices(1、2),Fs)

detectSpeech函数返回紧紧围绕检测到的语音区域的索引。根据经验,在这个例子中,将检测到的语音的索引在两侧延长五帧,可以提高最终模型的性能。将语音索引扩展5帧,然后收听语音。

speech hinices (1,1) = max(speech hinices (1,1) - 5* nummel (win),1);speech hinices (1,2) = min(speech hinices (1,2) + 5*numel(win),numel(data));声音(数据(speechIndices (1,1): speechIndices(1、2),Fs)

重置训练数据存储,并打乱数据存储中文件的顺序。

reset(adsTrain) adsTrain = shuffle(adsTrain);adsValidation = shuffle(adsValidation);

detectSpeech函数计算基于统计的阈值来确定语音区域。可以跳过阈值计算并加快detectSpeech通过直接指定阈值来实现功能。要确定数据集的阈值,请调用detectSpeech对文件进行抽样,并获得它计算的阈值。取阈值的平均值。

Tm = [];index1 = 1:500 data = read(adsTrain);[~,T] = detectSpeech(data,Fs,“窗口”,赢了);Tm = [Tm; t];结束T = mean(TM);重置(adsTrain)

结合训练数据集中的多个语音文件,创建一个1000秒的训练信号。使用detectSpeech删除每个文件中不需要的部分。在语音片段之间插入一段随机的沉默时间。

预分配训练信号。

持续时间= 2000*Fs;audioTraining = 0 (duration,1);

预分配语音活动训练掩码。掩码中的值1对应于位于有声音活动区域的样本。0代表没有声音活动的区域。

maskTraining = 0 (duration,1);

指定最大沉默段持续时间为2秒。

maxsilencsegment = 2;

通过呼叫构建训练信号在循环中的数据存储上。

numSamples = 1;numSamples < duration data = read(adsTrain);Data = Data ./ max(abs(Data));归一化振幅确定语音区域idx = detectSpeech(数据,Fs,“窗口”,赢了,“阈值”T);%如果检测到语音区域如果~ isempty (idx)将索引扩展5帧Idx (1,1) = max(1, Idx (1,1) - 5* nummel (win));idx(1、2)= min(长度(数据),idx(1、2)+ 5 *元素个数(赢得));%隔离讲话数据=数据(idx(1,1):idx(1,2));将语音段写入训练信号audioTraining(numSamples:numSamples+ numeric (data)-1) = data;设置VAD基线maskTraining(numSamples:numSamples+ numeric (data)-1) = true;%随机静默期numSilenceSamples = randi(maxsilencessegment *Fs,1,1);numSamples = numSamples + nummel (data) + numSilenceSamples;结束结束

想象一个10秒的训练信号。绘制基线语音活动掩码。

图范围= 1:10*Fs;情节((1 / Fs) *(范围1)audioTraining(范围);持有情节((1 / Fs) *(范围1)maskTraining(范围);网格Lines = findall(gcf,“类型”“行”);行(1)。LineWidth = 2;包含(“时间(s)”)传说(“信号”“演讲地区”)标题(“训练信号(前10秒)”);

听训练信号的前10秒。

声音(audioTraining(范围),Fs);

在训练信号中添加噪声

通过在语音信号中加入洗衣机噪声,使信噪比为-10 dB,对训练信号进行洗衣机噪声的破坏。

读取8千赫的噪声并将其转换为16千赫。

噪音= audieread (“洗衣机- 16 - 8 mono - 1000 - secs.mp3”);噪声= resample(噪声,2,1);

用噪声破坏训练信号。

audioTraining = audioTraining(1:数字(噪音));信噪比= -10;噪声= 10^(-SNR/20) *噪声*范数(audioTraining) /范数(噪声);audiotrainingnoise = audioTraining + noise;audiotrainingnoise = audiotrainingnoise / max(abs(audiotrainingnoise));

想象一段10秒的训练信号。绘制基线语音活动掩码。

图绘制((1 / Fs) *(范围1)audioTrainingNoisy(范围);持有情节((1 / Fs) *(范围1)maskTraining(范围);网格Lines = findall(gcf,“类型”“行”);行(1)。LineWidth = 2;包含(“时间(s)”)传说(“噪声信号”“言语区”)标题(“训练信号(前10秒)”);

听前10秒的嘈杂训练信号。

声音(audioTrainingNoisy(范围)、Fs)

请注意,您使用无噪声语音加静音信号获得了基线语音活动掩码。验证使用detectSpeech对噪声损坏的信号不产生良好的效果。

speech hinices = detectSpeech(audiotrainingnoise,Fs,“窗口”,赢了);speechIndices(:,1) = max(1,speechIndices(:,1) - 5* nummel (win));speechinices (:,2) = min(nummel (audiotrainingnoise), speechinices (:,2) + 5* nummel (win));noisyMask = 0 (size(audiotrainingnoise));ii = 1:size(speech hinices) noisyMask(speech hinices (ii,1):speech hinices (ii,2)) = 1;结束

想象一段10秒的训练信号。通过分析噪声信号,绘制出语音活动掩码。

图绘制((1 / Fs) *(范围1)audioTrainingNoisy(范围);持有情节((1 / Fs) *(范围1)noisyMask(范围);网格Lines = findall(gcf,“类型”“行”);行(1)。LineWidth = 2;包含(“时间(s)”)传说(“噪声信号”“噪声信号屏蔽”)标题(“训练信号(前10秒)”);

创建语音加静音验证信号

创建一个200秒的噪声语音信号来验证训练好的网络。使用验证数据存储。注意,验证和训练数据存储具有不同的扬声器。

预分配验证信号和验证掩码。您将使用此掩码来评估训练网络的准确性。

duration = 200*Fs;audioValidation = 0 (duration,1);maskValidation = 0 (duration,1);

通过调用构造验证信号在循环中的数据存储上。

numSamples = 1;numSamples < duration data = read(adsValidation);Data = Data ./ max(abs(Data));归一化振幅确定语音区域idx = detectSpeech(数据,Fs,“窗口”,赢了,“阈值”T);%如果检测到语音区域如果~ isempty (idx)将索引扩展5帧Idx (1,1) = max(1, Idx (1,1) - 5* nummel (win));idx(1、2)= min(长度(数据),idx(1、2)+ 5 *元素个数(赢得));%隔离讲话数据=数据(idx(1,1):idx(1,2));将语音段写入训练信号audioValidation(numSamples:numSamples+ nummel (data)-1) = data;设置VAD基线maskValidation(numSamples:numSamples+ nummel (data)-1) = true;%随机静默期numSilenceSamples = randi(maxsilencessegment *Fs,1,1);numSamples = numSamples + nummel (data) + numSilenceSamples;结束结束

通过在语音信号中添加洗衣机噪声,使信噪比为-10 dB,从而用洗衣机噪声破坏验证信号。对验证信号使用与训练信号不同的噪声文件。

噪音= audieread (“洗衣机- 16 - 8 mono - 200 - secs.mp3”);噪声= resample(噪声,2,1);噪音=噪音(1:持续时间);audioValidation = audioValidation(1:数字(噪音));噪声= 10^(-信噪比/20)*噪声*范数(audioValidation) /范数(噪声);audiovalidationnoise = audioValidation + noise;audiovalidationnoise = audiovalidationnoise / max(abs(audiovalidationnoise));

提取培训特点

本例使用以下特性训练LSTM网络:

这个例子使用了audioFeatureExtractor为特征集创建一个最佳的特征提取管道。创建一个audioFeatureExtractor对象来提取特征集。使用256点汉恩窗口,重叠50%。

afe = audioFeatureExtractor(“SampleRate”Fs,...“窗口”损害(256,“周期”),...“OverlapLength”, 128,......“spectralCentroid”,真的,...“spectralCrest”,真的,...“spectralEntropy”,真的,...“spectralFlux”,真的,...“spectralKurtosis”,真的,...“spectralRolloffPoint”,真的,...“spectralSkewness”,真的,...“spectralSlope”,真的,...“harmonicRatio”,真正的);featurestraint = extract(afe, audiotrainingnoise);

显示特征矩阵的维数。第一个维度对应于信号被打断的窗口数(它取决于窗口长度和重叠长度)。第二个维度是本例中使用的特性的数量。

[numWindows,numFeatures] = size(featurestrictions)
numWindows = 125009
numFeatures = 9

在分类应用中,将所有特征归一化为零均值和单位标准差是一个很好的实践。

计算每个系数的平均值和标准差,并使用它们对数据进行归一化。

M = mean(featurestraint,1);S = std(featurestraint,[],1);featurestraint = (featurestraint - M) ./ S;

使用相同的过程从验证信号中提取特征。

featuresValidation = extract(afe, audiovalidationnoise);featuresValidation = (featuresValidation - mean(featuresValidation,1)) ./ std(featuresValidation,[],1);

每个特征对应128个数据样本(跳长)。每一跳的语音/无语音期望值设置为这128个样本对应的基线掩码值的模式。将语音/无语音掩码转换为分类掩码。

windowLength = numel(afe.Window);hopLength = windowLength - afe.OverlapLength;range = (hopLength) * (1:size(featurestraint,1)) + hopLength;maskMode = 0(大小(范围));maskMode(index) = mode(maskTraining((index-1)*hopLength+1:(index-1)*hopLength+windowLength));结束maskTraining = maskMode.';maskTrainingCat = categorical(maskTraining);

对验证掩码执行同样的操作。

range = (hopLength) * (1:size(featuresValidation,1)) + hopLength;maskMode = 0(大小(范围));maskMode(index) = mode(maskValidation((index-1)*hopLength+1:(index-1)*hopLength+windowLength));结束maskValidation = maskMode.';maskValidationCat = categorical(maskValidation);

将训练特征和面具分割成长度为800的序列,连续序列之间有75%的重叠。

sequenceLength = 800;sequenceOverlap = round(0.75* sequencelth);trainFeatureCell = helperFeatureVector2Sequence(featuinhibit ',sequenceLength,sequenceOverlap);trainLabelCell = helperFeatureVector2Sequence(maskTrainingCat',sequenceLength,sequenceOverlap);

定义LSTM网络体系结构

LSTM网络可以学习序列数据时间步长之间的长期依赖关系。本例使用双向LSTM层bilstmLayer(深度学习工具箱)从前后两个方向看序列。

指定输入大小为长度序列9(功能的数量)。指定一个隐藏的双向LSTM层,输出大小为200,输出一个序列。该命令指示双向LSTM层将输入的时间序列映射为200个特征,并传递给下一层。然后,指定一个输出大小为200的双向LSTM层,并输出序列的最后一个元素。该命令指示双向LSTM层将其输入映射为200个特征,然后为全连接层准备输出。最后,通过包含大小的全连接层来指定两个类2,然后是softmax层和classification层。

层= [...sequenceInputLayer(size(featuresValidation,2))“OutputMode”“序列”) bilstmLayer (200,“OutputMode”“序列”) fullyConnectedLayer(2) softmaxLayer classificationLayer];

接下来,为分类器指定训练选项。集MaxEpochs20.这样网络就通过了20次训练数据。集MiniBatchSize64这样网络一次就能看到64个训练信号。集情节“训练进步”生成随迭代次数增加而显示训练进度的图。集详细的禁用打印与图中显示的数据相对应的表输出。集洗牌“every-epoch”在每个纪元开始时重新洗牌训练序列。集LearnRateSchedule“分段”每次经过一定数量的epoch(10)时,将学习率降低指定的因子(0.1)。集ValidationData到验证预测器和目标。

本例使用自适应矩估计(ADAM)求解器。ADAM与LSTMs等递归神经网络(rnn)相比,默认的随机动量梯度下降(SGDM)求解器的性能更好。

maxEpochs = 20;miniBatchSize = 64;选项= trainingOptions(“亚当”...“MaxEpochs”maxEpochs,...“MiniBatchSize”miniBatchSize,...“洗牌”“every-epoch”...“详细”0,...“SequenceLength”sequenceLength,...“ValidationFrequency”、地板(元素个数(trainFeatureCell) / miniBatchSize),...“ValidationData”, {featuresValidation。“maskValidationCat。”},...“阴谋”“训练进步”...“LearnRateSchedule”“分段”...“LearnRateDropFactor”, 0.1,...“LearnRateDropPeriod”5);

培训LSTM网络

使用指定的训练选项和层结构训练LSTM网络trainNetwork.由于训练集很大,训练过程可能需要几分钟。

doTraining = true;如果doTraining [speechDetectNet,netInfo] = trainNetwork(trainFeatureCell,trainLabelCell,layers,options);流("验证精度:%f %。\n", netInfo.FinalValidationAccuracy);其他的负载speechDetectNet结束
验证精度:91.320312%。

使用训练网络检测语音活动

使用训练过的网络估计验证信号中的语音活动。将估计的VAD掩码从分类转换为双重。

EstimatedVADMask = classification (speechDetectNet,featuresValidation.');EstimatedVADMask = double(EstimatedVADMask);EstimatedVADMask = EstimatedVADMask。' - 1;

根据实际标签和估计标签的向量计算并绘制验证混淆矩阵。

figure cm = confusichart (maskValidation,EstimatedVADMask,“标题”“验证准确性”);厘米。ColumnSummary =“column-normalized”;厘米。RowSummary =“row-normalized”

如果您更改了网络或特征提取管道的参数,请考虑使用新的网络和重新保存MAT文件audioFeatureExtractor对象。

resaveNetwork =如果resaveNetwork保存(“Audio_VoiceActivityDetectionExample.mat”“speechDetectNet”“安全的”);结束

金宝app支持功能

将特征向量转换为序列

函数[sequences,sequencePerFile] = helperFeatureVector2Sequence(features,featureVectorsPerSequence,featureVectorOverlap)如果featureVectorsPerSequence <= featureVectorOverlap错误(重叠的特征向量的数量必须小于每个序列的特征向量的数量。结束如果~iscell(features) features = {features};结束hopLength = featureVectorsPerSequence - featureVectorOverlap;Idx1 = 1;序列= {};sequencePerFile = cell(数字(特征),1);ii = 1:numel(features) sequencePerFile{ii} = floor((size(features{ii},2) - featureVectorsPerSequence)/hopLength) + 1;Idx2 = 1;j = 1:sequencePerFile{ii} sequences{idx1,1} = features{ii}(:,idx2:idx2 + featureVectorsPerSequence - 1);% #好< AGROW >Idx1 = Idx1 + 1;idx2 = idx2 + hopLength;结束结束结束

流媒体演示

函数helperStreamingDemo (speechDetectNet afe cleanSpeech,噪音,testDuration, sequenceLength, sequenceHop, signalToListenTo, noiseGain)

创建dsp。AudioFileReader对象逐帧从语音和噪声文件中读取。

speechReader = dsp。AudioFileReader(cleanSpeech,“PlayCount”、正);noiseReader = dsp。AudioFileReader(noise,“PlayCount”、正);fs = speechReader.SampleRate;

创建一个dsp。MovingStandardDeviation对象和dsp。MovingAverage对象。您将使用这些来确定标准化音频特征的标准偏差和平均值。随着时间的推移,统计数据应该会有所改善。

movSTD = dsp。MovingStandardDeviation (“方法”指数权重的“ForgettingFactor”1);movMean = dsp。MovingAverage (“方法”指数权重的“ForgettingFactor”1);

创建三个dsp。AsyncBuffer对象。一个用于缓冲输入音频,一个用于缓冲提取的特征,一个用于缓冲输出缓冲区。输出缓冲区仅用于实时可视化决策。

audioInBuffer = dsp.AsyncBuffer;featureBuffer = dsp.AsyncBuffer;audioOutBuffer = dsp.AsyncBuffer;

对于音频缓冲区,您将缓冲原始的干净语音信号和有噪声的信号。您将只播放指定的内容signalToListenTo.转换signalToListenTo变量到您想要收听的频道。

channelToListenTo = 1;如果比较字符串(signalToListenTo“清洁”) channelToListenTo = 2;结束

创建一个时间范围来可视化原始语音信号、网络应用的噪声信号以及网络的决策输出。

Scope = timescope(“SampleRate”fs,...“TimeSpanSource”“属性”...“时间间隔”3,...“BufferLength”fs * 3 * 3,...“YLimits”[1],...“TimeSpanOverrunAction”“滚动”...“ShowGrid”,真的,...“NumInputPorts”3,...“LayoutDimensions”(3,1),...“标题”的嘈杂的演讲);范围。ActiveDisplay = 2;范围。Title =“干净演说(原文)”;范围。YLimits = [-1 1];范围。ActiveDisplay = 3;范围。Title =“发现演讲”;范围。YLimits = [-1 1];

创建一个audioDeviceWriter对象从扬声器中播放原始音频或有噪声的音频。

deviceWriter = audioDeviceWriter(“SampleRate”fs);

初始化循环中使用的变量。

windowLength = numel(afe.Window);hopLength = windowLength - afe.OverlapLength;myMax = 0;audioBufferInitialized = false;featureBufferInitialized = false;

运行流演示。

抽搐toc < testDuration读取一帧语音信号和一帧噪声信号speechIn = speechReader();noiseIn = noiseReader();以指定的信噪比将语音和噪声混合noisyAudio = speechIn + noiseIn;为标准化更新运行最大值myMax = max(myMax,max(abs(noisyAudio)));将有噪声的音频和语音写入缓冲区写(audioInBuffer [noisyAudio speechIn]);%如果缓冲了足够多的样本,%标记音频缓冲区已初始化,并推读指针%为一个窗口长度的音频缓冲区。如果audioInBuffer。NumUnreadSamples >= windowLength && ~audioBufferInitialized audioBufferInitialized = true;读(audioInBuffer windowLength);结束%如果音频缓冲区中有足够的样本来计算一个特征%向量,读取样本,归一化,提取特征向量,并写入%最新的特征向量到特征缓冲区。(audioInBuffer。NumUnreadSamples >= hopLength) && audioBufferInitialized x = read(audioInBuffer,windowLength + hopLength,windowLength);写(audioOutBuffer x (end-hopLength + 1:,:));noisyAudio = x(:,1);noisyAudio = noisyAudio/myMax;features = extract(afe,noisyAudio);写(featureBuffer特性(2:));结束如果缓冲了足够多的特征向量,标记特征缓冲区%初始化,并推入特征缓冲区的读指针%和音频输出缓冲区(这样它们是同步的)。如果featureBuffer。NumUnreadSamples >= (sequenceLength + sequenceHop) && ~featureBufferInitialized featureBufferInitialized = true;读取(featureBuffer,sequenceLength - sequenceHop);read(audioOutBuffer,(sequenceLength - sequenceHop)*windowLength);结束featureBuffer。NumUnreadSamples >= sequenceHop && featureBufferInitialized features = read(featureBuffer,sequenceLength,sequenceLength - sequenceHop);Features (isnan(Features)) = 0;仅使用新功能来更新%标准差和平均值。标准化特征。localSTD = movSTD(features(end- sequencehop +1:end,:));localMean = movMean(features(end- sequencehop +1:end,:));features = (features - localMean(end,:)) ./ localSTD(end,:);decision = classification (speechDetectNet,features');决定=决定(end- sequencehop +1:结束);Decision = double(Decision)' - 1;decision = repelem(decision,hopLength);audioHop = read(audioOutBuffer,sequenceHop*hopLength);听演讲或演讲+噪音deviceWriter (audioHop (:, channelToListenTo));视觉化演讲+噪音,原始演讲,和%语音活动检测。范围(audioHop (: 1), audioHop (:, 2), audioHop(: 1)。*决定)结束结束release(deviceWriter) release(audioInBuffer) release(audioOutBuffer) release(featureBuffer) release(movSTD) release(movMean) release(scope)结束

参考文献

狱长P。“语音命令:用于单词语音识别的公共数据集”,2017年。可以从https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.01.tar.gz.版权所有谷歌2017。语音命令数据集是在创作共用属性4.0许可下授权的