Добрый день! Понемногу делаю модель простейшего полосного вокодера. Собственно, идея заключается в:
1. Сигнал нарезается по 20 мс не перекрывающихся сегменты;
2. Для каждого сегмента проводим БПФ (кол-во точек определяет точность);
3. Спектр каждого сегмента "нарезается" на заданное кол-во полос;
4. Огибающая усредняется и готова к передаче;
Восстановление:
1. "Собираем" спектр сегмента назад;
2. Проводим обратное БПФ;
3. "Склеиваем" сегменты назад во временной области;
Код матлабовской функции:
Код
function [ y ] = channel( x, seg_length, F_orig, N_chan, N_points )
%CODEC полосный кодер
% x - массив входящих отсчетов
% seg_length - длина сегмента для обработки [с]
% F_orig - частота отсчетов оригинального сигнала
% N_chan - количество подполос
% N_points - кол-во точек преобразования
% Определяем длину оригинального сигнала
overall_length = length(x);
% Определяем кол-во отсчетов в сегменте обработки
seg_samples = F_orig*seg_length;
% Приводим кол-во отсчетов оригинального сигнала к кратному длине сегмента
x(overall_length+1:ceil(overall_length/seg_samples)*seg_samples) = 0;
i = 0;
% Индексы подполос
bands = 1:round(N_points/N_chan):N_points;
bands(end) = N_points;
% Задаем длину обработанного сигнала и заполняем его нулями
y = zeros(size(x));
% Перебираем сегменты
while i*seg_samples < overall_length
% Проводим БПФ текущего сегмента
index = 1+i*seg_samples:seg_samples*i+seg_samples;
spectrum = real(fft( x(index), N_points*2 ));
% Для каждой подполосы
for j = 1:N_chan-1
% Текущие индексы подполосы
band_cur = [bands(j):bands(j+1)-1];
% Получем усредненную энергию подполосы
band_avg = mean(spectrum(band_cur));
% Собираем спектр назад здесь же
ench_spectrum(j) = band_avg;
end
ench_sample = real(ifft(ench_spectrum, seg_samples, 'symmetric'));
y(index) = ench_sample;
% Переходим к следующему сегменту
i = i+1;
end
y = y/max(abs(y))*0.8;
end
Моменты, связанные с непосредственной передачей опущены, т.к. задача это исследование субъективного качества голоса при кодировании.
Столкнулся со следующими проблемами:
При увеличении кол-ва полос спектр относительно исходного "размывается", полагаю, что это может быть связано с тем, что при восстановлении мы в конце концов получаем ступенчатую функцию, состоящую из 20 мс отрезков.
Становится что-то слышно только на 64 каналах, хотя и на 16 уже должно быть возможным разобрать хотя бы отдельные слова.
Куда копать? Кодер простейший, но реализаций похожих не видел к сожалению.
PS Задачи производительности кода сейчас не рассматриваю и поэтому в коде много вещей, которые можно было бы сократить, но они оставлены для наглядности процесса =)