Музыкальная коробочка из Arduino
2021/06/03Дай человеку рыбу, и он будет сыт один день.
Дай ему PC-спикер, и он подключит его к Arduino.
👉 Пропустить охуительные истории и перейти к сути
Каждый мужчина в своей жизни должен сделать три вещи:
- Купить Arduino.
- Подключить к ней кнопочки.
- Приделать к ней PC-спикер.
Первыми двумя вещами я занимаюсь уже давно, собирал на базе Arduino Leonardo всякую дичь и разную хтонь. Добрался наконец и до пиликанья пиликалкой.
В целом пиликать на Arduino несложно: с помощью функции tone()
запускается генерация квадартной волны заданной частоты на заданном пине,
длительность определяется последующим вызовом delay()
, а выключается звук функцией noTone()
.
Полифонии нет — за раз может звучать только одна нота, поэтому цикл tone
, delay
,noTone
нужно повторять для каждой ноты в композиции.
Таким образом, задача сводится к тому, чтобы найти нужную монофоническую мелодию, посчитать частоты нот в ней, их длительность и запрограммировать это на Arduino.
Понапридумывают себе задач дурацких...
Что будем играть? Не гонять же гаммы. Нужно что-то светлое, доброе, вечное. Например, E1M1 из DOOM.
В сети ее можно найти в виде партитуры для Guitar Pro. В нем удобно будет удалить из композиции лишние дорожки, оставив одну гитару, выпилить все эффекты и экспортировать в монофонический трек.
Следующий момент — подобрать частоты нот для использования в виде констант в коде. Можно частоты эти посчитать, если вы ходили в музыкалку, а можно просто нагуглить все эти октавы, диезы и бемоли.
Длительность нот обозначим по долям целой ноты. Целая нота — 1, половинная — 2, четвертная — 4 и так далее.
15 минут трудов и прошивка, которая делает из Arduino пиликалку, готова! Сама композиция подключается как заголовочный файл с нотами и их длительностями.
Круто. Круто-круто-круто. Но чего-то не хватает.
Ну да, как из MIDI-файла прошивку-то делать?
... и пишут программы на Петоне!
А не написать ли конвертер, который будет принимать на вход MIDI, а на выходе давать желанный заголовочный файл?
Тем более, что в Python есть отличная библиотека для работы с MIDI — mido
.
С ней проблем нет, проблемы есть с MIDI как таковым. Когда-то мне рассказывали, что MIDI «прямо в себе ноты хранит» и поэтому такой универсальный и переносимый, поэтому я ожидал, что сделать партитуру из MIDI-файла будет крайне просто. Boy, was I wrong.
MIDI, как выяснилось, хранит композицию в виде сообщений. Буквально все, что происходит в треке (начать издавать звук, перестать играть, добавить эффекты типа вибрато, поменять громкость, задать темп) — это сообщения. У сообщений есть тип, длительность и другие специфические для каждого типа служебные параметры.
Поскольку нужно работать с однодорожечными MIDI-файлами без полифонии, нас интересуют только события, связанные с включением и выключением звука и заданием темпа (BPM) композиции. Конвертер в итоге получается не сильно страшный.
Высота звука задается не сочетанием ноты и октавы, а в виде целого числа. Октаву определяем как целую часть от деления на 12, а ноту — как остаток.
Длительность звука (и тут проявляется гениальность инженеров, что придумали MIDI), задается не в миллисекундах, а в тиках внутреннего осцилятора. Зная, сколько тиков на удар (ticks per beat) задано в свойствах файла, можно посчитать, какую длительность имеет нота в принятой нами нотации. В попытках найти объяснение, зачем так странно, наткнулся на аргументацию: «Если вам нужно сделать ноту длиной 2,743 секунды, не влезающюю в размер, то в MIDI все получится!». С таким и не поспоришь ведь.
А теперь слайды
Конвертим MIDI в прошивку, билдим и заливаем на девайс. Корпус опциональный, для души.