Плата Arduino DUE хоть внешне и весьма похожа на Arduino Mega – но это только с первого взгляда. Совместимости между ними нет даже по электрическим уровням. Плата DUE имеет трехвольтовые сигнальные линии, и посему с ней несовместимы подавляющее число щитов от обычной ардуины. Этот факт серьезно ставит под угрозу «жизнь и здоровье» контроллера архитектуры ARM3E… кстати, далеко не дешевого и весьма продвинутого. К обычной Ардуине (с архитектурой AVR) – Arduino DUE не имеет практически никакого отношения, и различий между ними намного больше, чем сходства (среда и язык разработки, да форм-фактор платы). Посему выходит что под DUE не так-то и просто «забабахать» что-то полезное - весь парк щитов и периферии от обычной ардуины идет лесом … а на вскидку для чего еще можно применить весьма не деццкие (в смысле нечита классическим ардуинам) вычислительные мощности? Одним из таких проектов стал

pedalSHIELD.

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

Да, плата DUE (а вернее контроллер) имеет на борту не только 12-ти разрядные АЦП (ADC), но я 12-ти разрядные ЦАП (DAC) – что вкупе с достаточно шустрым ядром позволяет в режиме реального времени обрабатывать цифровой звук и реализовать «педаль эффектов» для электрогитары. Щит, собственно, добавляет необходимую обвязку в виде операционников (дифференциальных усилителей) на входе и выходе, коннекторы и органы управления в виде тумблеров и переменных резисторов. …

Самым распространенным эффектом является «дисторшен» (или «перегруз») …

Реализация дисторшена …

… приведенная в примере реализация с сайта разработчика щита содержит лишь канву идеи математического описания эффекта. Сам же пример неработоспособен в принципе! – скомпилировав и запустив его вы не услышите ничего похожего на дисторшен, будет просто эффект сквозного прохождения сигнала. Впрочем самые внимательные возможно и услышат, что в очень узком диапазоне регулятора глубины эффекта, некое еле-слышное подобие дисторшена, после чего звук вовсе пропадает… Именно этот момент и должен явится подсказкой к причине такого результата … и соответственно помочь решить задачу реализации дисторшена (математического) на данной "педале" наиболее оптимально.

С чем мы работает в коде? Со входа к нам поступает оцифрованный сигнал на ADC0 в виде числа в диапазоне от 0 до 4095 (12 бит), с ADC1 мы получаем также инверсный сигнал (его весовой эквивалент) – опрос АЦП'шек происходит в цикле с максимально возможной цикличностью. Здесь же мы должны обсчитать (модифицировать) прочитанный сигнал и направить его на выход в DAC0 И DAC1. По ходу дела можно еще опрашивать состояние тумблеров и резисторов, да мигать единственным светодиодом. Если честно, то органов управления и визуализации имхо маловато, но приходиться крутиться с тем что есть.

Так все же, какую модель данных (входного сигнала) мы обрабатываем и как? - почему не работает базовый пример дисторшена?

Как уже говорилось выше: в бесконечном цикле мы периодически опрашиваем входные АЦП и формально каждый раз на входе получаем значение от 0 до 4095 (12 бит) эквивалентное уровню напряжения на входе из диапазона допустимых напряжений для АЦП. Соответственно в этом же цикле мы должны записать некоторое значение в выходные ЦАП, имеющие такую же разрядность. Входной сигнал представляет из себя кривую («синусоиду», а вернее периодическую функцию) выраженную в нашем случае последовательностью точек, аппроксимация которых имеет схожею форму с самим сигналом. Максимальная амплитуда входного сигнала в цифровом эквиваленте вовсе не будет «размазана» по всему диапазону АЦП от 0 до 4095 – хотя в некоторой степени ее (степень усиления входного операционника) можно регулировать установленным на плате переменным резистором (сбоку, максимум усиления – по часовой стрелке). В реале сигнал идущий напрямую с электрогитары (без предусилителя) на pedalSHIELD весьма не велик по амплитуде – и снимаемый с АЦП числовой поток будет находиться, например, в диапазоне от 1400 до 2600 (из возможных от 0 до 4095). Соответственно устанавливать линии ограничения (среза дисторшена) выше 2600 и ниже 1400 бессмысленно – т.к. сигнал попросту не доходит до таких значений, и на выходе будет ровно тот же сигнал, что и на входе – совсем без изменений. Эту ситуацию мы и наблюдаем в базовом примере – фактически нерабочем и без права на жизнь в таком виде. Да, если честно, то можно умудриться «поймать» и слегка услышать эффект дисторшена на базовом примере в почти крайнем положении регулятора глубины эффекта (при максимальном уровне регулятора громкости) когда линии среза еще не сошлись в плотную на значении 2047, но уже «зацепили» сигнал. Но оценить, продемонстрировать, а тем-более пользоваться таким эффектом ну никак нельзя! Кстати, такое тупое отрезание верхушек «синусоиды», выходящих за определенные значения линии среза не столько создает эффект дисторшена, сколько банально снижает громкость! Но забудем про рукожопых горе-кодеров, писавших базовый пример дисторшена, и напишем его корректно с точки зрения логики и математики.

