olegas 0 26 сентября, 2016 Опубликовано 26 сентября, 2016 · Жалоба Всем доброго времени суток! Для реализации распознавания отдельных слов потребовалось вычисление дискретного преобразования Фурье. Быстрое преобразование применить нельзя, поскольку число отсчётов не является степенью двойки (в противном случае ухудшаются результаты работы основного алгоритма). Восстановление сигнала после преобразования не требуется, всё, что нужно от ДПФ - амплитуда и частота. Сейчас вычисляю ДПФ формулами по определению (формулы ниже, плюс ещё вычисление амплитуды). При обработке одного слова требуется выполнить 30 преобразований Фурье. Число отсчётов лежит в пределах 200 - 500 (конкретное значение заранее неизвестно), но одинаковое для всех тридцати преобразований. В результате при реализации такого алгоритма на stm32f417 при частоте 168 МГц и арифметике с 32-битными float эти 30 преобразований (анализ одного произнесённого слова) вычисляются четыре-пять секунд, что составляет большую часть времени всех вычислений (80%). Для вычисления коэффициентов ДПФ и квадратных корней использую функции DSP-ядра этого микроконтроллера (синус, косинус, квадратный корень). И большую часть времени (68%) занимает как раз вычисление этих самых коэффициентов. Как ещё можно ускорить вычисление ДПФ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 26 сентября, 2016 Опубликовано 26 сентября, 2016 · Жалоба Например, увеличить в 4 раза частоту выборок, и делать БПФ по 2048 точкам. И ничего не потеряете, а наоборот, я думаю, приобретете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andyp 9 26 сентября, 2016 Опубликовано 26 сентября, 2016 · Жалоба В результате при реализации такого алгоритма на stm32f417 при частоте 168 МГц и арифметике с 32-битными float эти 30 преобразований (анализ одного произнесённого слова) вычисляются четыре-пять секунд, что составляет большую часть времени всех вычислений (80%). Для вычисления коэффициентов ДПФ и квадратных корней использую функции DSP-ядра этого микроконтроллера (синус, косинус, квадратный корень). И большую часть времени (68%) занимает как раз вычисление этих самых коэффициентов. Как ещё можно ускорить вычисление ДПФ? Для вычисления sin и cos можно использовать тот же подход, что используется в DDFS - небольшая таблица для фаз (pi/2/N, N - размер таблицы) + линейная аппроксимация между отсчетами из таблицы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 26 сентября, 2016 Опубликовано 26 сентября, 2016 · Жалоба FFT требует ~100 тактов на отсчёт, соответственно не жалко потратить ещё десяток тактов на отсчёт и сделать resampling, чтобы точек было всегда 512, ну или хотя бы просто нулями буфер дозабить по длине до 512 точек. соответственно для 30 FFT * 512 точек * 100 тактов надо 1.5-2МГц, или 10мс при 168МГц. если же надо именно ДПФ только для определённых частот, а для не всего спектра, можно Герцелем посчитать, почти без вычисления тригонометрии (там надо только один раз косинус посчитать для каждой частоты, а не для каждого отсчёта). будет несколько тысяч тактов на отсчёт, но если надо только несколько частот, а не весь спектр, может быть быстрее чем через FFT float SpecPowerGoertzel(float * y, int num, float dt, float w){ const float K = 2.0 * cos(w * dt / num); float s1 = 0, s2 = 0; for (int i = 0; i < num; i++){ float s0 = y[i] + K * s1 - s2; s2 = s1; s1 = s0; } return (s2*s2 + s1*s1 - K * s1 * s2) / ((float)num * num); } только корень еще навеное взять надо и почему оно на длину выборки делилось, причём дважды, уже не вспомню. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olegas 0 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба Дело в том, что для распознавания необходим весь спектр, поэтому алгоритм Гёрцеля не подходит. По поводу изменения частоты дискретизации. Для сравнения результатов в MATLAB построено два спектра: – первый (чёрный) – исходный вариант, ДПФ на 348 точки; – второй (красный) – после передискретизации, БПФ на 512 точек. Графики построены в координатах частота – амплитуда. Вот из-за такой разницы алгоритм распознавания ухудшается (значительно увеличивается расстояние даже между одинаковыми словами (примерно в три раза)). Если возможно, применялось бы БПФ. Вот пример кода из MATLAB: y = audioread('1.wav'); N = length(y); T = 30; %Число кадров K = ceil(2*N/(T+1)); %Число отсчётов в кадре Fs = 8000; %Частота дискретизации %Желаемые параметры сигнала Kwant = 512; Nwant = Kwant/2 * (T+1); %Длина всего сигнала, чтобы число отсчётов в кадре было 512 Fswant= Nwant/N * Fs; %Интерполируем Y = interp1(1:N, y, 1:N/Nwant:N, 'linear'); frame1 = y(1:K); fft_frame1 = abs(fft(frame1)); frame1Y = Y(1:Kwant); fft_frame1Y = abs(fft(frame1Y)); fky = 1:Fs/K:Fs; fkY = 1:Fswant/Kwant:Fswant; fft_frame1y = zeros(size(frame1Y)); fft_frame1y(1:K) = fft_frame1; plot(fkY, fft_frame1Y,'r', fkY,fft_frame1y,'k'); xlabel 'частота, Гц' Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр77 1 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба Глядя на первый график (на котором представлены спектры для 348 и 512 Гц) создается ощущение, что частоты соотносятся друг с другом с отношением 348/512. Если это так, то делая БПФ Вам просто необходимо умножать каждый бин на эту константу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба интерполировать надо нормально. от линейной интерполяции спектр портится особенно на высоких частотах. разницы между графиками не заметил, ну кроме того что на 512/348 домножить забыли. Герцель это и есть ДПФ только без вычисления тригонометрии, соответственно вычисляется заметно быстрее простого ДПФ с синусами/косинусами, даже если посчитать его для всех частот. но FFT всё равно быстрее. если в формулу ДПФ из первого поста добавить еще K точек S = 0, так, чтобы N+K стало 512, результат от этого поменяется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olegas 0 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба То, что частоты сдвинуты - не страшно. Гораздо хуже, что амплитуды для двух вариантов для частот 0..4000 Гц не совпадают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба Так вы не интерполируйте свой файл, тем более, линейно. Считайте, что он взят с другой частотой, и ищите, соответственно другие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба этот файл "1.wav" сюда прикрепите Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр77 1 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба То, что частоты сдвинуты - не страшно. Гораздо хуже, что амплитуды для двух вариантов для частот 0..4000 Гц не совпадают. Взял примерные значения пиков в районе 1 кГц, 11,5 и 16,8. Их отношение 512(Гц)*11,5/16,8~=350(Гц). Думаю у Вас более точные значения амплитуд еще больше совпадут с отношением частот дискретизации. Учитывая имеющийся доступ к оригиналу - можете для всех точек пересчитать. Еще лучше - возьмите максимальные значения в каждой реализации и относительно него пронормируйте полученные данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 35 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба Когда то для ускорения использовали только uint16 - примерно 1-2 mS на lsi-11 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 27 сентября, 2016 Опубликовано 27 сентября, 2016 · Жалоба Когда то для ускорения использовали только uint16 - примерно 1-2 mS на lsi-11 на M4 не особо поможет, у него FPU есть, для быстрого преобразования Фурье разница в тактах между 16ти разрядным целым и 32х разрядным float меньше 20%. а целочисленное 32х разрядое так еще и в полтора раза медленне чем float. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
olegas 0 27 сентября, 2016 Опубликовано 27 сентября, 2016 (изменено) · Жалоба Еще лучше - возьмите максимальные значения в каждой реализации и относительно него пронормируйте полученные данные. Это хорошая идея, если коэффициент нормировки будет константой для всех вариантов. Ну или хотя бы зависеть только от исходного числа отсчётов (которое не есть степень двойки) и желаемого (степень двойки, например 512). И вот подопытный файл для всех желающих. 1.wav Изменено 27 сентября, 2016 пользователем Olegas Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 28 сентября, 2016 Опубликовано 28 сентября, 2016 · Жалоба Для вычисления коэффициентов ДПФ и квадратных корней использую функции DSP-ядра этого микроконтроллера (синус, косинус, квадратный корень). И большую часть времени (68%) занимает как раз вычисление этих самых коэффициентов. Как ещё можно ускорить вычисление ДПФ? Ну так, заранее вычислите эти коэффициенты и разместите их в таблице. У меня на 100 МГц ДСП двойной МАК для преобразования Фурье вычисляется за 10 нс. Т.о., для 200-500 точек время счёта Re/Im одной палки составит порядка 2-5 мкс. Для 30 частот время счета составит 60-150 мкс. Но это прикид для 100 МГц тактовой, а у вас 168 МГц тактовая, так что о каких секундах может идти речь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться