Отслеживание тангажа с использованием нескольких оценок тангажа и HMM

Этот пример показывает, как выполнить отслеживание тангажа с помощью нескольких оценок тангажа, октавного и медианного сглаживания и скрытой модели Маркова (HMM).

Введение

Обнаружение тангажа является фундаментальным базовым блоком в обработке речи, кодировании речи и поиске музыкальной информации (MIR). При распознавании речи и динамика тангаж используется как функция в системе машинного обучения. Для вызовов тангаж используется для указания эмоционального состояния и пола клиентов. В логопедии тангаж используется для индикации и анализа патологий и диагностики физических дефектов. В MIR тангаж используется для категоризации музыки, для систем запроса за хумингом и в качестве основной функции в системах идентификации песен.

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

Обычно алгоритм обнаружения тангажа (PDA) оценивает тангаж для заданного момента времени. Оценка тангажа затем проверяется или корректируется в системе отслеживания тангажа. Системы отслеживания тангажа обеспечивают непрерывность оценок тангажа с течением времени.

Этот пример предоставляет функцию , взятую в качестве примера,, HelperPitchTracker, который реализует систему отслеживания тангажа. Пример проходит через алгоритм, реализованный HelperPitchTracker функция.

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

Загрузите аудиофайл и соответствующий эталонный шаг для аудиофайла. Ссылка тангажа сообщается каждые 10 мс и определялся как среднее значение нескольких сторонних алгоритмов в чистом речевом файле. Области без голосовой речи представлены как nan.

[x,fs] = audioread('Counting-16-44p1-mono-15secs.wav');
load TruePitch.mat truePitch

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

[f0,locs] = pitch(x,fs);

При определении ошибки тангажа обычно сообщаются две метрики: грубая ошибка тангажа (GPE) и ошибка принятия голосового решения (VDE). Поскольку алгоритмы тангажа в этом примере не обеспечивают озвучивание решения, сообщается только о GPE. В этом примере GPE вычисляется как процент оценок тангажа вне ±10% опорного тангажа по размаху голосовых сегментов.

Вычислите GPE для областей речи и постройте график результатов. Слушайте чистый аудиосигнал.

isVoiced = ~isnan(truePitch);
f0(~isVoiced) = nan;

p = 0.1;
GPE = mean(abs(f0(isVoiced)-truePitch(isVoiced)) > truePitch(isVoiced).*p).*100;

t = (0:length(x)-1)/fs;
t0 = (locs-1)/fs;
sound(x,fs)

figure(1)
tiledlayout(2,1)
nexttile
plot(t,x)
ylabel('Amplitude')
title('Pitch Estimation of Clean Signal')

nexttile
plot(t0,[truePitch,f0])
legend('Reference','Estimate','Location','NW')
ylabel('F0 (Hz)')
xlabel('Time (s)')
title(sprintf('GPE = %0.1f%%',GPE))

Смешайте речевой сигнал с шумом при -5 ОСШ дБ.

Используйте pitch функция на шумном звуке для оценки тангажа с течением времени. Вычислите GPE для областей озвученной речи и постройте график результатов. Слушайте шумный аудиосигнал.

desiredSNR = -5;
x = mixSNR(x,rand(size(x)),desiredSNR);

[f0,locs] = pitch(x,fs);
f0(~isVoiced) = nan;
GPE = mean(abs(f0(isVoiced) - truePitch(isVoiced)) > truePitch(isVoiced).*p).*100;

sound(x,fs)

figure(2)
tiledlayout(2,1)

nexttile
plot(t,x)
ylabel('Amplitude')
title('Pitch Estimation of Noisy Signal')

nexttile
plot(t0,[truePitch,f0])
legend('Reference','Estimate','Location','NW')
ylabel('F0 (Hz)')
xlabel('Time (s)')
title(sprintf('GPE = %0.1f%%',GPE))

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

Алгоритм, описанный в этом примере, реализован в функция , взятая в качестве примера, HelperPitchTracker. Чтобы узнать о HelperPitchTracker function, введите help HelperPitchTracker в командной строке.

help HelperPitchTracker
 HelperPitchTracker Track the fundamental frequency of audio signal
    f0 = HelperPitchTracker(audioIn,fs) returns an estimate of the
    fundamental frequency contour for the audio input. Columns of the
    input are treated as individual channels. The HelperPitchTracker
    function uses multiple pitch detection algorithms to generate pitch
    candidates, and uses octave smoothing and a Hidden Markov Model to
    return an estimate of the fundamental frequency.
 
    f0 = HelperPitchTracker(...,'HopLength',HOPLENGTH) specifies the number
    of samples in each hop. The pitch estimate is updated every hop.
    Specify HOPLENGTH as a scalar integer. If unspecified, HOPLENGTH
    defaults to round(0.01*fs).
 
    f0 = HelperPitchTracker(...,'OctaveSmoothing',TF) specifies whether or
    not to apply octave smoothing. Specify as true or false. If
    unspecified, TF defaults to true.
 
    f0 = HelperPitchTracker(...,'EmissionMatrix',EMISSIONMATRIX) specifies
    the emission matrix used for the HMM during the forward pass. The
    default emission matrix was trained on the Pitch Tracking Database from
    Graz University of Technology. The database consists of 4720 speech
    segments with corresponding pitch trajectories derived from
    laryngograph signals. The emission matrix corresponds to the
    probability that a speaker leaves one pitch state to another, in the
    range [50, 400] Hz. Specify the emission matrix such that rows
    correspond to the current state, columns correspond to the possible
    future state, and the values of the matrix correspond to the
    probability of moving from the current state to the future state. If
    you specify your own emission matrix, specify its corresponding
    EMISSIONMATRIXRANGE. EMISSIONMATRIX must be a real N-by-N matrix of
    integers.
 
    f0 = HelperPitchTracker(...,'EmissionMatrixRange',EMISSIONMATRIXRANGE)
    specifies how the EMISSIONMATRIX corresponds to Hz. If unspecified,
    EMISSIONMATRIXRANGE defaults to 50:400.
 
    [f0,loc] = HelperPitchTracker(...) returns the locations associated
    with each pitch decision. The locations correspond to the ceiling of
    the center of the analysis frames.
 
    [f0,loc,hr] = HelperPitchTracker(...) returns the harmonic ratio
    associated with each pitch decision.
 
  See also pitch, voiceActivityDetector

Описание системы отслеживания тангажа

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

1. Сгенерируйте несколько кандидатов тангажа

На первом этапе системы отслеживания тангажа вы генерируете несколько кандидатов тангажа с помощью нескольких алгоритмов обнаружения тангажа. Первичные кандидаты тангажа, которые в целом более точны, сгенерированы с помощью алгоритмов, основанных на алгоритме Суммирования остаточных гармоник (SRH) [2] и алгоритме оценки тангажа с амплитудным сжатием (PEFAC) [3].

Буферизуйте шумный входной сигнал в перекрываемые системы координат, а затем используйте audio.internal.pitch.SRH чтобы сгенерировать 5 кандидатов тангажа для каждого скачка. Также верните относительное доверие каждого кандидата на тангаж. Постройте график результатов.

RANGE = [50,400];
HOPLENGTH = round(fs.*0.01);

% Buffer into required sizes
xBuff_SRH = buffer(x,round(0.025*fs),round(0.02*fs),'nodelay');

% Define pitch parameters
params_SRH = struct('Method','SRH', ...
    'Range',RANGE, ...
    'WindowLength',round(fs*0.06), ...
    'OverlapLength',round(fs*0.06-HOPLENGTH), ...
    'SampleRate',fs, ...
    'NumChannels',size(x,2), ...
    'SamplesPerChannel',size(x,1));
multiCandidate_params_SRH = struct('NumCandidates',5,'MinPeakDistance',1);

% Get pitch estimate and confidence
[f0_SRH,conf_SRH] = audio.internal.pitch.SRH(xBuff_SRH,x, ...
                                             params_SRH, ...
                                             multiCandidate_params_SRH);
figure(3)
tiledlayout(2,1)
nexttile
plot(t0,f0_SRH)
ylabel('F0 Candidates (Hz)')
title('Multiple Candidates from SRH Pitch Estimation')
nexttile
plot(t0,conf_SRH)
ylabel('Relative Confidence')
xlabel('Time (s)')

