exponenta event banner

Denoise Speech с использованием сетей глубокого обучения

В этом примере показано, как подавлять речевые сигналы с помощью сетей глубокого обучения. В примере сравниваются два типа сетей, применяемых к одной задаче: полностью связанные и сверточные.

Введение

Целью шумоподавления речи является удаление шума из речевых сигналов при одновременном повышении качества и разборчивости речи. В этом примере показано удаление шума стиральной машины из речевых сигналов с использованием сетей глубокого обучения. В примере сравниваются два типа сетей, применяемых к одной задаче: полностью связанные и сверточные.

Сводка проблем

Рассмотрим следующий речевой сигнал, дискретизированный на частоте 8 кГц.

[cleanAudio,fs] = audioread("SpeechDFT-16-8-mono-5secs.wav");
sound(cleanAudio,fs)

Добавьте шум стиральной машины к речевому сигналу. Установите мощность шума таким образом, чтобы отношение сигнал/шум (SNR) было равно нулю дБ.

noise = audioread("WashingMachine-16-8-mono-1000secs.mp3");

% Extract a noise segment from a random location in the noise file
ind = randi(numel(noise) - numel(cleanAudio) + 1, 1, 1);
noiseSegment = noise(ind:ind + numel(cleanAudio) - 1);

speechPower = sum(cleanAudio.^2);
noisePower = sum(noiseSegment.^2);
noisyAudio = cleanAudio + sqrt(speechPower/noisePower) * noiseSegment;

Слушайте шумный речевой сигнал.

sound(noisyAudio,fs)

Визуализируйте исходные и шумные сигналы.

t = (1/fs) * (0:numel(cleanAudio)-1);

subplot(2,1,1)
plot(t,cleanAudio)
title("Clean Audio")
grid on

subplot(2,1,2)
plot(t,noisyAudio)
title("Noisy Audio")
xlabel("Time (s)")
grid on

Цель искажения речи состоит в том, чтобы удалить шум стиральной машины из речевого сигнала при минимизации нежелательных артефактов в выходной речи.

Проверка набора данных

В этом примере используется подмножество набора данных Mozilla Common Voice [1] для обучения и тестирования сетей глубокого обучения. Набор данных содержит записи 48 кГц субъектов, говорящих короткие предложения. Загрузите набор данных и распакуйте загруженный файл.

url = 'http://ssd.mathworks.com/supportfiles/audio/commonvoice.zip';
downloadFolder = tempdir;
dataFolder = fullfile(downloadFolder,'commonvoice');

if ~exist(dataFolder,'dir')
    disp('Downloading data set (956 MB) ...')
    unzip(url,downloadFolder)
end

Использовать audioDatastore для создания хранилища данных для обучающего набора. Чтобы ускорить выполнение примера за счет производительности, установите reduceDataset кому true.

adsTrain = audioDatastore(fullfile(dataFolder,'train'),'IncludeSubfolders',true);

reduceDataset = true;
if reduceDataset
    adsTrain = shuffle(adsTrain);
    adsTrain = subset(adsTrain,1:1000);
end

Использовать read для получения содержимого первого файла в хранилище данных.

[audio,adsTrainInfo] = read(adsTrain);

Слушайте речевой сигнал.

sound(audio,adsTrainInfo.SampleRate)

Постройте график речевого сигнала.

figure
t = (1/adsTrainInfo.SampleRate) * (0:numel(audio)-1);
plot(t,audio)
title("Example Speech Signal")
xlabel("Time (s)")
grid on

Обзор системы глубокого обучения

Ниже приводится схема базового углубленного обучения. Следует отметить, что, поскольку речь обычно падает ниже 4 кГц, для уменьшения вычислительной нагрузки сети сначала следует уменьшить количество чистых и шумных звуковых сигналов до 8 кГц. Сигналы предиктора и целевой сети являются амплитудными спектрами шумных и чистых звуковых сигналов соответственно. Выходной сигнал сети представляет собой амплитудный спектр денойзированного сигнала. Регрессионная сеть использует вход предиктора для минимизации среднеквадратической ошибки между его выходом и входной целью. Деноизолированный звук преобразуется обратно во временную область с использованием спектра выходной величины и фазы шумного сигнала [2].

