Перейти к содержанию
    

Cortex-M7 кол-во циклов на инструкцию

Можно ли наплевать на спектральные "прострелы" из-за вставления/убирания сэмпла при соотношении частоты сигнала 3.5 кГц и дискретизации 48 кГц?

Извиняюсь, прочитал невнимательно, а разговор был про линейную интерполяцию...

 

Если просто выкидывать, то оно щелкать будет. Вот файл - 10 секунд, 3.5кГц сигнал, 48кГц оцифровка, каждый 24000й сэмпл удален, что соответствует разнице частот 41ppm.

ASRCr.7z

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имхо - у SOF-фреймов от хоста тоже может быть джиттер. Так что аппаратным или не аппаратным таймером мерять - всё равно значения будут дёргаться - так как погрешность возникает не у Вас. Всё равно придётся усреднять или ФНЧ.

Да это понятно, но избавиться от дополнительного джиттера (связанного с вызовами прерываний) все же стоит. Переделал на таймер. Не очень удобно оно в STM32 сделано, ну да ладно. С ФНЧ с постоянной времени 0.2с получается теперь так:

post-39839-1493811788_thumb.png

В цифрах в среднем джиттер меньше где-то в 1.5..2раза и не зависит от того, что делает девайс - с таймером однозначно лучше.

 

Теперь осталось прикрутить часть со стороны DSP процессора и потом устроить "наведение порядка". Эх, зря я не предусмотрел подачу MCLK на SAI интерфейс от DSP процессора, придется костыли изобретать :rolleyes: ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Теперь осталось прикрутить часть со стороны DSP процессора и потом устроить "наведение порядка". Эх, зря я не предусмотрел подачу MCLK на SAI интерфейс от DSP процессора, придется костыли изобретать :rolleyes: ...

А что-ж Вы ресэмплинг не на DSP делаете? Имхо - он гораздо лучше для этого приспособлен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что-ж Вы ресэмплинг не на DSP делаете? Имхо - он гораздо лучше для этого приспособлен.

Приспособлен он пожалуй получше, но скормить ему клок от USB проблематично. К тому же тогда нужно обеспечить синхронную работу SAI и USB интерфейсов, плюс SAI интерфейс должен работать независимо от наличия USB подключения. Так, как сейчас выходит гибче, проще и удобнее. Несколько процентов от производительности STMа вполне можно потратить на ASRC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приспособлен он пожалуй получше, но скормить ему клок от USB проблематично.

А зачем? Сделать как у меня: отдавать поток сэмплов как есть, а в DSP делать ресэмплинг на коэфф. равный произведению постоянной и переменной части; переменную часть вычислять от уровня заполненности буфера принимаемых DSP сэмплов; постоянная Вам известна.

Тогда и мерить/усреднять ничего не надо - это всё будет делать кольцевой буфер принимаемых сэмплов в DSP.

Хотя конечно этот буфер будет вносить некоторую задержку в сигнал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

отдавать поток сэмплов как есть,

А как отдать его через SAI интерфейс "как есть"? Я ведь его могу затактировать или со стороны DSP, или со стороны управляющего STM32. Оба клока асинхронные относительно клока USB. Придется сделать на STM32 что-то типа FLL, чтобы загнать частоту SAI (в этом случае он будет мастером) в допустимые пределы... В принципе можно и так, боюсь только джиттер у такого решение вылезет большой, скорее всего бОльший, чем если сразу сделать ASRC на STM32 ориентируясь на соотношение частот SAI/USB.

 

а в DSP делать ресэмплинг на коэфф. равный произведению постоянной и переменной части; переменную часть вычислять от уровня заполненности буфера принимаемых DSP сэмплов; постоянная Вам известна. Тогда и мерить/усреднять ничего не надо - это всё будет делать кольцевой буфер принимаемых сэмплов в DSP.

Через отслеживание буфера боюсь нужное качество не получу, или буфер сильно большой придется делать (сейчас дополнительная задержка не превышает 1..2 мс - это 12..24сэмплов).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как отдать его через SAI интерфейс "как есть"? Я ведь его могу затактировать или со стороны DSP, или со стороны управляющего STM32. Оба клока асинхронные относительно клока USB.

Ну и пускай. Скорость SAI сделать такой, чтобы точно хватало для передачи потока при любом соотношении частот с небольшим запасом по скорости.

