[recovery mode] Spin FV-1. Железный ревербератор своими руками. Часть 1, вводная
Статья пригодится для тех, кто хочет сам разработать и собрать педаль пространственных эффектов для гитары/синтезатора и, заодно сделать первые шаги в области цифровой обработки звука.
Spin FV-1 — микросхема «все в одном» (АЦП, сигнальный процессор, ЦАП, память) для выполнения алгоритмических операций над звуком в цифровом виде.
Чип у многих на слуху, и не смотря на то, что появился на свет в 2006 (2003) году, оказывается все еще популярен. На нем выпускается наверное под сотню гитарных педалей и не менее десятка синтезаторных модулей.
Конкурентов до сих пор особо нет, потому что где мощное процессорное ядро там шум, отпадает качественный АЦП. Где есть хороший АЦП — все плохо с памятью и ядром, и так далее.
Специальных знаний не потребуется, чип довольно простой, +уже имеет 8 встроенных программ, поэтому можно собрать девайс и он уже будет звучать. А потом уже писать свои программы-патчи-алгоритмы.
Статьи планируются как художественное «переложение» документации FV-1 и примеров программ на язык школьной алгебры + бейсика.
Также, будут показаны некоторые характерные приемы программирования и сниппеты. Тем самым, будет сэкономлено довольно много времени, меньше придется вычитывать официальный форум и, все доступные сайты и исходники. Официальная документация — хорошая, но её маловато и в ней много вещей, которые неплохо бы подразжевать, либо перегруппировать.
DSP мышление довольно непривычное по сравнению с другими областями программирования, материал должен немного помочь привыкнуть мыслить «поточно».
Первая часть будет скорее стартово-обзорной, дальше, будет увеличиваться детализация.
Начинать стоит с вычитки официального сайта: http://www.spinsemi.com/, потом уже смотреть данный материал.
Микросхема содержит 24 бит стерео аудио АЦП и ЦАП, DSP ядро, аналоговый вход на 3 канала — АЦП «постоянного тока» (Aux ADC), для изменения параметров звука ручкой потенциометра и индикатор клиппинга.
Также, на борту есть ПЗУ с предварительно зашитыми заводскими программами. Пользовательские программы подгружаются с внешнего i2c ПЗУ.
Все это упаковано в корпус soic 28, который по теперешним меркам очень даже user friendly.
Частота дискретизации и тактирование в целом обычно задается часовым кварцем, что компактно и дешево, либо внешним генератором и обычно равняется 32768 сэмплам в секунду.
Максимальная стабильная частота дискретизации от внешнего источника тактирования — 48000 сэмплов в секунду (пруф: http://www.spinsemi.com/forum/viewtopic.php? t=217).
Для референса, дискретизация компакт-диска 44100@16 бит, процессора Zoom 505 — 708 — 31250@16 бит.
У многих девайсов (приборов обработки звука на слэнге) до победы стандарта 44100, частота дискретизации плавала от 18 до 31кГц, так что чип с часовым кварцем вполне себе на уровне.
Хотим 48кГц дискретизацию — даем 48кГц на вход, хотим 32768 — даем 32768. PLL — встроена. Набора из 12.288МГц + 3072кГц + 48кГц — не надо.
Размер ОЗУ — 32768 сэмплов (слов), но уже не 24 бит, а 14 бит, с упаковкой.Алгоритм в даташите не описан. При частоте дискретизации 32768 Гц — это 1 секунда звука. Вся область ОЗУ — аппаратная кольцевая память.
Разрядность AUX АЦП параметров — 9 целых 1/512 бит (513 значений, от 0 до 512).
Внутри DSP ядра 32 регистра общего назначения по 24 бит.
Аккумулятор 24 бит (+ состояния «насыщения», об этом ниже).
Операнды разного формата, зависит от команды и к чему обращаемся, ОЗУ, или РОН, как правило, знаковые дробные с фиксированной точкой.
Есть «параллельный» аккумулятор, регистр «указатель» адреса, аналог регистра флагов и еще кое какие минорные вещи.
Команд DSP всего 20. Основной язык программирования — Spin Asm.
Максимальный размер программы — 128 команд по 32 бита.
Забегая вперед, скажу что этого достаточно чтобы сделать свой собственный процессор типа Zoom3030.
Циклов — нет. Любимый многими FFT чип не умеет, в автокорреляцию — тоже не получится, но и без этого будет над чем поработать. При этом, чип хорошо справляется с пространственными эффектами (ревер, хорус, дилей), компрессией, фильтрацией и при желании можно сделать синтезатор 8bit или FM, задавая частоту через вход потенциометров или аудио.
При всех недостатках, фильтр первого порядка — это 2 команды, полочные фильтры первого порядка — 2 команды, allpass фильтр Шреддера-Логана — 2 команды!
На FV-1 вполне выполнима импульсная свертка (FIR) на 125 точек.
Из аппаратных средств еще можно отметить два генератора низкой частоты (LFO) синусоидальной формы (sin 0,1) и два генератора пилообразной формы (ramp 0,1).
Разрядность, а следовательно, и точность LFO различается в разы. У пилы точность частоты 16 бит, но только 4 назначаемых значения амплитуды. У синуса частота 9 бит, но точность амплитуды — 15 бит (пруф: www.spinsemi.com/knowledge_base/pgm_quick.html#LFOs).
Генерация треугольной формы выполняется «зеркалированием» пилообразной. Если надо будет еще LFO, они делаются по известным алгоритмам, типа DDS или Sin Cos.
Средства отладки — уши, очень пригодится осциллограф.
Ближайший широко известный аналог FV1 «все в одном» — ADAU1701. Он прилично производительнее FV-1, но памяти сэмплов в 32 раза меньше. Поэтому годится для ограниченного числа эффектов, т.к. ревербератор приличный не сделать, октавер и прочее — тоже. Еще из конкурентов набор микросхем Wavefront AL3201, но — уже набор, об этом чуть ниже.
К самодельщикам бывшего СССР чип зашел практически инкогнито, году в 2008 м. У паяльщиков тогда в тренде был микропроцессорный комплект AL3201 от Alesis, который был прям классный. 48кГц, 24 бит, кварц на 12.288, балансные входы и выходы АЦП и ЦАП, 16 вшитых программ.
И, неизвестный чип Spin FV-1 прошел мимо. Мол, что за ноунейм, наверное китайцы сделали очередной PT2399. И его не воспринимали всерьез, пока не начался бум эффектов, в частности шиммеров (разновидность ревербератора с октавой вверх, звук частично возвращался с выхода ревера на вход, таким образом каждый цикл тон повышался на октаву) и эффектов бесконечного «зависания» звука (Hold/Freeze), когда сыгранный аккорд по нажатию кнопки мог звучать до бесконечности.
Когда энтузиасты стали смотреть под кузов этих недешевых педалей — удивились, увидев там Spin FV-1, иногда прямо на плате, срисованной под копирку с сайта зарубежных самодельщиков.
Чип привел на офсайт, офсайт — на форумы, форумы — на гуглеж всего что только можно, чтобы добыть исходники крутых эффектов, выкладывать которые авторы явно не торопились.
Гуглилось все, включая автора чипа. Им оказался никто иной, как кейт Барр.
Внезапно, это оказался отец MXR и той самой Alesis, чьи чипы выше обозначены как «классные».
Американцы знали чей чип, поэтому сравнительно быстро погрузились и разобрались. У нас же — царил и царит консерватизм.
Таким образом, восстановился порядок: FV-1 — потомок AL3201, а AL3201 — эволюция обработки звука Keith Barr.
Сравнение с ближайшими функциональными аналогами
Про ADAU1701 был абзац выше. В общем-то, широко распространенных решений «все в одном и чтобы легко паялось и программировать не пришлось» больше нет. Из популярных комплектов приходит на ум Alesis/Wavefront AL3201, он же Cool Audio V1000.
В целом, у комплекта AL3201 и FV-1 схожая архитектура. Но:
- у Spin FV-1 одна микросхема «все в одном».
- Три потенциометра для рулежки.
- i2c интерфейс для подкачки пользовательских программ.
- Доступный кварц маленького размера.
- Микроконтроллер — не нужен.
- Можно дешевое доступное ПЗУ.
У AL3201:
- Набор из трех микросхем (АЦП, DSP, ЦАП).
- Балансные вход и выход.
- Есть более производительный аналог, к которому подключается более 2х каналов.
- Без чипа интерфейса, который возьмет на себя работу с потенциометрами и загрузку программ, он ограниченно раб
отоспособен, требуется минимум энкодер для смены предварительно прошитых программ.
Получается, Spin FV-1 + 24LC32A достаточно мощный и самодостаточный кастом комплект, когда для AL3201 надо еще микроконтроллер для опроса потенциометров и решение для хранения программ.
Из достоинств AL3201: можно менять хоть 1 команду программы. Если надо подключить N потенциометров — только проблемы выбранного МК. Программу без пересброса загрузить — запросто. У АЦП и ЦАП — балансные входы и выходы, меньше шум.
Но, комплект минимум 3 чипа, площадь на плате, монтаж, потребление, тесты.
В настоящее время, даже микроконтроллер типа STM32F4 может довольно неплохо эмулировать вышеназванные чипы, а специализированные DSP вообще порвут их клочья.
Но, к ним все равно требуется внешний кодек (АЦП+ЦАП), и более существенный «обвес». Паять шаг 0.4–0.6, а тем более, BGA — сильно сложнее, чем или 1.25.
Плюс, нужен софт и IDE для работы со звуком. А у Spin FV-1 все это есть «из коробки», поэтому он популярен у самодельщиков и любителей поколдовать со звуком.
Немного истории
Лично мне был интересен ход мышления Кейта Барра и очень повезло, что в интернете были его сообщения и интересные диалоги. Человек он был открытый, охотно делился опытом. И если лет 5 назад при старте освоения чипа было практически ничего не понятно, то после получения кое-каких навыков, многие вещи прояснились, снова интересно почитать.
Великие вещи не берутся из ниоткуда. Keith Barr со-основал MXR в 1974 м, MXR переживал взлеты и падения, и спустя 10 лет был продан, а в 1984 м Кейт основал Alesis.
У фирмы Alesis богатая история в плане разработок, плюс из нее отпочковались специалисты и организовывали свои проекты, например, Line6, а от Line6 — Merris. Такое вот дерево производителей музыкального оборудования получилось, можно сказать, из под его начала.
Кейт писал, что в 70е, во времена MXR еще работал на обычной работе — нанимался матросом и возвращался из плавания со свежими идеями и записями, воплощая их в железо.
Однако, в 80е был кризис не только видеоигр, но и гитарной педальной индустрии тоже (тот же Electro-Harmonix приостановил деятельность, не помогала ни реклама по ТВ, ни визит в Москву), и MXR пришлось продать.
Кейт не унывал, а наоборот, устремился в цифровую обработку звука, которой тогда мало кто занимался, а приборы были очень дорогими, прям очень.
Первый и культовый цифровой ревербератор EMT 250 стоил $20 000 в 1976 году, вот его фото:
Первое что приходит на ум — компактность! О весе каждой «педальки» остается только догадываться.
На самом деле, по меркам 70х он и вправду маленький, Plate реверы c реальными металлическими пластинами были значительно больше.
Lexicon 224 1978 года на 2 программы стоил $7500, а на 4 программы — $7900. Он был прям хит, к тому же, сильно юзер френдли в плане размеров, и уже под рэк:
Alesis XT, вышедший в 1985 году стоил всего $799, уделывая ценой Лексикон на порядок. Ревер менялся от 200 мс, до 10 секунд, куча ручек и размер 1 юнит. Это был разрыв шаблонов.
Вот это он:
Кейт Барр мыслил так: мол, раз делать цифровой звук, понадобится разработать специализированные микросхемы. Значит надо ехать туда, где их производят. И переехал в 80х в Калифорнию.
Кстати, EMT и Lexicon тоже немного родственники, через доктора Barry Blesser. Мир довольно тесен.
В 70х микропроцессоры едва появились на свет и были довольно медленные, дорогие, распространены мало, никто не воспринимал диковинку всерьез в качествах отличных от терминалов/печатных машинок, в результате первые цифровые реверы были «железные». Да и тот же АЦП — отдельная плата, битком набитая деталями. Умножение строилось на микросхемах умножения, и перемножить 2 числа по 16 бит стоило больших денег.
Ревер Кейта Барра выехал на том, что в нем не было умножений совсем. Только суммирование и сдвиги. Для сетей Шреддера использовались коэффициенты 0.5 и -0.5 (сдвиг на 1 бит), в большинстве случаев этого хватало.
Глубоко в историю я не нырял, но, думаю, заказные микросхемы тоже имели место и делали свое дело, вспомним легендарную ULA в ZX-Spectrum, или ключевые чипы Amiga. Это и экономия места на плате и защита разработки.
Несмотря на успех и признание, дела у Alesis под конец пошли не очень и в 2003 Кейт Барр продал её, основав Spin Semiconductor, в котором разработал Spin FV-1.
Архитектура FV-1 унаследована от первых микропроцессорных ревербераторов сконструированных Кейтом Барром, когда на адресной шине процессора старшие биты были адресами ОЗУ, а младшие — ПЗУ. И между циклами регенерации динамического ОЗУ как раз укладывалось 128 команд ПЗУ. Таким образом, на цикл чтения ОЗУ приходилось 128 циклов ПЗУ, которые в FV-1 стали программой в 128 команд.
Для «раскрутки» чипа было не так много ресурсов + ограничения, + значимые эффекты были созданы чуть позже, а сами Spin по каким-то причинам эффекты не выпускали и были не совсем в курсе текущей моды у музыкантов.
Вероятно, продав Alesis Кейт не имел права позиционировать себя с Alesis и MXR (на западе за неправомерное использование чужой торговой марки набутылят довольно быстро) + неконкуренция, Возможно, поэтому сами Spin какие-либо законченные устройства на FV-1 не выпускали.
Железо
Официальный путь
Лучше всего купить официальную девборду
тут.
К счастью, она подешевела в 2 раза (раньше стоила $200) и стоит для нас столько же, сколько в 2010 м.
Она как влитая работает со штатной IDE и так далее. Экономит тупые телодвижения вроде «откомпилируй-прошей-отключи программатор».
Путь Ильича
Сделать самому, например взять за основу схему Tonepad FraVerb
Обычно все эффекты моно и можно не тратиться на детали для правого канала, а то и входной буфер целиком выкинуть. Кто владеет утюгом и паяльником — осилят.
К плате надо подключить программатор i2c и ПЗУ типа 23LC32A или 24LC64.
Я колхозил свой программатор, на базе STM32 и общался с ним через виртуальный com порт, потом надоела нестабильность и подключил PicKit-2 (за 200р с али).
Вот как подключать:
Arduino тоже сойдет, но надо учесть написанное выше про подтяжку.
Уверен, что готовые платы FraVerb продаются на фанатских сайтах, с платами и наборами для любителей спаять себе гитарную педаль самому и утюжить — не придется. С другой стороны, утюг — и через пару часов плата в руках.
Сам чип Spin FV-1 покупать только в проверенном магазине. Например, smallbear-electronics.mybigcommerce.com или тот же Profusion.
Обращаю внимание: ни одного небракованного чипа на aliexpress куплено не было, там только брак. Не тратьте свои деньги на али.
Вариацией пути Ильича будет покупка и допиливание педали вроде T-Rex Tonebug (смотреть цифровые эффекты на FV-1) (стоит 1000–3000р за б/у) или любой другой, где есть искомый чип, 3 потенциометра параметров и ПЗУ.
Еще вариант — купить в интернете готовый модуль-заготовку, на котором распаяны основные компоненты и остается подключить «GPIO» и программатор.
Я ищу время чтобы набросать свою девборду на FV1+Blue Pill. Тогда не нужен будет кварц (тактовую будет давать МК) и i2c ПЗУ (FV1 будет грузиться с МК), и вообще, там схема штук 5 конденсаторов и десяток проводков.
Программный эмулятор
Официального нет, можно попробовать неофициальный.
Эндрю Килпатрик сделал класс эмуляции на джаве, но без GUI: electro-music.com/forum/topic-46040.html, HolyCityAudio его применили в своей GUI утилите — конструкторе патчей: github.com/HolyCityAudio/SpinCAD-Designer.
Плюс этого конструктора, что он может грузить сторонние прошивки.
Соединив их вместе получается работоспособный эмулятор, в который можно грузить свои программы.
В целом, приноровиться можно, к сожалению, мне удалось оживить эмулятор, когда чип во всю гонялся живьем, и… эмулятор показалось неудобно и не то, и вообще, как безалкогольное пиво и первый шаг к…
Сам конструктор, если использовать его не только как плеер прошивок, представляет собой графический конфигуратор (чем-то похож на Sigma Studio), который соединяет блоками цепочки сниппетов в патч (программу), местами странный (генерируемые им исходники плохо читабельны из-за отсутствия адекватного форматирования и убирания незначащих нулей и т.п.). Для старта — сойдет, можно свою форматировалку написать и прокатывать ей исходник, чтобы глаза не болели и проект открытый, можно допилить.
Возвращаясь к эмуляуции, неподготовленному человеку придется уделить вечерок чтобы все запустить.
Параметры i2c
У чипа прошито 8 заводских программ, также он может считывать еще до 8 программ с EEPROM микросхемы типа 24LC32A по шине i2c.
Частота i2c шины — около 260кГц, напрашивается вывод, что 2^15 степени Герц тактовой частоты кварца умножаются на 8. Соответственно, при 50кГц тактовой, частота i2c должна быть в районе 400кГц. Судя по даташиту на 24LC32, чип может не потянуть 400кГц тактовой при питании от 3.3 вольт. Я — хитрил, грузил патчи на 32768, а потом поднимал до 48кГц, благо тактирование было от МК.
Подтягивающие резисторы уже стоят внутри чипа, номинал 4К-5К, в зависимости от тех. процесса. Внешние ставить — не нужно.
Иногда, когда на i2c висет программатор (PicKit-2) — чип не может загрузиться, поэтому программатор придется сделать отключаемый (тумблер, или разъем).
Среда разработки
Скачать и установить с официальной страницы
SpinAsm assembler for the SPN1001 V1.1.31
Среда олдскульная, возможностей там примерно как у notepad.exe. С другой стороны, в 128 строк и 20 команд, можно обойтись без дописаторов и автотабуляций.
Редактировать исходники можно и в любом удобном редакторе, а в SpinAsm просто компилироваться.
Директив, кроме MEM и EQU — нет, подкачивать сниппеты и свои библиотеки придется через ^C ^V.
Кроме того, существует неофициальный альтернативный компилятор написанный на питоне: pypi.org/project/asfv1, лично я его не тестировал, т.к. процесс разработки был уже отлажен, а на счету — каждый час.
Как оно работает, простым языком
Сам процессор — довольно простой, чем-то похож на ZX-Spectrum Z80 или Atmel AVR. Задачи тоже немного схожи: на спектруме задача была выстроить кадр 50 раз в секунду, здесь же надо посчитать всего 1 сэмпл, но 32768 раз в секунду.
Упрощенно, работа чипа похожа на синхронный конечный автомат.
Каждый тик генератора (а их 32768 в секунду при использовании часового кварца) защелкиваются данные с АЦП + отправляются в ЦАП (входы/выходы аудио и входы потенциометров) и запускается программа длинною 128 команд. И так тик за тиком.
Аккумулятор (А) — классический, единственный регистр, который может все. Регистры общего назначения годятся для хранения и как операнды, например, для умножения.
Доступ к АЦП/ЦАП и прочей периферии ведется через специализированные регистры.
Система команд элементарна (и почти целиком завязана на аккумулятор):
- Чтение и запись в/из аккумулятор памяти или регистров, работы с памятью.
- Умножение аккумулятора на константу с приращением другой константы.
- Умножение аккумулятора на регистр
- Логарифм/экспонента аккумулятора.
- Команды управления LFO (генераторы низкой частоты, нужны для эффекта хорус, тремоло, замыливания хвостов ревербераторов и транспонирования). Смена темпа, амплитуды, сброс в начальную позицию.
Чего нет:
- Нет операторов циклов. Только раскрывать.
- Нет привычных If Then, все по классике ассемблера — переходить согласно флагу выполнения предыдущей операции. Есть команда условного относительного перехода, переход возможен только вперед, до 64 команд. Если надо пропустить 96 команд — переходов придется делать два.
- Нет Push/Pop (стека — нет) и много чего еще.
С аккумулятором не работают лишь команды сброса LFO, условного перехода (проверяет не аккумулятор, а флаги предыдущего состояния) и полной настройки LFO, когда в одной команде задается частота и глубина.
Каждая команда — 32 бита, соответственно, длина всей программы постоянна и составляет 128×4 = 512 байт.
Если команд в программе менее 128, то неиспользованная область добивается компилятором NOP’ами (по факту, это безусловный переход на следующую строку).
В 128 команд надо уложить все, левый, правый канал и т.п. Известны случаи мультиэффектового использования Spin FV-1, когда на левом канале крутился алгоритм, допустим, хоруса, а на правом — ревер, или фэйзер. И выход левого канала замыкался переключателем на плате на вход правого. Но можно «замыкать» и в программе, все равно, 3 общих потенциометра и общая память.
Проблема обычно не в размере программы (в 5 строк можно сделать неплохой эффект, а в 128 — штук 20), а в нехватке памяти и ограниченном интерфейсе. Нельзя менять параметры на лету больше трех штатных, как в AL3201 или ADAU1701.
Потенциометры с AUX ADC читаются как линейные. Для имитации логарифмической характеристики данные считанные с потенциометра возводятся в квадрат, либо в куб, с соответствующей потерей точности. Для обратного логарифма — извлекается корень.
Короткая шпаргалка от создателей FV-1
www.spinsemi.com/knowledge_base/cheat.html команды, аргументы и размерность. Будет у вас открыта постоянно.
Внутренняя математика
Операции — с фиксированной точкой.
Основной формат аккумулятора можно назвать Q.23 (по аналогии с ARM c его Q15 и Q31). Т.е. первый бит — знак, остальные 23 бита — мантисса. На языке FV-1 это формат S0.23. Знак, 0 бит до точки и 23 бита после точки.
Числа с фиксированной точкой, аккумулятор 24 бита, может хранить число [ -1; 1) или же 0×800000 до 0×7FffFF.
Что надо вспомнить про подобную математику? что при умножении чисел меньше 1 итоговое число еще меньше. 0.5×0.6 = 0.3, поэтому переполнения вещь довольно редкая.
Значения аккумулятора [-1;+1) в дробном представлении фактически означают от -2^23 / 2^23 до (2^23–1) / 2^23, т.е. аккумулятор будучи положительным на 0,0000001192092896 никогда не дотянет до единицы.
Аккумулятор не переполняется, как в классических микропроцессорах, а «насыщается». Если А = 0.6 и к нему прибавить 0.9, то результат будет (2^23–1) / 2^23 = 0,9999998808 (+ сработает внутренний флаг «переполнения»), на классическом процессоре результат был бы условно (0.6 + 0.9 — 0,9999998808 = 0,5000001192) + флаг переноса.
При вычитании тоже самое, Акк станет равен -1.0, флаг, и всё.
Получается «жесткое ограничение» ближе к электронике, для звука оно и к лучшему и в алгоритмах используется как фича.
Из-за насыщения, крутить классический счетчик типа i++, с автосбросом в 0 делается на 22 битах аккумулятора, выполняя после инкремента или декремента AND 0×3FffFF. Значение аккумулятора может меняться от [0; 0.5) в представлении с точкой и никогда не переполнится благодаря AND, после достижения максимума — сбросится в 0.
Аккумулятор может работать не только с числами с фиксированной точкой, но и побитно. Еще, это единственный способ загрузить маленькое, либо очень точное число, т.к. младшие 8 бит аккумулятора почти всегда недоступны для прямой записи или иного воздействия (о этом чуть ниже, в аргументах команд).
Кроме того, в аккумуляторе формируется указатель на адрес ОЗУ для чтения, когда надо считать данные с вычисляемого адреса, а не заданного константой. Для этого адрес считается в старших битах аккумулятора (младшие 8 могут быть любые, все равно отбрасываются, знак — тоже == 0, => оставшиеся старшие 15 бит соответствуют 15 битам адреса в ОЗУ), а потом записывается в регистр PTR.
Аргументы команд
В плане размерности — небольшой зоопарк. Команда в скомпилированном виде всегда 32 бит, из них 5 бит — код операции, потом могут идти перечисления регистров (еще 6 бит) и операнды. Чтобы все вместилось в 32 бит, размерность операндов — плавает.
Например, если читать регистр, то операнд 16 бит (S1.14), если читать ОЗУ, то операнд уже 11 бит (S1.9), т.к. в команде код операции 5 бит, адрес ОЗУ 15(16) бит и операнд — 11 бит.
Обычно не предается этому значение, пока на выходе девайса не получается тишина, или искажения, и поиск ошибки много часов подряд, то потом приходится вдумчиво читать мануалы.
Аргументы обычно [-2; 2), т.е. аккумулятор «снаружи» можно умножать на константу даже больше 1, но меньше 2. «Насыщение» это не отменяет. И двойка эта размерностью то 16 бит, то 11 (дополняется до 25 бит, где младшие биты просто нули).
Маленькие и большие числа
Иногда надо сделать фильтр на самую низкую частоту, или отмерить время, или еще чего.
Пример 1:
; хотим вычесть из аккумулятора маленькое числоSOF 1 , -0.0002 ; (размерность s1.14 + s0.10). Суть: A = A * 1 - 0.0002
Будет вычитаться ноль, т.к. второй аргумент по модулю меньше 1/(2^10), оно же 0.0009765625. Если это переменная для плавного затухания громкости, то затухания просто не будет.
Пример 2: RDFX REG16 , 0.000018 ; меньше 0.000018 (1/16384 или 0.000061035156250)
Тоже самое, хотя разрядность S1.14, но числа по модулю меньше 1/(2^14) будут заменены на ноль, а близкие к граничным — будут ощутимо врать.
Хотим загрузить 24 битное число? Грузим побитово!
CLR ; очистка аккмулятора
OR 0x123456 , загрузка 24 битного произвольного числа в аккумулятор. [-1 ; 1)
Чтобы проверить, будет ли число воспринято компилятором не как 0 была набросана довольно примитивная, но онлайн проверялка: s.shift-line.com/decompiler2/calc.php
Рекомендации по коэффициентам
Как повысить качество звука, особенно на тихой громкости?
Отчасти, правильным выбором коэффициентов при командах. Математика FV-1 с фиксированной точкой, чаще всего S1.14 (коэффициенты при командах чтения, олпаса и тп).
Использование заковыристых коэффициентов в циклической обработке может подгаживать звук, добавлять артефактов. Облегчить жизнь можно применяя коэффициенты близкие степени двойки.
Не понятно? Тогда пример:
Число 0.6 после компиляции и декомпиляции назад станет 0.5999755859375 (это максимально приближенное машинное значение к 0.6). Некрасиво и корявенько.
Смотрим еще более в корень: если мы захотим загрузить 0.6 в пустой аккумулятор FV-1, то сделаем
OR %010011001100110011001100; 24 бит вариант
OR %0100110011001100; 16 бит вариант
Видно, что при 16 битах информация в младшем байте теряется и искажается. А потом упаковщик памяти сделает еще хуже.
Как быть? Подберем близкие степени двойки коэффициенты, с меньшей «детализацией хвоста».
Например, 0.6 можно записать как 144/256 = (128+16)/256 = 0.5625, или 160/256 = (128+32)/256 = 0.625,
или напрячь калькулятор и получить 152/256 = (128+16+8)/256 = 0.59375
152/256 = 0.59375, о определенной погрешностью равно 0.6, но есть нюанс:
OR %0100110011001100; было 0.6 = 0.5999755859375
OR %0100110000000000: подобрали 152/256 = 0.59375, младшие биты == 0, красиво, как блокчейн! :-)
Если второй вариант сдвигать вправо, то полезные данные коэффициента долго не потеряются и детали звука не так сильно исказятся.
Если хотим наоборот, добавить искажений и шума, то используем кривейшие числа. Но требуется такое довольно редко.
ОЗУ у FV-1 — 14-битное. Поэтому мелкие детальки будут теряться, и наши более стройные коэффициенты отсрочат потери как могут. Кроме того, такие числа лучше логарифмируются FV-1, т.к. операции логарифмирования и экспонирования выполняются приближенно. Мы попали в 8 старших бит и имеем еще 16 бит запаса при масштабировании.
ОЗУ
ОЗУ емкостью 32768 слов по 14 бит (упакованных, алгоритм не озвучен, вероятно, мантисса+экспонента+знак) работает как разомкнутое кольцо. Т.е. каждый новый тик кварца физический адрес увеличивается на 1 и данные сдвигаются вверх по адресному пространству.
Допустим, если записать значение -1 в нулевой адрес, то при следующем тике эта единица будет уже по адресу 1, затем 2 и так далее.
Поэтому задача завести данные в память в обратном порядке похожа на квест.
На что кольцевая память похожа физически? На магнитофон, в котором крутится кольцо магнитной ленты. Вот мы записали что-то и, записанное тут же сдвинулось и через фиксированное время вот оно снова. А эхо — и есть цикличное повторение звука. Так и делались первые «доступные и портативные» эхо процессоры.
Зачем нужно кольцевое ОЗУ и чем оно хорошо будет понятней на примерах, которые будут ниже.
Если разрядность ОЗУ недостаточна (мантисса дай бог 11 бит, а на деле может оказаться 8–10), есть рецепт как сделать разрядность памяти из 14 бит снова 24, при этом потери памяти в 2–3 раза, т.к. отдельно хранятся старшие биты мантиссы, отдельно остатки. Кто возился с математикой запертой в том же float — эти приемы знает.
Конечно, точность выходит пугающе низкая, но качество звука подтверждено практикой. Даже 8 хороших бит — это качество кассетного магнитофона (12 бит — бобинного, грубо говоря, студийного, на который писались от Beatles до Prodigy) + есть экспонента, а значит, детализация при разных уровнях громкости — не провалится.
Так, что звук нужно уметь готовить.
Написание программ
Работа ведется на языке Spin Asm в среде производителя. Ассемблер простой, всего 20 команд.
Инструкция к ассемблеру качается с сайта производителя.
Со средствами отладки все просто, их — нет. Теоретически, для отладки можно поморгать светодиодиком если повесить его через повторитель или резистор 10кОм на выход одного из ЦАП (как правило, правый канал), делая систему моно. Будет эдакий однопиксельный осциллограф. Либо настоящий осциллограф туда же. Он пригодится чтобы видеть что творится в переменных, огибающих, генераторах и т.п. И банальных вещах, поступает ли звук на вход. Сойдет любой, больше 24кГц на выходе не получится. Просто крутить коэффициенты на готовых исходниках можно и на слух, но чтобы оторваться от них, все же надо найти любой осцилл, хоть учебный.
Если использовать самодельную девборду, то откомпилированный пакет программ (1–8) зашивается в микросхему EEPROM памяти с интерфейсом i2c. Среда разработки умеет выгружать intel hex. С заводской девбордой все проще, там клик в меню.
Spin FV-1 считывает из ПЗУ программу соответствующую ножкам выбора программы.
На официальном сайте и форумах хватает примеров программ, можно начать с них. Будет ничего непонятно, но уже можно научиться компилироваться, шить, слушать и крутить ручки.
Алгоритм простого дилея в 1 секунду
Дилей — это повтор звука с задержкой. Если повторы приглушать и подмешивать ко входу, будет простенькое караоке-эхо.
А если при этом повторам срезать высокие частоты фильтрами, то это уже отсыл к ленточным-магнитофонным дилеям, которые использовались богатыми музыкантами 60х — 70х годов прошлого века.
При достаточно высокой скорости ленты и небольшом токе стирающая головка не успевала до конца размагничивать и срезала высокие частоты, поэтому эхо затухало постепенным срезом частот. Прям как точить деревяшку рубанком, слой за слоем.
Попробуем начать с одного повтора, алгоритм:
- Чтение АЦП левого канала.
- Запись в ОЗУ по адресу 0. Через 32767 тиков записанное значение автоматически дойдет до адреса 32767, т.к. память кольцевая и сама сдвигается. Нам не надо руками считать адреса чтения и записи как в классических ПК/процессорах.
- Чтение ОЗУ по адресу 32767.
- Запись в ЦАП левого канала.
Все. Остальное все компилятор добьет nop’ами.
; Пример сам
ой простой задержки на 1 секунду, только один повтор, без зацикливания и обратной связи.
; На выходе только задержанный сигнал. Чистый, если он нужен, должен быть подмешан аппаратно, блендером, микшером или парой резисторов.
LDAX ADCL ; чтение АЦП в акк. Предыдущее значение акк. игнорируется
WRA 0 , 0 ; Запись ОЗУ, адрес 0. Пишем АЦП в нулевое слово, и чистим акк.
RDA 32767,1 ; читаем последнее слово ОЗУ в чистый акк
WRAX DACL,0 ; и пишем в ЦАП, чистим акк.
eof: ; конец программы
На бейсике сие выглядело бы так:
RAM[0] = ADCL
DACL=RAM[32767]
Всё. Входной сэмпл доедет до выхода за 32768 тиков, считать руками указатель адреса — не нужно.
Соответственно, чтобы дилей был в 0.5 секунды, данные надо читать по адресу не 32767, а 16383. А для 0.25 секунды — 8191.
У нашей девборды может не быть аппаратного чистого и сыграв ноту — в наушниках слышно тишину, а только через секунду — ноту.
Что ж, это исправляется в 2 счета.
LDAX ADCL ; A = ADCL
WRA 0 , 0.5 ; RAM[0] = A ; A = A * 0.5
RDA 32767,0.5 ; A = A + RAM[32767]
WRAX DACL,0 ; DACL = A ; A = A * 0;
eof: ; конец программы
Итак, читается АЦП, записывается в ОЗУ. Уменьшается в 2 раза. Читается значение задержанного на 1 секунду, но не всё, а только половина.
Итого, в аккумуляторе 50% громкости входного («чистого») сигнала, 50% громкости задержанного (обработанного) сигнала. Т.е. у нас случился мини микшер, и стоил он нам ноль байт, просто поправили пару коэффициентов. Видно, что каждая команда делает несколько операций за раз и это можно использовать с пользой.
Дилей с регулируемым временем задержки
Всё неплохо, но задержка на фиксированное время не особо интересна, в музыке нужно попадать в ритм, а значит время задержки надо настраивать ручкой потенциометра кратно ритму.
Для времени задержки определяемой потенциометром, нужно масштабировать (высчитывать) адрес чтения задержанного сигнала с помощью потенциометра [0…1].
И тут мы влетаем на такую вещь, как разрядность АЦП потенциометров, которая составляет 9 бит. А разрядность адреса памяти — 15 бит.
Получается, шаг регулировки задержки кратен 2^15/2^9 = 2^6 = 64 сэмплам, т.е. регулировка не плавная, а с проскоками, но, в принципе, достаточная. При кручении могут появляться артефакты, для красоты вращения ручки по мере роста опыта с ними придется бороться.
А с масштабированием — все просто, если буфер 32768 сэмплов — это одна секунда. То потенциометр в среднем положении равен 0.5, 32768×0.5 = 16384, это пол секунды.
Потенциометр «на 9 часов» равен 0.25, это ¼ буфера, или 0.25 секунды.
Если наш буфер во всю память уменьшим в 8 раз, то и максимальное время задержки упадет в 8 раз и относительн