Mini-JV880pi
Mini-JV880pi

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

В видео на ютубе все нагляднее и со звуком

Странно, что я занялся этим ретро синтезаторным проектом как раз во время расцвета AI музыки (и видео), которая на данный момент заполнила всевозможные чарты, соцсети, видеоплатформы, стриминговые сервисы. И скорее всего синтезаторы, а так же музыканты как класс скоро никому не будут нужны.

Как все начиналось

Все началось со статьи Как собрать клон Yamaha DX7 за 10$. Так как я достаточно давно занимаюсь музыкой, и люблю конструировать всякие электронные штучки, меня эта статья заинтересовала. Я тут же начал прикидывать по цене возможные варианты. RPI2040 конечно же очень дешево, но посмотрев пару обзоров на Picodexed на YouTube, меня не привлекла простенькая синтезаторная составляющая. Понятно, что это полная эмуляция движка Yamaha DX7, но слишком уж звук невзрачный и простой. После просмотра вариантов эмуляторов синтезаторов на RPI на YouTube меня больше заинтересовали проекты MiniDexed, MT32-pi и Mini-JV880. По минимальным требованиям подходила достаточно недорогая малинка RPi Zero 2w, которая является бюджетным вариантом RPi 3 с уменьшенной памятью и сниженной частотой процессора. Но зато имеет полноценные 4 ядра. А так как эмулятор весит всего ничего, то 512мб памяти должно хватить для всего. Поиск самой низкой цены привел меня на Pinduoduo, где я и купил Zero 2w з�� 130 юаней. Вместе с платой я так же заказал ЦАП PCM5102 за копейки. Но про дисплей не подумал.

Дисплей

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

Снизу OLED, сверху синий 1602.
Снизу OLED, сверху синий 1602.

Пришлось подробнее изучить datasheet и правильно сконфигурировать дисплей для работы по I2C. По центру видны перемычки для конфигурирования. Дисплей может работать в четырех режимах: 6800, 8080, SPI, I2C

Обратная сторона дисплея.
Обратная сторона дисплея.

MIDI интерфейс

MIDI интерфейс (я же должен как то давать команды синтезатору) был собран из первой попавшейся оптопары. Но так как у транзистора не было смещения по базе, да и вообще не было базы, команды проходили с ошибками. Да и 3.3в питание тоже осложняло жизнь. Позже я все-таки нашел оптопару с выводом базы и сделал правильную схему.

В качестве элемента управления я использовал не энкодер, что было бы проще, а кнопки. Вернее джойстик от какого то телевизора. Тоже валялся в мусоре. Отпаял все элементы с платы и тонкими проводками соединил выводы джойстика с RPi.

ЦАП

Ну а с PCM5102 все было просто. Соединил по схеме. Схемы, кстати, есть во всех проектах на гитхабе. Единственное, что я не посмотрел на схему и запитал его от 3.3в. Хотя во всех схемах от 5в. Я потом переключил, но разницы никакой не услышал.

Запуск

Сначала я запустил MT-32pi. Эмулятор MT32 порадовал жирным и чистым звуком, несмотря на то что он эмулируется с изначальным 32кгц сэмплрейтом. Но вот эмулятор SoundFont (.sf2) немного убогий. Все как бы с ним нормально, грузит даже большие (>100мб) файлы .sf2, но динамика клавиш оставляет желать лучшего. Слабые звуки почти не слышны, а громкие звуки слишком громкие, то есть управляемости динамикой нет. Возможно какой то баг или неточность интерпретации команд. Автора этого эмулятора dwhinham захейтили где то в интернете, уж не знаю за что. Но в итоге он послал всех и бросил проект. Хотя возможно проблема в FluidSynth, который использовал dwhinham в своем проекте.

При запуске нам показывают красивую заставку.
При запуске нам показывают красивую заставку.

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

После этого я решил запустить MiniDexed. Но тут меня ожидал неожиданный сюрприз. Мой дисплей SSD1305 не поддерживался библиотекой Circle, которую использовал MiniDexed. MT32-pi использовал свои драйвера дисплеев, поэтому там есть поддержка почти всех распространенных дисплеев. Вот так это выглядело при запуске:

MiniDexed на дисплее SSD1305 с драйвером SSD1306
MiniDexed на дисплее SSD1305 с драйвером SSD1306

В итоге мне пришлось смотреть код драйвера библиотеки Circle и сравнивать отличия с драйвером MT-32pi. Хорошо, что сейчас можно просто запустить Codespace на гитхабе и сразу скомпилировать измененный код. Я поправил код так же как сделано в MT32-pi и все заработало. Проблема была лишь в нескольких строчках кода. У дисплея SSD1305 внутренний буфер 132 точки по горизонтали, хотя реальный размер экрана 128 точек. И используются другие COMpin. Я еще немного разобрался с даташитами и отличие лишь в том, что SSD1305 может выводить градации, либо цвет (если дисплей цветной). На фото хорошо видно, что части изображения выводятся в других градациях. SSD1306 намного проще и этого не умеет. В остальном они одинаковы.

