LPC Анализ и синтез речи
В этом примере показано как реализовать метод сжатия речи, используя функциональность библиотеки EngeeDSP. В данном примере реализовано кодирование с линейным предсказанием (LPC) - это метод, используемый в основном в обработки аудиосигнала и речи для представления спектральной огибающей цифрового сигнала речи в сжатой форме с использованием информации линейной модели прогнозирования. В модели реализуется анализ и синтез LPC речевого сигнала.
В разделе "анализ" извлекаются из сигнала коэффициенты отражения и используются для вычисления остаточного сигнала.
В разделе "синтеза" восстанавливается сигнал с помощью остаточного сигнала и коэффициентов отражения.
Остаточный сигнал и коэффициенты отражения требуют меньшего количества битов для кодирования, чем исходный речевой сигнал.
Подключение библиотек, объявление входных данных
Подключение библиотек
using .EngeeDSP;
using Plots;
plotlyjs();
using WAV;
using Base64;
Объявление переменных
sample = 80;
var_load = load_audio();
step = EngeeDSP.step;
In1 = step( var_load, "$(@__DIR__)/check_signal.wav", sample );
Объявление структур данных и функций LPC
В этой модели речевой сигнал делится на кадры размером 80 отсчетов с перекрытием 160 отсчетов.
Каждый кадр обрабатывается окном Хэмминга.
Находят коэффициенты автокорреляции десятого порядка, а затем из коэффициентов автокорреляции вычисляют коэффициенты отражения с использованием алгоритма Левинсона-Дарбина. Исходный речевой сигнал проходит через анализирующий фильтр, который представляет собой нулевой фильтр с коэффициентами, равными коэффициентам отражения, полученным выше. Выход фильтра – остаточный сигнал. Этот остаточный сигнал проходит через фильтр синтеза, который является обратным фильтру анализа.
Выход синтезирующего фильтра представляет собой исходный сигнал.
mutable struct LPCAnalysisAndSynthesisOfSpeech
obj_Pre_Emphasis
obj_Overlap_Analysis_Windows
obj_Window
obj_Autocorrelation
obj_Levinson_Durbin
obj_Time_Varying_Analysis_Filter
obj_Pad
obj_FFT
obj_MathFunction1
obj_RC_To_InvSine
obj_5_bit_Quantizer
obj_6_bit_Quantizer
obj_Inv_Sine_to_RC
obj_Time_Varying_Synthesis_Filter
obj_De_emphasis_Filter
function LPCAnalysisAndSynthesisOfSpeech()
new(
DescretFIRFilter("Dialog parameters","Direct form",[1, -.95],"Columns as channels",0,false,"None"),
Buffer(160,80,0),
WindowFunction("Apply window to input","Hamming","Symmetric"),
Autocorrelation("Biased",10),
LevinsonDurbin("A and K",false,true),
DescretFIRFilter("Input port","Lattice MA","Columns as channels",0,false,"None"),
EngeeDSP.Pad("Columns","Specify via dialog",0,"User-specified",256,"End","None"),
EngeeFFT("Auto",false,false,true),
MathFunction("reciprocal","Exact","auto"),
TrigonometricFunction("asin","auto",false),
Quantizer(0.1,false),
Quantizer(0.03125,false),
TrigonometricFunction("sin","None","auto"),
AllpoleFilter("Input port","Lattice AR","Columns as channels",0),
AllpoleFilter("Dialog parameters","Direct form",[1 , -.95],"Columns as channels",0)
)
end
end
Настройка параметров LPC.
function setup(obj::LPCAnalysisAndSynthesisOfSpeech,In1)
Pre_Emphasis_set = EngeeDSP.setup(obj.obj_Pre_Emphasis,In1)
Overlap_Analysis_Windows_set = EngeeDSP.setup(obj.obj_Overlap_Analysis_Windows,Pre_Emphasis_set);
Window_set = EngeeDSP.setup(obj.obj_Window,Overlap_Analysis_Windows_set);
Autocorrelation_set = EngeeDSP.setup(obj.obj_Autocorrelation,Window_set);
Levinson_Durbin_set = EngeeDSP.setup(obj.obj_Levinson_Durbin,Autocorrelation_set);
Time_Varying_Analysis_Filter_set = EngeeDSP.setup(obj.obj_Time_Varying_Analysis_Filter,Pre_Emphasis_set,Levinson_Durbin_set[2]);
RC_To_InvSine_set = EngeeDSP.setup(obj.obj_RC_To_InvSine,Levinson_Durbin_set[2]);
bit_Quantizer_5_set = EngeeDSP.setup(obj.obj_5_bit_Quantizer,RC_To_InvSine_set);
bit_Quantizer_6_set = EngeeDSP.setup(obj.obj_6_bit_Quantizer,Time_Varying_Analysis_Filter_set);
Inv_Sine_to_RC_set = EngeeDSP.setup(obj.obj_Inv_Sine_to_RC,bit_Quantizer_5_set);
Time_Varying_Synthesis_Filter_set = EngeeDSP.setup(obj.obj_Time_Varying_Synthesis_Filter,bit_Quantizer_6_set,Inv_Sine_to_RC_set);
De_emphasis_Filter_set = EngeeDSP.setup(obj.obj_De_emphasis_Filter,Time_Varying_Synthesis_Filter_set);
end
setup (generic function with 1 method)
Объявление настроек для первого шага обработки.
function step1(obj::LPCAnalysisAndSynthesisOfSpeech,In1)
Pre_Emphasis_out = EngeeDSP.step(obj.obj_Pre_Emphasis,In1);
Overlap_Analysis_Windows_out = EngeeDSP.step(obj.obj_Overlap_Analysis_Windows,Pre_Emphasis_out);
Window_out = EngeeDSP.step(obj.obj_Window,Overlap_Analysis_Windows_out);
Autocorrelation_out = EngeeDSP.step(obj.obj_Autocorrelation,Window_out);
Levinson_Durbin_out = EngeeDSP.step(obj.obj_Levinson_Durbin,Autocorrelation_out);
Time_Varying_Analysis_Filter_out = EngeeDSP.step(obj.obj_Time_Varying_Analysis_Filter,Pre_Emphasis_out,Levinson_Durbin_out[2]);
Pad_out = EngeeDSP.step(obj.obj_Pad,Levinson_Durbin_out[1]);
FFT_out = EngeeDSP.step(obj.obj_FFT,Pad_out);
MathFunction1_out = EngeeDSP.step(obj.obj_MathFunction1,FFT_out);
RC_To_InvSine_out = EngeeDSP.step(obj.obj_RC_To_InvSine,Levinson_Durbin_out[2]);
bit_Quantizer_5_out = EngeeDSP.step(obj.obj_5_bit_Quantizer,RC_To_InvSine_out);
bit_Quantizer_6_out = EngeeDSP.step(obj.obj_6_bit_Quantizer,Time_Varying_Analysis_Filter_out);
Inv_Sine_to_RC_out = EngeeDSP.step(obj.obj_Inv_Sine_to_RC,bit_Quantizer_5_out);
Time_Varying_Synthesis_Filter_out = EngeeDSP.step(obj.obj_Time_Varying_Synthesis_Filter,bit_Quantizer_6_out,Inv_Sine_to_RC_out);
De_emphasis_Filter_out = EngeeDSP.step(obj.obj_De_emphasis_Filter,Time_Varying_Synthesis_Filter_out);
De_emphasis_Filter_out,MathFunction1_out;
end
step1 (generic function with 1 method)
Реализация алгоритма LPC
Вызов функции и обработка выхода эквалайзера.
obj = LPCAnalysisAndSynthesisOfSpeech()
setup(obj,In1[1]);
Out_a = zeros(size(vcat(In1...)))
Out_p = In1.*1im
size(In1,1)
for i = 0:size(In1,1) - 2
output_a = step1(obj,In1[i+1])
Out_a[sample*i + 1 : sample*(i + 1)] = output_a[1]
output_p = step1(obj,In1[i+1])
Out_p[i+1] = output_p[2]
end
Обработка и анализ результатов
Настройка плеера.
In2 = vcat(In1...);
function audioplayer(s, fs);
buf = IOBuffer();
wavwrite(s, buf; Fs=fs);
data = base64encode(unsafe_string(pointer(buf.data), buf.size));
markup = """<audio controls="controls" {autoplay}>
<source src="data:audio/wav;base64,$data" type="audio/wav" />
Your browser does not support the audio element.
</audio>"""
display("text/html", markup);
end
audioplayer (generic function with 1 method)
Воспроизведение оригинального аудио-файла
audioplayer(In2, 8000)
Воспроизведение шифрованного аудио-файла.
audioplayer(Out_a, 8000)
График визуального сравнения оригинального и шифрованного файлов.
plot(In2)
plot!(Out_a)
Вывод графика спектрального анализатора.
u1 = Out_p[1]; u2 = Out_p[2];
uSubset1 = u1[1:floor(Int,length(u1)/2+1)];
uSubset2 = u2[1:floor(Int,length(u2)/2+1)];
y1 = 6.02059991327962 .* log2.(abs.(uSubset1)+hypot.(eps.(real(uSubset1)),eps.(imag(uSubset1))));
y2 = 6.02059991327962 .* log2.(abs.(uSubset2)+hypot.(eps.(real(uSubset2)),eps.(imag(uSubset2))));
plot([1:129], y1[:], fillrange = -20, fillalpha = 0.35, c = 1, ylabel = "Mag^2", legend = false)
a = plot!([1:129],y1[:], msw = 0, ms = 2.5, xlabel = "Frequency")
plot([1:129], y2[:], fillrange = -20, fillalpha = 0.35, c = 1, ylabel = "Mag^2", legend = false)
b = plot!([1:129],y2[:], msw = 0, ms = 2.5, xlabel = "Frequency")
plot!(a,b)
Вывод
По итогам данной демонстрации мы разобрали методы взаимодействия с функциями из библиотеки EngeeDSP, а также продемонстрировали возможность создания интерактивных блоков внутри скриптов, данный пример наглядно демонстрирует работу метода LPC кодирования и позволяет нам оценить его эффективность. Это один из самых мощных методов анализа речи и один из самых полезных методов кодирования речи хорошего качества с низкой скоростью передачи данных, обеспечивающий высокоточные оценки параметров речи.