Сгенерируйте дополнительный набор кандидатов основного тангажа и связанного с ним доверия с помощью алгоритма PEF. Сгенерируйте резервные кандидаты и связанные с ними доверия, используя алгоритм нормализованной корреляционной функции (NCF) и алгоритм определения тангажа (CEP) cepstrum. Логгирование только самой уверенной оценки из резервных кандидатов.

xBuff_PEF = buffer(x,round(0.06*fs),round(0.05*fs),'nodelay');
params_PEF = struct('Method','PEF', ...
    'Range',RANGE, ...
    'WindowLength',round(fs*0.06), ...
    'OverlapLength',round(fs*0.06-HOPLENGTH), ...
    'SampleRate',fs, ...
    'NumChannels',size(x,2), ...
    'SamplesPerChannel',size(x,1));
multiCandidate_params_PEF = struct('NumCandidates',5,'MinPeakDistance',5);
[f0_PEF,conf_PEF] = audio.internal.pitch.PEF(xBuff_PEF, ...
                                             params_PEF, ...
                                             multiCandidate_params_PEF);

xBuff_NCF = buffer(x,round(0.04*fs),round(0.03*fs),'nodelay');
xBuff_NCF = xBuff_NCF(:,2:end-1);
params_NCF = struct('Method','NCF', ...
    'Range',RANGE, ...
    'WindowLength',round(fs*0.04), ...
    'OverlapLength',round(fs*0.04-HOPLENGTH), ...
    'SampleRate',fs, ...
    'NumChannels',size(x,2), ...
    'SamplesPerChannel',size(x,1));
multiCandidate_params_NCF = struct('NumCandidates',5,'MinPeakDistance',1);
f0_NCF = audio.internal.pitch.NCF(xBuff_NCF, ...
                                  params_NCF, ...
                                  multiCandidate_params_NCF);

xBuff_CEP = buffer(x,round(0.04*fs),round(0.03*fs),'nodelay');
xBuff_CEP = xBuff_CEP(:,2:end-1);
params_CEP = struct('Method','CEP', ...
    'Range',RANGE, ...
    'WindowLength',round(fs*0.04), ...
    'OverlapLength',round(fs*0.04-HOPLENGTH), ...
    'SampleRate',fs, ...
    'NumChannels',size(x,2), ...
    'SamplesPerChannel',size(x,1));
multiCandidate_params_CEP = struct('NumCandidates',5,'MinPeakDistance',1);
f0_CEP = audio.internal.pitch.CEP(xBuff_CEP, ...
                                  params_CEP, ...
                                  multiCandidate_params_CEP);

BackupCandidates = [f0_NCF(:,1),f0_CEP(:,1)];

2. Определите долгосрочный Медиан

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

hr = harmonicRatio(xBuff_PEF,fs, ...
                  'Window',hamming(size(xBuff_NCF,1),'periodic'), ...
                  'OverlapLength',0);

figure(4)
tiledlayout(2,1)
nexttile
plot(t,x)
ylabel('Amplitude')
nexttile
plot(t0,hr)
ylabel('Harmonic Ratio')
xlabel('Time (s)')

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

idxToKeep = logical(movmedian(hr>((3/4)*max(hr)),3));
longTermMedian = median([f0_PEF(idxToKeep,1);f0_SRH(idxToKeep,1)]);
lower = max((2/3)*longTermMedian,RANGE(1));
upper = min((4/3)*longTermMedian,RANGE(2));

figure(5)
tiledlayout(1,1)
nexttile
plot(t0,[f0_PEF,f0_SRH])
hold on
plot(t0,longTermMedian.*ones(size(f0_PEF,1)),'r:','LineWidth',3)
plot(t0,upper.*ones(size(f0_PEF,1)),'r','LineWidth',2)
plot(t0,lower.*ones(size(f0_PEF,1)),'r','LineWidth',2)
hold off
xlabel('Time (s)')
ylabel('Frequency (Hz)')
title('Long Term Median')

3. Сокращение кандидата

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

Постройте график сокращенных кандидатов.

invalid = f0_PEF>lower | f0_PEF>upper;
conf_PEF(invalid) = conf_PEF(invalid)/10;
[conf_PEF,order] = sort(conf_PEF,2,'descend');
for i = 1:size(f0_PEF,1)
    f0_PEF(i,:) = f0_PEF(i,order(i,:));