Да, конечно, уровень загрузки кольцевого буфера в DSP будет не стоять, а болтаться у некоего значения - ничего страшного.

 

Через отслеживание буфера боюсь нужное качество не получу, или буфер сильно большой придется делать (сейчас дополнительная задержка не превышает 1..2 мс - это 12..24сэмплов).

Необходимый размер буфера будет зависеть от размера регулярных "биений" скорости потока сэмплов - надо, чтобы он был заведомо больше этих биений.

У меня весь буфер разбит на 3 участка: A, B, C. Размерности участков например такие: A - от 0% до 20% заполненности; B - 20%...80%; C - 80%...100% заполненности (конкретные значения могут быть другие).

Участок B - горизонтальный: при нахождении уровня заполненности в нём, переменная часть коэфф. ресэмплинга == 1.

Участок A - линейно-наклонный: переменная часть коэфф. ресэмплинга изменяется по линейному закону от 1 до 1-D/100 при смещении указателя заполненности от 20% до 0%.

Участок C - линейно-наклонный: переменная часть коэфф. ресэмплинга изменяется по линейному закону от 1 до 1+D/100 при смещении указателя заполненности от 80% до 100%.

где D - максимальное значение (в %) переменной части коэфф. ресэмплинга (может быть любое значение, например 10%).

Размер участка B выбирается таким, чтобы он полностью поглощал регулярные биения загрузки буфера.

 

Это работает так:

При старте вначале идёт пребуферизация (сэмплы только накапливаются в буфер, без выходного потока) до некоторого значения на участке B. Потом включается обычный рабочий режим ресэмплинга. В реале, если частоты генераторов источника и ЦАП идеально совпадают, то уровень заполненности устаканится на некотором значении - будет регулярно болтаться вокруг этого значения на суммарную величину всех джиттеров. Если частоты генераторов различаются в ту или иную сторону, то этот уровень загрузки будет постепенно смещаться в сторону участка A или C (тоже с биениями) и в конце-концов - залезет в A или C, где и устаканится на некотором значении (будет болтаться возле него), до тех пор, пока разница частот не изменится (например из-за влияния температур на генераторы) и тогда может поползти в обратную сторону.

Вот примерно так это у меня и работает. Как плюс метода - он не требует никаких дополнительных измерений и устойчив к довольно большому и неравномерному джиттеру (у меня поток сэмплов приходит с TCP-сокета работающего поверх WiFi - поток болтается очень даже произвольно).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это работает так:

Да, у Вас получается вариант регулирования с обратной связью, у меня вариант прямого регулирования.

 

Если частоты генераторов различаются в ту или иную сторону, то этот уровень загрузки будет постепенно смещаться в сторону участка A или C (тоже с биениями) и в конце-концов - залезет в A или C, где и устаканится на некотором значении (будет болтаться возле него), до тех пор, пока разница частот не изменится (например из-за влияния температур на генераторы) и тогда может поползти в обратную сторону.

Т.е. реализован обычный пропорциональный регулятор с ОС и зоной нечувствительности. А почему интегратор не добавили? Логично добавить интегратор, чтобы система стала астатической. Тогда после коррекции буфер возвратится на участок В (может правда интегрирование есть, но я не понял этого из описания).

 

С одной стороны, при высокой долговременной стабильности генераторов зона нечувствительности это плюс, но как только мы начинаем "плыть", она становится минусом, т.к. без нее корректировка начнется раньше и будет проходить "плавнее" = с меньшей модуляцией основного сигнала, а с таким алгоритмом чем быстрее уплывает частота, тем агрессивнее коррекция, что при высокой скорости уплывания опять становится плюсом :). Интересно посмотреть, как это выглядит при объективном контроле - Вы случайно не делали замеров типа спектров, как я выше выкладывал?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему интегратор не добавили? Логично добавить интегратор, чтобы система стала астатической. Тогда после коррекции буфер возвратится на участок В (может правда интегрирование есть, но я не понял этого из описания).

А зачем интегратор? Участки A и C сами по себе являются интеграторами, точнее - их длина. Если нужна большая "интегрируемость", то увеличиваем размер этих участков (они становятся более пологими) и всё.