Вы преобразуете звук в частотную область с помощью преобразования краткосрочного Фурье (STFT) с длиной окна 256 выборок, перекрытием 75% и окном Хэмминга. Вы уменьшаете размер спектрального вектора до 129, отбрасывая частотные выборки, соответствующие отрицательным частотам (поскольку речевой сигнал временной области является реальным, это не приводит к какой-либо потере информации). Вход предсказателя состоит из 8 последовательных шумных STFT векторов, так что каждая выходная оценка STFT вычисляется на основе текущего шумного STFT и 7 предыдущих шумных STFT векторов.

Цели и предикторы STFT

В этом разделе показано, как генерировать сигналы цели и предиктора из одного обучающего файла.

Сначала определите системные параметры:

windowLength = 256;
win = hamming(windowLength,"periodic");
overlap = round(0.75 * windowLength);
ffTLength = windowLength;
inputFs = 48e3;
fs = 8e3;
numFeatures = ffTLength/2 + 1;
numSegments = 8;

Создать dsp.SampleRateConverter Объект (DSP System Toolbox) для преобразования звука 48 кГц в 8 кГц.

src = dsp.SampleRateConverter("InputSampleRate",inputFs, ...
                              "OutputSampleRate",fs, ...
                              "Bandwidth",7920);

Использовать read для получения содержимого аудиофайла из хранилища данных.

audio = read(adsTrain);

Убедитесь, что длина звука кратна коэффициенту прореживания преобразователя частоты дискретизации.

decimationFactor = inputFs/fs;
L = floor(numel(audio)/decimationFactor);
audio = audio(1:decimationFactor*L);

Преобразуйте звуковой сигнал в 8 кГц.

audio = src(audio);
reset(src)

Создайте сегмент случайного шума из вектора шума стиральной машины.

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

Добавьте шум к речевому сигналу таким образом, чтобы SNR был равен 0 дБ.

noisePower = sum(noiseSegment.^2);
cleanPower = sum(audio.^2);
noiseSegment = noiseSegment .* sqrt(cleanPower/noisePower);
noisyAudio = audio + noiseSegment;

Использовать stft(Панель инструментов обработки сигналов) для генерации векторов STFT величины из исходных и шумных звуковых сигналов.

cleanSTFT = stft(audio,'Window',win,'OverlapLength',overlap,'FFTLength',ffTLength);
cleanSTFT = abs(cleanSTFT(numFeatures-1:end,:));
noisySTFT = stft(noisyAudio,'Window',win,'OverlapLength',overlap,'FFTLength',ffTLength);
noisySTFT = abs(noisySTFT(numFeatures-1:end,:));

Генерируйте 8-сегментные сигналы обучающего предиктора из шумного STFT. Перекрытие между последовательными предикторами составляет 7 сегментов.

noisySTFT = [noisySTFT(:,1:numSegments - 1), noisySTFT];
stftSegments = zeros(numFeatures, numSegments , size(noisySTFT,2) - numSegments + 1);
for index = 1:size(noisySTFT,2) - numSegments + 1
    stftSegments(:,:,index) = (noisySTFT(:,index:index + numSegments - 1)); 
end

Установите цели и предикторы. Последняя размерность обеих переменных соответствует количеству отдельных пар предиктор/цель, сгенерированных аудиофайлом. Каждый предиктор - 129 на 8, а каждая цель - 129 на 1.

targets = cleanSTFT;
size(targets)
ans = 1×2

   129   544

predictors = stftSegments;
size(predictors)
ans = 1×3

   129     8   544