Другая проблема заключалась в том, что я совсем не программист профессионал. Последний раз я программировал в начале 2000-х. Это был Borland C++. Мало того - GitHub для меня вообще темный лес. Все эти pull request и другие разные термины вводят меня в ступор. Ну и изменение драйвера это обычная копипаста, причем драйверы идентичные, но rsta2 почему-то не добавил поддержку SSD1305. Как он ответил мне где то на просторах гитхаба: "Это неправильно, надо писать свой драйвер, а не добавлять костыли в существующий." Но тем не менее добавил мои изменения. Правда это произошло примерно через месяц, а до этого MiniDexed выходил без поддержки SSD1305, что меня очень бесило. Приходилось компилировать свою версию. В итоге получилось так:

MiniDexed с исправленным драйвером.
MiniDexed с исправленным драйвером.

Встраивание

И когда более или менее рабочий экземпляр был собран, я решил все это оформить как устройство. Но делать ужасные деревянные или пластиковые коробочки как большинство минидексеров я не хотел. Да и не видел смысл в отдельной коробке. Ну что мне с ней делать? У меня была MIDI клавиатура Novation 61SL MkII

Novation 61SL MkII
Novation 61SL MkII

и я решил встроить эмулятор внутрь. Портить внешний вид клавиатуры я не хотел и хотел сделать всё так, чтобы эмулятора вообще не было видно и сохранить базовую функциональность клавиатуры. Начал я с дисплея. На фото видно, что используется только правый дисплей. В Novation Remote 61 используются 2 дисплея, но нет энкодеров со светодиодной шкалой. Мне кажется, что от второго дисплея в 61SL отказались по пределу питания. 8 энкодеров с десятью светодиодами на каждом потребляют очень много энергии. А у USB лимит в 500ma. Поэтому на дисплей питания скорее всего не хватало. Причем интересно, что в моей клавиатуре разъем под второй дисплей есть. Но не запаян. Поэтому я решил встроить дисплей с этой стороны. Но не знал как и не знал какой. Поискав на маркетплейсах был найден такой дисплей.

SSD1305. Дисплей работает по I2C есть пины конфигурации адреса. Цвет можно было выбрать синий, белый, желтый. Но я выбрал зеленый. После разборки клавиатуры стало ясно, что целиком дисплей туда не поместится.

На плате видно разъем для несуществующего дисплея CN5
На плате видно разъем для несуществующего дисплея CN5

Пришлось его разобрать. Дисплей состоит из платы, стекляшки со шлейфом и металлического ободка. Замерив длину шлейфа стекляшки, я понял, что саму OLED стекляшку можно поставить под стеклом, а плату убрать в другое место. Подрезав мешающий пластик, я приклеил стекляшку к корпусу клавиатуры.

Плату дисплея я приклеил обычным двухсторонним 3М к плате регуляторов MIDI клавиатуры. Пришлось немного подрезать торчащие из платы выводы разъема, чтобы не замкнуло на нижнюю плату.

Плата дисплея
Плата дисплея

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

Но примерив стекло, стало понятно, что это страшненько выглядит. Стекло ложилось в корпус на 2 небольших выступа по всей длине. и через прозрачное стекло все было видно. Я день убил, заклеивал скотчем область дисплея на стекле и красил черной краской. Но края при отклеивании скотча были рваными и неровными. Отчаявшись я вспомнил довольно простой способ. Заклеить изнутри автомобильной тонировкой. В итоге получилось очень оригинально и даже с небольшого расстояния непонятно, что там что то есть. Просто черное стекло. Хотя область дисплея и отличается по цвету, это практически не заметно.

Готовый дисплей
Готовый дисплей

Потом меня мучала дилемма - как соединить компоненты эмулятора. Запаять? А если что то сгорит? Как менять? И так как у Rpi разъем 40 пин, к нему очень хорошо подойдет разъем и шлейф IDE. Со старой платы HDD был выдернут разъем и запаян в малинку. В качестве ответной части я хотел использовать перепинованый 40 проводный шлейф IDE, но потом посмотрел на ножевое соединение, сечение проводов и отказался от этой затеи. После перепиновки контакты были ненадежные. Поэтому заказал у китайцев разъем для пайки на плату 40 pin. И к нему припаял все провода. Получилось достаточно красиво и надежно. Выбрав произвольное место в клавиатуре, я установил плату малинки. Устанавливал на стойки, сделанные из квадратиков корпуса бытовой аппаратуры (телевизора наверное) с впаяными резьбовыми втулками. Клеил на дихлорэтан.