И нет - указатель буфера не должен возвращаться на участок B, если между генераторами есть постоянная разница частот (в несколько ppm например из-за их погрешности). Он должен находиться на участке A или C, на некотором удалении от его границы с B. Величина этого удаления как раз и определяется разностью частот. Если разность частот постоянна - он как раз и будет стабильно находиться в той точке, внося свой дополнительный вклад в произведение коэффициентов ресэмплинга. Ну т.е. в реале из-за джиттера он конечно не находится всё время в одной точке, а колеблется около неё. Нужен больший интервал интегрирования - просто увеличиваем размеры участков A и C, делаем их более пологими, можно вообще размер участка B свести к 0 даже.

Можно обойтись вообще без участка B, но у меня характер потока такой, что при старте онлайн-радиостанции выплёвывают сразу бОльший объём траффика чем соответствует битрейту. Т.е. - воспроизведение стартует как бы из прошлого на несколько секунд. Радиостанция таким образом как я понимаю обеспечивает пребуферизацию, чтобы не было провалов воспроизведения. Но размер этой пребуферизации у каждой радиостанции свой и заранее не известен. Поэтому, чтобы у меня сразу при старте воспроизведения, не уходил поток в зону ресэмплинга, я и ввёл участок B. Его размер я выбрал экспериментально - пробовал с разными радиостанциями и постарался чтобы все они при старте своей пребуферизацией не вылезали за пределы участка B.

 

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

Эта зона у меня выбрана такой большой именно из-за необходимости пропустить пребуферизацию онлайн-радиостанций.

И скоростью потока данных от радиостанции я не могу управлять (WiFi-модуль не предоставляет средств управления потоком, типа окна в TCP-сокете).

 

Интересно посмотреть, как это выглядит при объективном контроле - Вы случайно не делали замеров типа спектров, как я выше выкладывал?

Нет. Да мне не особо интересно какой там спектр. На слух в сигнале не ощущается каких-то искажений - и ладно, так как только это и нужно. :)

Вот когда в потоке идут большие провалы (бывает некоторые радиостанции изредка приостанавливают поток на неск. секунд, а может и не радиостанции, а что-нить по WiFi), то указатель буфера смещается на участок A и это слышно сразу искажением звуковых частот и замедлением. А потом, когда эта пробка прочищается - наоборот - происходит выброс большого объёма данных и может улететь на участок C (но не всегда как раз из-за размера участка B).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем интегратор?

Если посмотреть на проблему "под другим углом", а именно установить конечную цель/критерий работы алгоритма определения соотношения частот поддержание оптимального заполнения буфера (50%), то без интегратора получится статическая САУ. Т.е. заполненность буфера будет определяться соотношением частот источника/приемника. При наличии интегратора САУ приобретет астатизм первого порядка, т.е. ошибка при наличии статичного расхождения частот будет равна 0.

 

Я вчера поэкспериментировал с этим алгоритмом - работает и как у Вас, и с интегратором. Есть некоторые нюансы, как у любой замкнутой САУ, но то такое.

 

Насчет джиттера - в конечном итоге, как ни крути, хоть с прямым управлением, хоть с ОС все определяет фильтр, которым усредняется коэффициент ресемплинга (что неудивительно - ведь фактически через этот коэффициент осуществляется ЧМ) :) Но с прямым замером можно обойтись менее агрессивной фильтрацией, ускорить реакцию системы и уменьшить размер буфера/задержу при одинаковом джиттере, т.к. точность и разрешающая способность единичного замера намного выше. Кроме того данные синхронизации доступны при отключенном аудиоустройстве. Для моего применения все это весьма существенно.

 

Сейчас сделал с замером периодов USB SOF и SAI FS двумя таймерами, потом деление и ФНЧ первого порядка => коэффициент ресэмплинга. Заполняемость буфера "гуляет" от 77 до 81 сэмплов. Учитывая обработку блоками по 4 сэмпла можно сказать, что буфер стоит на месте (как и должно быть) :) - можно его раза в четыре меньше сделать. Немного напрягают меня палки на спектре (в сравнении с матлабовской моделью), скорее всего это ошибки округления, ну или я где-то налажал в фильтре :laughing: - надо будет поразбираться. А так, вот пример уже вместе с ДСП, с синхронизацией от его клока:

post-39839-1493906425_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вот, палки поборол тоже :) Как и предполагал причина была в точности вычислений в формате float. После небольшой коррекции работает так:

post-39839-1493977593_thumb.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...