end

invalid = f0_SRH>lower | f0_SRH>upper;
conf_SRH(invalid) = conf_SRH(invalid)/10;
[conf_SRH,order] = sort(conf_SRH,2,'descend');
for i = 1:size(f0_SRH,1)
    f0_SRH(i,:) = f0_SRH(i,order(i,:));
end

candidates = [f0_PEF(:,1:2),f0_SRH(:,1:2)];
confidence = [conf_PEF(:,1:2),conf_SRH(:,1:2)];

figure(6)
plot(t0,candidates)
xlabel('Time (s)')
ylabel('Frequency (Hz)')
title('Reduced Candidates')

4. Делайте отличительные

Если два или более кандидата находятся в пределах заданного диапазона 5 Гц, задайте среднее значение для кандидатов и суммируйте их доверие.

span = 5;
confidenceFactor = 1;
for r = 1:size(candidates,1)
    for c = 1:size(candidates,2)
        tf = abs(candidates(r,c)-candidates(r,:)) < span;
        candidates(r,c) = mean(candidates(r,tf));
        confidence(r,c) = sum(confidence(r,tf))*confidenceFactor;
    end
end
candidates = max(min(candidates,400),50);

5. Прямая итерация HMM с октавным сглаживанием

Теперь, когда кандидаты были сокращены, можно загрузить их в HMM, чтобы применить ограничения непрерывности. Контуры тангажа обычно непрерывны для речевых сигналов при анализе в скачках 10 мс. Вероятность перехода тангажа от одного состояния к другому через время упоминается как вероятность излучения. Вероятности излучения могут быть инкапсулированы в матрицу, которая описывает вероятность перехода от любого значения тангажа в заданной области значений к любому другому в заданной области значений. Матрица выбросов, использованная в этом примере, была создана с использованием базы данных Граца. [1]

Загрузите матрицу выбросов и связанную область значений. Постройте график функции плотности вероятностей (PDF) тангажа в состоянии 150 Гц.

load EmissionMatrix.mat emissionMatrix emissionMatrixRange

currentState = 150;

рисунок (7)
график (emissionMatrixRange (1): emissionMatrixRange (2), emissionMatrix (currentState - emissionMatrixRange (1) -1,:))
заголовок (sprintf ('Emission PDF for %d Hz', currentState))
xlabel ('Next Pitch Value (Hz)')
ylabel ('Probability')

HMM, используемый в этом примере, объединяет вероятности выбросов, которые обеспечивают непрерывность и относительное доверие тангажа. На каждом скачке вероятности излучения объединяются с относительным доверием, чтобы создать матрицу доверия. Лучший выбор для каждого пути определяется как макс матрицы доверия. HMM, используемый в этом примере, также принимает, что только один путь может быть назначен заданному состоянию (предположение алгоритма Viterbi).

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

% Preallocation
numPaths = 4;
numHops = size(candidates,1);
logbook = zeros(numHops,3,numPaths);
suspectHops = zeros(numHops,1);