Ягода малина
Ягода малина

Тут же видно удлинитель SD карты. Почему удлинитель? Потому-что разъем SD карты на плате малинке стоит вровень с краем платы. И даже если плату установить вплотную к стенке MIDI клавиатуры, которая имеет толщину 4-5 мм, то SD карта будет находиться внутри и извлечь ее будет проблематично. Да и разъем карты на малинке простецкий, без пружинной защелки. Поэтому я и использовал удлинитель SD карты. Плату я подпилил снизу, чтобы разъем входил в стенку и карта при установке не пряталась внутри корпуса, а немного выглядывала. Совсем немного, 0.5-1 мм.

Прогоны эмулятора в MT32pi показали достаточно высокий нагрев процессора, поэтому был установлен кусок радиатора от материнской платы на термоклей Kafuter. Так же был выведен USB порт типа А. �� уже после того, как я начал писать очень много кода, я вывел HDMI порт для отладки.

Так как я не собирался питать эмулятор от USB, было решено встроить блок питания внутрь MIDI клавиатуры. Для этого был раскурочен старый китайский DVD и из него был извлечен блок питания на 5/12в.

Блок питания.
Блок питания.

Из него были удалены 12 вольтовые цепи, добавлены блокировочные конденсаторы по выходной части. Установлены конденсаторы увеличенной емкости. У MIDI клавиатуры был переключатель внешнее питание/USB. Внешнее питание было организовано через стабилизатор 7805. Я его выпаял и подключил блок питания на его выход. Таким образом можно было выбирать тип питания самой клавиатуры. От USB кабеля большой длины MIDI клавиатура иногда могла работать нестабильно, поэтому предпочтительно было питать ее от блока питания. Так как теперь клавиатура питалась от общего БП с эмулятором, было решено отказаться от развязки MIDI оптопарой и подключить напрямую. И в принципе меня все устраивало, но переключатель питания на клавиатуре был устроен таким образом, что от USB MIDI клавиатуры запитывал так же и эмулятор. А ему иногда не хватало питания и он зависал. Решил развязать питание клавиатуры и эмулятора диодами. А так как падение на диодах слишком большое, пришлось поднять напряжение питания на 0.5 в и запитать от разных диодов малинку и клавиатуру и при этом выдержать честные 5.0 в, хотя как я понял и клавиатура и малинка в итоге питаются от 3.3 в собственными стабилизаторами. БП собран на обычном 431 стабилитроне и мне понадобилось просто увеличить один резистор, чтобы поднять напряжение. И теперь при включении БП включается и эмулятор и клавиатура, а если переключить на USB, то работает только клавиатура.

Здесь видно что я не стал заморачиваться с платой выхода. Взял первый попавшийся RCA разъем и припаял к нему плату в том положении, в котором она подходила по выводам. На этом фото еще не смонтированы USB и HDMI, но я уже использовал переходник для отладки. Изначально я вообще не думал использовать USB, мне и Serial MIDI хватало, но потом решил что пригодится. А так как я смонтировал USB, то теперь стало непонятно, по какому интерфейсу работает эмулятор, что было важно для отладки, пришлось отказаться от прямого соединения MIDI и ставить оптопару.

Serial MIDI и сетевая кнопка питания
Serial MIDI и сетевая кнопка питания

Таким образом у меня в клавиатуре получился абсолютно автономный эмулятор. Достаточно было соединить эмулятор с клавиатурой USB или MIDI кабелем и можно было играть как на синтезаторе. В данный момент у меня такая конфигурация: USB клавиатуры подключен к компьютеру как обычная миди клавиатура. Эмулятор подключен MIDI кабелем в порт MIDI2. В клавиатуре сконфигурирована передача транзитом входящих MIDI сообщений с компьютера на порт MIDI2. И теперь если я играю на клавиатуре, команды уходят в компьютер и одновременно на эмулятор. А если воспроизводить MIDI с компьютера, команды пересылаются в эмулятор. Поэтому очень удобно работать с DAW.

Немного про софт

Изначально я не хотел портить внешний вид MIDI клавиатуры всякими лишними кнопочками и энкодерами. Все управление я решил сделать средствами MIDI клавиатуры. Novation позаботилась об этом и разработала отличный конфигуратор. Кнопок на панели и регуляторов хватает. Конечно же MIDI управление накладывает некоторые ограничения, но я даже реализовал поддержку MIDI энкодера. Но об этом расскажу немного позже.