Извлечение элементов с помощью массивов Tall

Чтобы ускорить обработку, извлеките последовательности функций из речевых сегментов всех аудиофайлов в хранилище данных с помощью массивов tall. В отличие от массивов в памяти, массивы tall обычно остаются невысокими до вызова gather функция. Этот отложенный анализ позволяет быстро работать с большими наборами данных. Когда вы в конечном итоге запрашиваете вывод с помощью gatherMATLAB объединяет вычисления в очереди, где это возможно, и принимает минимальное количество проходов через данные. При наличии Toolbox™ параллельных вычислений можно использовать массивы tall в локальной сессии MATLAB или в локальном пуле параллельных вычислений. Можно также выполнить вычисления массива высокого уровня в кластере, если установлен MATLAB ® Parallel Server™.

Сначала преобразуйте хранилище данных в массив высокого уровня.

reset(adsTrain)
T = tall(adsTrain)
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).
T =

  M×1 tall cell array

    {234480×1 double}
    {210288×1 double}
    {282864×1 double}
    {292080×1 double}
    {410736×1 double}
    {303600×1 double}
    {326640×1 double}
    {233328×1 double}
        :        :
        :        :

Отображение показывает, что количество строк (соответствующее количеству файлов в хранилище данных), M, еще не известно. M является местозаполнителем до завершения расчета.

Извлеките целевую и предикторную величины STFT из таблицы высокого уровня. Это действие создает новые переменные массива высокого уровня для использования в последующих вычислениях. Функция HelperGenerateSpeechDenoisingFeatures выполняет шаги, уже выделенные в разделе STFT Targets and Predictors. cellfun применяется команда HelperGenerateSpeechDenoisingFeatures к содержимому каждого аудиофайла в хранилище данных.

[targets,predictors] = cellfun(@(x)HelperGenerateSpeechDenoisingFeatures(x,noise,src),T,"UniformOutput",false);

Использовать gather для оценки целей и предикторов.

[targets,predictors] = gather(targets,predictors);
Evaluating tall expression using the Parallel Pool 'local':
- Pass 1 of 1: Completed in 42 sec
Evaluation completed in 1 min 36 sec

Рекомендуется нормализовать все элементы до нулевого среднего и единичного стандартного отклонения.

Вычислите среднее и стандартное отклонения предикторов и целей соответственно и используйте их для нормализации данных.

predictors = cat(3,predictors{:});
noisyMean = mean(predictors(:));
noisyStd = std(predictors(:));
predictors(:) = (predictors(:) - noisyMean)/noisyStd;

targets = cat(2,targets{:});
cleanMean = mean(targets(:));
cleanStd = std(targets(:));
targets(:) = (targets(:) - cleanMean)/cleanStd;

Изменить предикторы и цели в соответствии с измерениями, ожидаемыми сетями глубокого обучения.

predictors = reshape(predictors,size(predictors,1),size(predictors,2),1,size(predictors,3));
targets = reshape(targets,1,1,size(targets,1),size(targets,2));

Вы будете использовать 1% данных для проверки во время обучения. Проверка полезна для выявления сценариев, когда сеть переоборудует данные обучения.

Случайное разделение данных на обучающие и проверочные наборы.

inds = randperm(size(predictors,4));
L = round(0.99 * size(predictors,4));

trainPredictors = predictors(:,:,:,inds(1:L));
trainTargets = targets(:,:,:,inds(1:L));

validatePredictors = predictors(:,:,:,inds(L+1:end));
validateTargets = targets(:,:,:,inds(L+1:end));

Обличение речи с полностью подключенными слоями

В первую очередь рассматривается денойзинговая сеть, состоящая из полностью соединенных слоев. Каждый нейрон в полностью связанном слое соединен со всеми активациями из предыдущего слоя. Полностью связанный слой умножает входной сигнал на весовую матрицу и затем добавляет вектор смещения. Размеры весовой матрицы и вектора смещения определяются количеством нейронов в слое и количеством активаций из предыдущего слоя.

