Денуазируйте речь, используя Нейронные сети для глубокого обучения

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

Введение

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

Сводные данные проблем

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

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

Добавьте шум стиральной машины в речевой сигнал. Установите степень шума так, чтобы отношение сигнал/шум (ОСШ) составляло нуль дБ.

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 чтобы создать datastore для набора обучающих данных. Чтобы ускорить выполнение примера за счет эффективности, установите reduceDataset на true.

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

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

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

[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].

Аудио преобразуется в частотный диапазон с помощью Short-Time Преобразования Фурье (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 объект для преобразования аудио 48 кГц в 8 кГц.

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

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

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);

Добавьте шум к речевому сигналу так, чтобы ОСШ составлял 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

Извлечение функций с помощью длинных массивов

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

Сначала преобразуйте datastore в длинный массив.

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}
        :        :
        :        :

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

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

[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));

Шумоподавление речи с полносвязными слоями

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

Задайте слои сети. Задайте размер входа, чтобы быть изображениями размера NumFeatures-by- NumSegments (129 на 8 в этом примере). Задайте два скрытых полносвязных слоев, каждый с 1024 нейронами. Поскольку чисто линейные системы, следуйте за каждым скрытым полностью соединенным слоем с слоем Rectified Linear Unit (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, trainTarget, слои, опции);
else
    url = 'http://ssd.mathworks.com/supportfiles/audio/SpeechDenoising.zip';
    downloadNetFolder = tempdir;
    netFolder = fullfile (downloadNetFolder,'SpeechDenoising');
    if ~ существует (netFolder,'dir')
        disp ('Downloading pretrained network (1 file - 8 MB) ...')
        unzip (url, downloadNetFolder)
    end
    s = загрузка (полный файл (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 (trainTarget, [3 1 2 4]), слои, опции);
else
    url = 'http://ssd.mathworks.com/supportfiles/audio/SpeechDenoising.zip';
    downloadNetFolder = tempdir;
    netFolder = fullfile (downloadNetFolder,'SpeechDenoising');
    if ~ существует (netFolder,'dir')
        disp ('Downloading pretrained network (1 file - 8 MB) ...')
        unzip (url, downloadNetFolder)
    end
    s = загрузка (полный файл (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

Тестируйте денуазирующие сети

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

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

Чтение содержимого файла из datastore.

[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);

Добавьте шум к речевому сигналу так, чтобы ОСШ составлял 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)

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

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

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

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

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

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

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

Ссылки

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

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

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