Что для этого нам нужно …

  1. Оценить максимальную амплитуду входного сигнала и осуществлять позиционирование линий среза относительно неё, а не по всему диапазону возможных входных значений АЦП. Для этого у нас, как нельзя кстати, входной сигнал представлен не только прямым, но и инверсным значением «синусоиды» (относительно виртуального нуля): ADC0 - прямой, ADC1 - инверсный. Именно благодаря инверсному значению мы можем четко определить не только верхний и нижний максимум сигнала одномоментно, но и посчитать уровень виртуального нуля (который оказывается в районе 2000 и слегка плавает из-за входного шума). Благодаря такому позиционированию регулятор глубины эффекта у нас будет работоспособен «от упора до упора»: от почти отсутствующего эффекта дисторшена – до полного зарезания «синусоиды» (что эквивалентно тишине на выходе). Разумеется, эти границы можно скорректировать, что бы избежать крайних значений не имеющих непосредственного отношения к самому эффекту.
  2. Далее собственно осуществляем сравнение текущего (считанного в настоящий момент) уровня сигнала с уровнем среза и режем его, если он превосходит один из уровней: верхний или нижний (присваиваем константу, соответствующую заданному уровню).
  3. Полезным будет также отсечь фоновый шум при отсутствии полезного входного звука. Шум в цифровом виде выглядит как хаотичный разброс входных значений в небольших пределах относительно виртуального нуля – соответственно анализируем и приводим к виртуальному нулю все значения отличающиеся от него незначительно (регулируется экспериментально).
  4. Ну и напоследок масштабируем получившийся выходной сигнал по всему диапазону ЦАП (от 0 до 4095) – ведь у нас цель: дисторшен (эффект перегруза усилителя), поэтому при масштабировании за 100% мы берем не максимальные уровни входного сигнала (полученные в п.1), а уровни среза сигнала. Благодаря этому вне зависимости от амплитуды (максимального разброса входных значений) – на выходе мы будем иметь одинаковый по амплитуде сигнал, срезанный пропорционально положению регулятора глубины эффекта.
  5. Ну и напоследок общий выходной регулятор громкости, - хотя имхо он излишен …
  6. Запись обработанного сигнала с ADC0 производится в DAC0. А в вот в DAC1 можно записывать как обработанный инверсный сигнал с ADC1 – так и просто константу 0. Субъективно разницы не ощущается.

В итоге мы получили, возможно не ах-прям-какой, но весьма рабочий, узнаваемый и в принципе юзабельный дисторшен! Можно сказать даже, что с точки зрения математики он идеален. Однако с точки зрения музыкального восприятия эффекта можно и далее вносить в форму выходного сигнала еще разные модификации, которые впрочем, к эффекту дисторшена непосредственного значения иметь не будут.

Пример описанного алгоритма прилагается (вариант через прерывание)…

MiGeRA (октябрь 2015)

Заглавная » Радиоэлектроника » Arduino - Высокоуровневая платформа устройств на микроконтроллерах » pedalSHIELD - Реализация дисторшена