Определите уровни сети. Укажите размер ввода, который должен быть размером изображений NumFeaturesоколо-NumSegments (129 на 8 в этом примере). Определите два скрытых полностью соединенных слоя, каждый с 1024 нейронами. Поскольку это чисто линейные системы, следите за каждым скрытым полностью соединенным слоем с уровнем ReLU. Уровни пакетной нормализации нормализуют средние и стандартные отклонения выходных данных. Добавьте полностью связанный слой с 129 нейронами, а затем регрессионный слой.

layers = [
    imageInputLayer([numFeatures,numSegments])
    fullyConnectedLayer(1024)
    batchNormalizationLayer
    reluLayer
    fullyConnectedLayer(1024)
    batchNormalizationLayer
    reluLayer
    fullyConnectedLayer(numFeatures)
    regressionLayer
    ];

Затем укажите параметры обучения для сети. Набор MaxEpochs кому 3 так, что сеть 3 проходит через обучающие данные. Набор MiniBatchSize из 128 чтобы сеть просматривала 128 обучающих сигналов одновременно. Определить Plots как "training-progress" для создания графиков, показывающих ход обучения по мере увеличения числа итераций. Набор Verbose кому false для отключения печати выходных данных таблицы, соответствующих данным, отображаемым на графике, в окне командной строки. Определить Shuffle как "every-epoch" для перетасовки тренировочных последовательностей в начале каждой эпохи. Определить LearnRateSchedule кому "piecewise" снижать скорость обучения на заданный коэффициент (0,9) каждый раз, когда проходит определенное количество эпох (1). Набор ValidationData к предикторам и целям проверки. Набор ValidationFrequency так, что средняя квадратная ошибка проверки вычисляется один раз за эпоху. В этом примере используется решатель адаптивной оценки момента (Адам).

miniBatchSize = 128;
options = trainingOptions("adam", ...
    "MaxEpochs",3, ...
    "InitialLearnRate",1e-5,...
    "MiniBatchSize",miniBatchSize, ...
    "Shuffle","every-epoch", ...
    "Plots","training-progress", ...
    "Verbose",false, ...
    "ValidationFrequency",floor(size(trainPredictors,4)/miniBatchSize), ...
    "LearnRateSchedule","piecewise", ...
    "LearnRateDropFactor",0.9, ...
    "LearnRateDropPeriod",1, ...
    "ValidationData",{validatePredictors,validateTargets});

Обучение сети с указанными вариантами обучения и архитектурой уровней с помощью trainNetwork. Поскольку тренировочный набор большой, тренировочный процесс может занять несколько минут. Чтобы загрузить и загрузить предварительно обученную сеть вместо обучения сети с нуля, установите doTraining кому false.

doTraining = true;
if doTraining
    denoiseNetFullyConnected = trainNetwork(trainPredictors,trainTargets,layers,options);
else
    url = 'http://ssd.mathworks.com/supportfiles/audio/SpeechDenoising.zip';
    downloadNetFolder = tempdir;
    netFolder = fullfile(downloadNetFolder,'SpeechDenoising');
    if ~exist(netFolder,'dir')
        disp('Downloading pretrained network (1 file - 8 MB) ...')
        unzip(url,downloadNetFolder)
    end
    s = load(fullfile(netFolder,"denoisenet.mat"));
    denoiseNetFullyConnected = s.denoiseNetFullyConnected;
    cleanMean = s.cleanMean;
    cleanStd = s.cleanStd;
    noisyMean = s.noisyMean;
    noisyStd = s.noisyStd;
end

Подсчитайте количество весов в полностью подключенных слоях сети.

numWeights = 0;
for index = 1:numel(denoiseNetFullyConnected.Layers)
    if isa(denoiseNetFullyConnected.Layers(index),"nnet.cnn.layer.FullyConnectedLayer")
        numWeights = numWeights + numel(denoiseNetFullyConnected.Layers(index).Weights);
    end