% Forward iteration with octave-smoothing
for hopNumber = 1:numHops
    nowCandidates = candidates(hopNumber,:);
    nowConfidence = confidence(hopNumber,:);
    
    % Remove octave jumps
    if hopNumber > 100
        numCandidates = numel(nowCandidates);
        
        % Weighted short term median
        medianWindowLength = 50;
        aTemp = logbook(max(hopNumber-min(hopNumber,medianWindowLength),1):hopNumber-1,1,:);
        shortTermMedian = median(aTemp(:));
        previousM = mean([longTermMedian,shortTermMedian]);
        lowerTight = max((4/3)*previousM,emissionMatrixRange(1));
        upperTight = min((2/3)*previousM,emissionMatrixRange(2));
        numCandidateOutside = sum([nowCandidates < lowerTight, nowCandidates > upperTight]);
        
        % If at least 1 candidate is outside the octave centered on the
        % short-term median, add the backup pitch candidates that were
        % generated by the normalized correlation function and cepstrum
        % pitch determination algorithms as potential candidates.
        if numCandidateOutside > 0
            % Apply the backup pitch estimators
            nowCandidates = [nowCandidates,BackupCandidates(hopNumber,:)];%#ok<AGROW>
            nowConfidence = [nowConfidence,repmat(mean(nowConfidence),1,2)];%#ok<AGROW>
            
            % Make distinctive
            span = 10;
            confidenceFactor = 1.2;
            for r = 1:size(nowCandidates,1)
                for c = 1:size(nowCandidates,2)
                    tf = abs(nowCandidates(r,c)-nowCandidates(r,:)) < span;
                    nowCandidates(r,c) = mean(nowCandidates(r,tf));
                    nowConfidence(r,c) = sum(nowConfidence(r,tf))*confidenceFactor;
                end
            end
        end
    end
    
    % Create confidence matrix
    confidenceMatrix = zeros(numel(nowCandidates),size(logbook,3));
    for pageIdx = 1:size(logbook,3)
        if hopNumber ~= 1
            pastPitch = floor(logbook(hopNumber-1,1,pageIdx)) - emissionMatrixRange(1) + 1;
        else
            pastPitch = nan;
        end
        for candidateNumber = 1:numel(nowCandidates)
            if hopNumber ~= 1
                % Get the current pitch and convert to an index in the range
                currentPitch = floor(nowCandidates(candidateNumber)) - emissionMatrixRange(1) + 1;
                confidenceMatrix(candidateNumber,pageIdx) = ...
                    emissionMatrix(currentPitch,pastPitch)*logbook(hopNumber-1,2,pageIdx)*nowConfidence(candidateNumber);
            else
                confidenceMatrix(candidateNumber,pageIdx) = 1;
            end
        end
    end
    
    % Assign an estimate for each path
    for pageIdx = 1:size(logbook,3)
        % Determine most confident transition from past to current pitch
        [~,idx] = max(confidenceMatrix(:));
        
        % Convert confidence matrix index to pitch and logbook page
        [chosenPitch,pastPitchIdx] = ind2sub([numel(nowCandidates),size(logbook,3)],idx);
        
        logbook(hopNumber,:,pageIdx) = ...
            [nowCandidates(chosenPitch), ...
            confidenceMatrix(chosenPitch,pastPitchIdx), ...
            pastPitchIdx];
        
        % Remove the chosen current pitch from the confidence matrix
        confidenceMatrix(chosenPitch,:) = NaN;
    end
    % Normalize confidence
    logbook(hopNumber,2,:) = logbook(hopNumber,2,:)/sum(logbook(hopNumber,2,:));
end

6. Отслеживание HMM

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

numHops = size(logbook,1);
keepLooking = true;
index = numHops + 1;

while keepLooking
    index = index - 1;
    if abs(max(logbook(index,2,:))-min(logbook(index,2,:)))~=0
        keepLooking = false;
    end
end

[~,bestPathIdx] = max(logbook(index,2,:));
bestIndices = zeros(numHops,1);
bestIndices(index) = bestPathIdx;

for ii = index:-1:2
    bestIndices(ii-1) = logbook(ii,3,bestIndices(ii));
end

bestIndices(bestIndices==0) = 1;
f0 = zeros(numHops,1);
for ii = (numHops):-1:2
    f0(ii) = logbook(ii,1,bestIndices(ii));
end

f0toPlot = f0;
f0toPlot(~isVoiced) = NaN;
GPE = mean( abs(f0toPlot(isVoiced) - truePitch(isVoiced)) > truePitch(isVoiced).*p).*100;
figure(8)
plot(t0,[truePitch,f0toPlot])
legend('Reference','Estimate')
ylabel('F0 (Hz)')
xlabel('Time (s)')
title(sprintf('GPE = %0.1f%%',GPE))

7. Движущийся Срединный Фильтр

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

f0 = movmedian(f0,3);
f0(~isVoiced) = NaN;

GPE = mean(abs(f0(isVoiced) - truePitch(isVoiced)) > truePitch(isVoiced).*p).*100;
figure(9)
plot(t0,[truePitch,f0])
legend('Reference','Estimate')
ylabel('F0 (Hz)')
xlabel('Time (s)')
title(sprintf('GPE = %0.1f%%',GPE))

Оценка эффективности

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

Этот пример использует базу данных отслеживания тангажа из Технологического университета Граца (PTDB-TUG) [4]. Набор данных состоит из 20 носителей английского языка, читающих 2342 фонетически богатых предложения из корпуса TIMIT. Загрузите и извлеките набор данных. В зависимости от вашей системы, загрузка и извлечение набора данных может занять приблизительно 1,5 часов.