Поигравшись с MiniDexed, меня поразило звучание. Все-таки это не Yamaha DX7, а 8 их штук собранные в один перформанс. Ну это если переключиться в режим перформанс и загрузить какие либо перформансы с диска (SD). Перформанс представляет собой настройки для 8 синтезаторов DX7, включая настройки панорамы и громкости. Сконфигурировав MIDI команды для управления громкостью каналов перформанса я мог выделять каналы и понять из чего состоит перформанс и откуда такое жирное звучание. Но все оказалось просто. Основной звук немного сдвинут по фазе или по тональности и панормирован. И в каждом канале по разному. Отсюда и наложение немного измененного одного и того же звука дает плотность и объем. Все просто, но в то же время и печально. Потому-что сам FM движок синтезатора DX7 довольно простой. И конфигурация генерации дает мало вариантов звучания. Они в какой то мере похожи друг на друга, либо дают невзрачный, либо резкий звук.

Конфигурация перформанса

BankNumber1=0
VoiceNumber1=1
MIDIChannel1=1
Volume1=96
Pan1=0
Detune1=-3
Cutoff1=99
Resonance1=0
NoteLimitLow1=0
NoteLimitHigh1=127
NoteShift1=0
ReverbSend1=99
PitchBendRange1=2
PitchBendStep1=0
PortamentoMode1=0
PortamentoGlissando1=0
PortamentoTime1=0
VoiceData1=3B 63 1D 16 63 63 5B 00 00 00 00 00 00 00 03 00 49 00 04 00 08 35 63 1B 32 63 63 52 00 00 00 00 00 00 00 00 02 5E 00 02 00 07 63 63 63 16 63 63 63 00 00 00 00 00 00 00 03 00 31 00 04 00 07 33 63 1C 35 63 63 51 00 00 00 00 00 00 00 00 02 63 00 02 00 07 63 63 63 16 63 63 63 00 00 00 00 00 00 00 03 00 31 00 04 00 07 33 63 1D 34 63 63 52 00 00 00 00 00 00 00 00 02 5D 00 02 00 07 63 1B 63 30 33 32 32 32 04 05 00 24 19 05 26 00 00 01 0C 50 66 65 69 66 65 6E 20 20 20 00
MonoMode1=0
ModulationWheelRange1=99
ModulationWheelTarget1=1
FootControlRange1=99
FootControlTarget1=0
BreathControlRange1=99
BreathControlTarget1=0
AftertouchRange1=99
AftertouchTarget1=1

Таких блоков в перформансе 8 и в конце добавляются общие настройки

CompressorEnable=1
ReverbEnable=1
ReverbSize=81
ReverbHighDamp=24
ReverbLowDamp=5
ReverbLowPass=85
ReverbDiffusion=66
ReverbLevel=79

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

И именно поэтому я начал искать дальше и наткнулся на видео:

Скрытый текст

Мне очень понравилось звучание Roland JV880 на эмуляторе и я решил так же загрузить этот эмулятор. Но возникла проблема. Giulio Zausa написал эмулятор под конкретно свою MIDI клавиатуру, куда он встроил эмулятор и сделал управление эмулятором только по USB и вывод на дисплей MIDI клавиатуры Komplete Control. Поэтому код не компилировался без файла usbkompletekontrol.h, которого в коде не было. Но даже если бы он и был, эмулятор бы не работал без дисплея и определенных миди команд. В итоге я нашел форк Plamikcho в котором так же не было SerialMIDI, но хотя бы поддерживался дисплей, хотя и особо извращенным образом. Дисплей оригинального Roland JV880 содержит 24 колонки в 2 строки. Это дисплей 2402 на обычных HD44780. Но таких дисплеев в широком распространении нет. Можно конечно найти, но это будет дорого и трудно. Обычно самодельщики используют 1602 и дешевую альтернативу SSD1306. Ну и соответственно в 16х2 никак не запихнуть 24 символа. А SSD1306 показывает 20х2 символов. Тоже не 24. Поэтому Plamikcho сделал скроллинг. И это как то решило проблему. То есть все символы эмулятора показывались, но скроллинг был посимвольный, дерганый. Ну да ладно. Скомпилировал я этот проект, а звук то никак не воспроизвести, потому что миди команды послать некуда, потому-что используется USB MIDI который на тот момент у меня был не выведен. И как то меня раздражало, что столь классный и оригинально звучащий синтезатор никто до конца не реализовал. И я решил попробовать доделать до конца этот проект. Но об этом я напишу во второй части.

Ссылки

MiniDexed Probonopd. Эмулятор 8 синтезаторов Yamaha DX7 / TX816

DreamDexed улучшенный форк MiniDexed

MT32-pi Dwhinham. Эмулятор звуковой карты Roland MT-32 / Soundfont 2

Mini-JV880 Plamikcho. Эмулятор синтезатора Roland JV-880

Mini-JV880 Giulioz

Mini-JV880pi мой

Nuked-SC55 основа эмулятора Mini-JV880

Circle библиотека для запуска приложений на Raspberry Pi без Linux