end
fprintf("The number of weights is %d.\n",numWeights);
The number of weights is 2237440.

Отрицание речи со сверточными слоями

Рассмотрим сеть, использующую сверточные слои вместо полностью соединенных [3]. 2-D сверточный слой применяет к входу скользящие фильтры. Слой свертывает входной сигнал, перемещая фильтры по входному сигналу вертикально и горизонтально и вычисляя скалярное произведение весов и входного сигнала, а затем добавляя элемент смещения. Сверточные слои обычно состоят из меньшего количества параметров, чем полностью соединенные слои.

Определите уровни полностью сверточной сети, описанной в [3], содержащей 16 сверточных слоев. Первые 15 сверточных слоев представляют собой группы из 3 слоев, повторяющихся 5 раз, с шириной фильтра 9, 5 и 9 и количеством фильтров 18, 30 и 8 соответственно. Последний сверточный слой имеет ширину фильтра 129 и 1 фильтр. В этой сети свертки выполняются только в одном направлении (вдоль частотной размерности), а ширина фильтра вдоль временной размерности устанавливается равной 1 для всех слоев, кроме первого. Аналогично полностью подключенной сети, за сверточными уровнями следуют уровни ReLu и пакетной нормализации.

layers = [imageInputLayer([numFeatures,numSegments])
          convolution2dLayer([9 8],18,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer
          
          repmat( ...
          [convolution2dLayer([5 1],30,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer
          convolution2dLayer([9 1],8,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer
          convolution2dLayer([9 1],18,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer],4,1)
          
          convolution2dLayer([5 1],30,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer
          convolution2dLayer([9 1],8,"Stride",[1 100],"Padding","same")
          batchNormalizationLayer
          reluLayer
          
          convolution2dLayer([129 1],1,"Stride",[1 100],"Padding","same")
          
          regressionLayer
          ];

Варианты обучения идентичны вариантам для полностью подключенной сети, за исключением того, что размеры целевых сигналов проверки подлинности переставляются, чтобы соответствовать размерам, ожидаемым уровнем регрессии.

options = trainingOptions("adam", ...
    "MaxEpochs",3, ...
    "InitialLearnRate",1e-5, ...
    "MiniBatchSize",miniBatchSize, ...
    "Shuffle","every-epoch", ...
    "Plots","training-progress", ...
    "Verbose",false, ...
    "ValidationFrequency",floor(size(trainPredictors,4)/miniBatchSize), ...
    "LearnRateSchedule","piecewise", ...
    "LearnRateDropFactor",0.9, ...
    "LearnRateDropPeriod",1, ...
    "ValidationData",{validatePredictors,permute(validateTargets,[3 1 2 4])});

Обучение сети с указанными вариантами обучения и архитектурой уровней с помощью trainNetwork. Поскольку тренировочный набор большой, тренировочный процесс может занять несколько минут. Чтобы загрузить и загрузить предварительно обученную сеть вместо обучения сети с нуля, установите doTraining кому false.

doTraining = true;
if doTraining
    denoiseNetFullyConvolutional = trainNetwork(trainPredictors,permute(trainTargets,[3 1 2 4]),layers,options);
else
    url = 'http://ssd.mathworks.com/supportfiles/audio/SpeechDenoising.zip';
    downloadNetFolder = tempdir;
    netFolder = fullfile(downloadNetFolder,'SpeechDenoising');
    if ~exist(netFolder,'dir')
        disp('Downloading pretrained network (1 file - 8 MB) ...')
        unzip(url,downloadNetFolder)
    end
    s = load(fullfile(netFolder,"denoisenet.mat"));
    denoiseNetFullyConvolutional = s.denoiseNetFullyConvolutional;
    cleanMean = s.cleanMean;
    cleanStd = s.cleanStd;
    noisyMean = s.noisyMean;
    noisyStd = s.noisyStd;
end

Подсчитайте количество весов в полностью подключенных слоях сети.

numWeights = 0;
for index = 1:numel(denoiseNetFullyConvolutional.Layers)
    if isa(denoiseNetFullyConvolutional.Layers(index),"nnet.cnn.layer.Convolution2DLayer")
        numWeights = numWeights + numel(denoiseNetFullyConvolutional.Layers(index).Weights);
    end
end
fprintf("The number of weights in convolutional layers is %d\n",numWeights);
The number of weights in convolutional layers is 31812

Протестируйте сети Denoising

Прочтите в наборе тестовых данных.

adsTest = audioDatastore(fullfile(dataFolder,'test'),'IncludeSubfolders',true);

Считывание содержимого файла из хранилища данных.

[cleanAudio,adsTestInfo] = read(adsTest);

Убедитесь, что длина звука кратна коэффициенту прореживания преобразователя частоты дискретизации.

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

Преобразуйте звуковой сигнал в 8 кГц.

cleanAudio = src(cleanAudio);
reset(src)

На этом этапе тестирования вы повреждаете речь с помощью шума стиральной машины, не используемого на этапе обучения.

noise = audioread("WashingMachine-16-8-mono-200secs.mp3");

Создайте сегмент случайного шума из вектора шума стиральной машины.

randind = randi(numel(noise) - numel(cleanAudio), [1 1]);
noiseSegment = noise(randind : randind + numel(cleanAudio) - 1);

Добавьте шум к речевому сигналу таким образом, чтобы SNR был равен 0 дБ.

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

Использовать stft для формирования векторов STFT величины из шумных аудиосигналов.

noisySTFT = stft(noisyAudio,'Window',win,'OverlapLength',overlap,'FFTLength',ffTLength);
noisyPhase = angle(noisySTFT(numFeatures-1:end,:));
noisySTFT = abs(noisySTFT(numFeatures-1:end,:));

Генерируйте 8-сегментные сигналы обучающего предиктора из шумного STFT. Перекрытие между последовательными предикторами составляет 7 сегментов.

noisySTFT = [noisySTFT(:,1:numSegments-1) noisySTFT];
predictors = zeros( numFeatures, numSegments , size(noisySTFT,2) - numSegments + 1);
for index = 1:(size(noisySTFT,2) - numSegments + 1)
    predictors(:,:,index) = noisySTFT(:,index:index + numSegments - 1); 
end

Нормализуйте предикторы на среднее и стандартное отклонение, вычисленное на этапе обучения.

predictors(:) = (predictors(:) - noisyMean) / noisyStd;

Вычислить денозированную величину STFT с помощью predict с двумя обученными сетями.

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

Масштабирование выходных данных по среднему и стандартному отклонению, используемому на этапе обучения.

STFTFullyConnected(:) = cleanStd * STFTFullyConnected(:) + cleanMean;
STFTFullyConvolutional(:) = cleanStd * STFTFullyConvolutional(:) + cleanMean;

Преобразование одностороннего STFT в центрированный STFT.

STFTFullyConnected = STFTFullyConnected.' .* exp(1j*noisyPhase);
STFTFullyConnected = [conj(STFTFullyConnected(end-1:-1:2,:)); STFTFullyConnected];
STFTFullyConvolutional = squeeze(STFTFullyConvolutional) .* exp(1j*noisyPhase);
STFTFullyConvolutional = [conj(STFTFullyConvolutional(end-1:-1:2,:)) ; STFTFullyConvolutional];

Вычислите деноизированные речевые сигналы. istft выполняет обратный STFT. Используйте фазу шумных STFT векторов для восстановления сигнала временной области.

denoisedAudioFullyConnected = istft(STFTFullyConnected,  ...
                                    'Window',win,'OverlapLength',overlap, ...
                                    'FFTLength',ffTLength,'ConjugateSymmetric',true);
                                
denoisedAudioFullyConvolutional = istft(STFTFullyConvolutional,  ...
                                        'Window',win,'OverlapLength',overlap, ...
                                        'FFTLength',ffTLength,'ConjugateSymmetric',true);

Постройте график чистых, шумных и шумных звуковых сигналов.

t = (1/fs) * (0:numel(denoisedAudioFullyConnected)-1);

figure

subplot(4,1,1)
plot(t,cleanAudio(1:numel(denoisedAudioFullyConnected)))
title("Clean Speech")
grid on

subplot(4,1,2)
plot(t,noisyAudio(1:numel(denoisedAudioFullyConnected)))
title("Noisy Speech")
grid on

subplot(4,1,3)
plot(t,denoisedAudioFullyConnected)
title("Denoised Speech (Fully Connected Layers)")
grid on

subplot(4,1,4)
plot(t,denoisedAudioFullyConvolutional)
title("Denoised Speech (Convolutional Layers)")
grid on
xlabel("Time (s)")

Постройте график чистых, шумных и шумных спектрограмм.

h = figure;

subplot(4,1,1)
spectrogram(cleanAudio,win,overlap,ffTLength,fs);
title("Clean Speech")
grid on

subplot(4,1,2)
spectrogram(noisyAudio,win,overlap,ffTLength,fs);
title("Noisy Speech")
grid on

subplot(4,1,3)
spectrogram(denoisedAudioFullyConnected,win,overlap,ffTLength,fs);
title("Denoised Speech (Fully Connected Layers)")
grid on

subplot(4,1,4)
spectrogram(denoisedAudioFullyConvolutional,win,overlap,ffTLength,fs);
title("Denoised Speech (Convolutional Layers)")
grid on

p = get(h,'Position');
set(h,'Position',[p(1) 65 p(3) 800]);

Слушай шумную речь.

sound(noisyAudio,fs)

Прослушивание запрещенной речи из сети с полностью подключенными уровнями.

sound(denoisedAudioFullyConnected,fs)

Прослушивание засекреченной речи из сети со сверточными слоями.

sound(denoisedAudioFullyConvolutional,fs)

Слушай чистую речь.

sound(cleanAudio,fs)

Вы можете протестировать больше файлов из хранилища данных, позвонив testDenoisingNets. Функция создает графики временной и частотной областей, выделенные выше, а также возвращает чистые, шумные и деноизированные звуковые сигналы.

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

Приложение реального времени

Процедура в предыдущем разделе передает весь спектр шумного сигнала в predict. Это не подходит для приложений реального времени, для которых требуется низкая задержка.

Управляемый speechDenoisingRealtimeApp для примера, как имитировать потоковую, в реальном времени, версию запрещающей сети. Приложение использует сеть с полностью подключенными слоями. Длина аудиокадра равна размеру перехода STFT, который равен 0,25 * 256 = 64 отсчетов.

speechDenoisingRealtimeApp запускает пользовательский интерфейс, предназначенный для взаимодействия с моделированием. Пользовательский интерфейс позволяет настраивать параметры, и результаты мгновенно отражаются в моделировании. Также можно включить/выключить шумовой затвор, который работает на шумовом выходе, чтобы дополнительно уменьшить шум, а также настроить время атаки, время освобождения и порог шумового затвора. Вы можете слушать шумный, чистый или шумный звук от пользовательского интерфейса.

Область применения включает в себя чистые, шумные и денозированные сигналы, а также коэффициент усиления шумового затвора.

Ссылки

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

[2] «Эксперименты по глубокому обучению для отрицания речи», Дин Лю, Париж Смарагдис, Минье Ким, INTERSPEECH, 2014.

[3] «Полностью сверточная нейронная сеть для улучшения речи», Se Rim Park, Jin Won Lee, INTERSPEECH, 2017.

См. также

Функции

Связанные темы