url = 'https://www2.spsc.tugraz.at/databases/PTDB-TUG/SPEECH_DATA_ZIPPED.zip';
downloadFolder = tempdir;
datasetFolder = fullfile(downloadFolder,'PTDB-TUG');

if ~exist(datasetFolder,'dir')
    disp('Downloading PTDB-TUG (3.9 G) ...')
    unzip(url,datasetFolder)
end

Создайте audio datastore, который указывает на записи микрофона в базе данных. Установите метку, связанную с каждым файлом, в местоположение связанного известного файла тангажа. Набор данных содержит записи 10 носителей женского и 10 носителей мужского пола. Использование subset изолировать 10-й носитель женского и мужского пола. Обучите матрицу выбросов на основе исходных контуров тангажа для динамиков с 1 по 9 как мужского, так и женского пола.

ads = audioDatastore([fullfile(datasetFolder,"SPEECH DATA","FEMALE","MIC"),fullfile(datasetFolder,"SPEECH DATA","MALE","MIC")], ...
                     'IncludeSubfolders',true, ...
                     'FileExtensions','.wav');
wavFileNames = ads.Files;
ads.Labels = replace(wavFileNames,{'MIC','mic','wav'},{'REF','ref','f0'});

idxToRemove = contains(ads.Files,{'F10','M10'});
ads1 = subset(ads,idxToRemove);
ads9 = subset(ads,~idxToRemove);

Перетащите хранилища аудиоданных.

ads1 = shuffle(ads1);
ads9 = shuffle(ads9);

Матрица излучения описывает вероятность перехода от одного состояния тангажа к другому. На следующем шаге вы создаете матрицу эмиссии на основе динамиков с 1 по 9 как для мужского, так и для женского пола. База данных хранит ссылку значения тангажа, краткосрочную энергию и дополнительную информацию в текстовых файлах с расширением файлов f0. The getReferencePitch функция читается в значениях тангажа, если краткосрочная энергия выше порога. Порог определяли эмпирически в тестах на прослушивание. The HelperUpdateEmissionMatrix создает 2-мерную гистограмму, основанную на текущем состоянии тангажа и следующем состоянии тангажа. После создания гистограммы она нормирована, чтобы создать матрицу выбросов.

emissionMatrixRange = [50,400];
emissionMatrix = [];

for i = 1:numel(ads9.Files)
    x = getReferencePitch(ads9.Labels{i});
    emissionMatrix = HelperUpdateEmissionMatrix(x,emissionMatrixRange,emissionMatrix);
end
emissionMatrix = emissionMatrix + sqrt(eps);
emissionMatrix = emissionMatrix./norm(emissionMatrix);

Задайте различные типы фонового шума: белый, атмосфера, двигатель, реактивный двигатель и улица. Повторно отобразите их на 16 кГц, чтобы помочь ускорить проверку базы данных.

Определите ОСШ для тестирования в дБ как 10, 5, 0, -5 и -10.

noiseType = {'white','ambiance','engine','jet','street'};
numNoiseToTest = numel(noiseType);

desiredFs = 16e3;

whiteNoiseMaker = dsp.ColoredNoise('Color','white','SamplesPerFrame',40000,'RandomStream','mt19937ar with seed','BoundedOutput',true);
noise{1} = whiteNoiseMaker();
[ambiance,ambianceFs] = audioread('Ambiance-16-44p1-mono-12secs.wav');
noise{2} = resample(ambiance,desiredFs,ambianceFs);
[engine,engineFs] = audioread('Engine-16-44p1-stereo-20sec.wav');
noise{3} = resample(engine,desiredFs,engineFs);
[jet,jetFs] = audioread('JetAirplane-16-11p025-mono-16secs.wav');
noise{4} = resample(jet,desiredFs,jetFs);
[street,streetFs] = audioread('MainStreetOne-16-16-mono-12secs.wav');
noise{5} = resample(street,desiredFs,streetFs);

snrToTest = [10,5,0,-5,-10];
numSNRtoTest = numel(snrToTest);

