Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: [MatLab] Модель полосного вокодера (channel vocoder)
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
Оксюморон
Добрый день! Понемногу делаю модель простейшего полосного вокодера. Собственно, идея заключается в:
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 Задачи производительности кода сейчас не рассматриваю и поэтому в коде много вещей, которые можно было бы сократить, но они оставлены для наглядности процесса =)
fontp
QUOTE (Оксюморон @ Sep 27 2010, 12:00) *
Добрый день! Понемногу делаю модель простейшего полосного вокодера. Собственно, идея заключается в:
1. Сигнал нарезается по 20 мс не перекрывающихся сегменты;
2. Для каждого сегмента проводим БПФ (кол-во точек определяет точность);
3. Спектр каждого сегмента "нарезается" на заданное кол-во полос;
4. Огибающая усредняется и готова к передаче;

Восстановление:
1. "Собираем" спектр сегмента назад;
2. Проводим обратное БПФ;
3. "Склеиваем" сегменты назад во временной области;

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

Столкнулся со следующими проблемами:
При увеличении кол-ва полос спектр относительно исходного "размывается", полагаю, что это может быть связано с тем, что при восстановлении мы в конце концов получаем ступенчатую функцию, состоящую из 20 мс отрезков.
Становится что-то слышно только на 64 каналах, хотя и на 16 уже должно быть возможным разобрать хотя бы отдельные слова.
Куда копать? Кодер простейший, но реализаций похожих не видел к сожалению.
PS Задачи производительности кода сейчас не рассматриваю и поэтому в коде много вещей, которые можно было бы сократить, но они оставлены для наглядности процесса =)


Думаю БПФ полосы сильно перекрываются, что не есть хорошо. Если подобрать банк полосовых фильтров с малым перекрытием такая схема работает -
я про такие не только читал, но даже и слушал как работает... Там в соответствии со свойствами слуха ещё и полосы берут расширяющимися пропорционально частоте
Оксюморон
Цитата(fontp @ Sep 27 2010, 15:06) *
Думаю БПФ полосы сильно перекрываются, что не есть хорошо. Если подобрать банк полосовых фильтров с малым перекрытием такая схема работает -
я про такие не только читал, но даже и слушал как работает... Там в соответствии со свойствами слуха ещё и полосы берут расширяющимися пропорционально частоте


Так в том-то и дело, что БПФ перебирается без перекрытия, или я что-то не догоняю в БПФ?
fontp
QUOTE (Оксюморон @ Sep 27 2010, 16:12) *
Так в том-то и дело, что БПФ перебирается без перекрытия, или я что-то не догоняю в БПФ?


Казалось бы. В дискретном представлении. Но каждый бин ДПФ собирает сигнал из некоторой взвешеной области. А физически отсутствие спектральных окон означает окно синком по форме - с большими хвостами и перекрытием по всем полосам. Можно окна подогнать какие-то типа Кайзера, с малыми боковиками
Но и центральные частоты полос нужно размещать типа логарифмически, а не равномерно как даёт ДПФ. Хорошо спроектированый банк фильтров решает обе проблемы. Спектр мощности передать, да, ухо фазу не слышит практически
Оксюморон
Цитата(fontp @ Sep 27 2010, 16:55) *
Казалось бы. В дискретном представлении. Но каждый бин ДПФ собирает сигнал из некоторой взвешеной области. А физически отсутствие спектральных окон означает окно синком по форме - с большими хвостами и перекрытием по всем полосам. Можно окна подогнать какие-то типа Кайзера, с малыми боковиками
Но и центральные частоты полос нужно размещать типа логарифмически, а не равномерно как даёт ДПФ. Хорошо спроектированый банк фильтров решает обе проблемы. Спектр мощности передать, да, ухо фазу не слышит практически


Я правильно понимаю, что при использовании окон необходимо выбирать временное представление сигнала сегментами, перекрывающими друг друга в зависимости от выбранного типа окна?

Пока плотно не изучил, но рис. 4 вот отсюда http://www.ee.iitm.ac.in/~nitin/_media/ee462/fftwindows.pdf насколько я понял и демонстрирует, сказанное вами?
fontp
QUOTE (Оксюморон @ Sep 28 2010, 11:06) *
Я правильно понимаю, что при использовании окон необходимо выбирать временное представление сигнала сегментами, перекрывающими друг друга в зависимости от выбранного типа окна?
Пока плотно не изучил, но рис. 4 вот отсюда http://www.ee.iitm.ac.in/~nitin/_media/ee462/fftwindows.pdf насколько я понял и демонстрирует, сказанное вами?


Демонстрирует спектральные окна.
Насчёт перекрытия я не уверен, что это нужно. Это зависит от размера фрейма. Перектрытие было бы необходимо, если пытаться восстановить сам сигнал, но для передачи звука это не нужно - достаточно смоделировать мгновенный спектр мощности и потом его воспроизвести.
Если не принимать во внимание тонкие моменты связанные в первую очередь с ограниченностью динамического диапазона, ухо не слышит фазу спектральных компонентов сигнала. Т.е. ухо можно считать - это банк фильтров + оценка энергии на выходе
Известно даже с какой предельной точностью, для передачи музыки нужно - 4 октавы по 12 полос (нот), расположенных по показательной функции - 2^(n/12). Более тонко люди не слышат. Для речи меньше. Понятно, что равномерное распределение полосовых фильтров, которое порождается Фурье не совсем адекватно, поэтому лучше использовать банк фильтров
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.