Запустите алгоритм обнаружения тангажа для каждого ОСШ и типа шума для каждого файла. Вычислите среднее значение GPE между речевыми файлами. Этот пример сравнивает эффективность с популярным алгоритмом отслеживания тангажа: Sawtooth Waveform Inspired Pitch Estimator (SWIPE). Реализация алгоритма MATLAB ® находится в [5]. Чтобы запустить этот пример, не сравнивая с другими алгоритмами, установите compare на false. Следующее сравнение занимает около 15 минут.

compare = true;
numFilesToTest = 20;
p = 0,1;
GPE_pitchTracker = нули (numSNRtoTest, numNoiseToTest, numFilesToTest);
if выдержать сравнение
    GPE_swipe = GPE_pitchTracker;
end
for i = 1:numFilesToTest
    [cleanSpeech, info] = read (ads1);
    cleanSpeech = resample (cleanSpeech, designedFs, info.SampleRate);
    
    truePitch = getReferencePitch (info.Label {:});
    isVoiced = truePitch ~ = 0;
    truePitchInVoicedRegions = truePitch (isVoiced);
    
    for j = 1:numSNRtoTest
        for k = 1:numNoiseToTest
            noisySpeech = mixSNR (cleanSpeech, noise {k}, snrToTest (j));
            f0 = HelperPitchTracker (noisySpeech, designedFs,'EmissionMatrix', emissionMatrix,'EmissionMatrixRange', emissionMatrixRange);
            f0 = [0; f0]; % manual alignment with database.
            GPE_pitchTracker (j, k, i) = среднее (abs (f0 (isVoiced) - truePitchInVoicedRegions) > truePitchInVoicedRegions. * p). * 100;
            
            if выдержать сравнение
                f0 = swipep (noisySpeech, designedFs, [50 400], 0,01);
                f0 = f0 (3: end );% manual alignment with database.
                GPE_swipe (j, k, i) = среднее (abs (f0 (isVoiced) - truePitchInVoicedRegions) > truePitchInVoicedRegions. * p). * 100;
            end
        end
    end
end
GPE_pitchTracker = среднее (GPE_pitchTracker,3);

if выдержать сравнение
    GPE_swipe = среднее (GPE_swipe,3);
end

Постройте график полной ошибки тангажа для каждого типа шума.

for ii = 1:numel(noise)
    figure(9+ii)
    plot(snrToTest,GPE_pitchTracker(:,ii),'b')
    hold on
    if compare
        plot(snrToTest,GPE_swipe(:,ii),'g')
    end
    plot(snrToTest,GPE_pitchTracker(:,ii),'bo')
    if compare
        plot(snrToTest,GPE_swipe(:,ii),'gv')
    end
    title(noiseType(ii))
    xlabel('SNR (dB)')
    ylabel(sprintf('Gross Pitch Error (p = %0.2f)',p))
    if compare
        legend('HelperPitchTracker','SWIPE')
    else
        legend('HelperPitchTracker')
    end
    grid on
    hold off
end

Заключение

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

Ссылки

[1] G. Pirker, M. Wohlmayr, S. Petrik, and F. Pernkopf, «A Pitch Tracking Corpus with Evaluation on Multipitch Tracking Scenario», Interspeech, pp. 1509-1512, 2011.

[2] Драгман, Томас и Абир Алван. Joint Robust Voicing Detection and Pitch Estimation Based On Leastual Harmonics (неопр.) (недоступная ссылка). Материалы ежегодной конференции Международной ассоциации речевых коммуникаций INTERSPEECH. 2011, стр. 1973-1976.

[3] Гонсалес, Сира и Майк Брукс. «Фильтр для оценки Тангажа, устойчивый к высоким уровням шума (PEFAC)». 19-я Европейская конференция по обработке сигналов. Барселона, 2011, с. 451-455.

[4] Лаборатория обработки сигналов и речевой связи. Доступ к 26 сентября 2018 года. https://www.spsc.tugraz.at/databases-and-tools/ptdb-tug-pitch-tracking-database-from-graz-university-of-technology.html.

[5] «Артуро Камачо». Доступ к 26 сентября 2018 года. https://www.cise.ufl.edu/~acamacho/english/.

[6] «Fxpefac». Описание Fxpefac. Доступ к 26 сентября 2018 года. http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html.