[Python, Программирование] Превращаем клавиатуру в пианино с помощью python
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Как-то заинтересовался я теорией музыки. Но пианино, увы, у меня нет, поэтому я отправился в поиски программы со следующий функционалом: после нажатия на кнопку звучит определенная нота. Сперва я посмотрел высокопрофессиональные программы, но в них слишком, уж слишком много функций. И это очень хорошо, но на текущем моменте моей жизни мне это попросту ненужно. Это будет только мешать и отвлекать. В программах с меньшим функционалом максимально неудобный интерфейс. Потому я решил просто написать такую программу сам. Подробности под катом.Немножко о MIDI.MIDI - стандарт цифровой звукозаписи на формат обмена данными между электронными музыкальными инструментами. Это отдельный большой мир, который заслуживает отдельного разговора. Но нам необходимо знать лишь некоторые правила:1) В каждом файле midi есть неограниченное количество треков, которые запускаются одновременно.2) В каждом треке хранятся определенные команды для синтезатора. Например, noteon – включить определенную ноту; noteoff – выключить определенную ноту; change_program – изменить инструмент, control_change – изменение настроек, влияющих на воспроизведение нот, их смену, и тп. Все команды можно посмотреть здесь.3) Каждая команда характеризуется несколькими параметрами: значение – это, например, номер ноты, номер инструмента и т.п; время от прошлой команды, через которое необходимо выполнить эту команду; номер канала (всего их 16), в котором играет данная нота или применяется соответствующая настройка, или изменяется инструмент. Если не включена полифония, то в канале не может звучать две одинаковые ноты одновременно.Запись MIDI-файлов с помощью Mido.Mido – это библиотека на python, созданная для работы с MIDI-сообщениями и портами. Установка.Классический пример прочтения файла:
from mido import MidiFile
mid = MidiFile('song.mid')
for i, track in enumerate(mid.tracks):
print('Track {}: {}'.format(i, track.name))
for msg in track:
print(msg)
Классический пример создания файла:
from mido import Message, MidiFile, MidiTrack, second2tick
mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)
time = int(second2tick(0.1, 480, 500000))
for i in range(100):
track.append(Message('program_change', program=12, time=0))
track.append(Message('note_on', note=64, velocity=64, time=time))
track.append(Message('note_off', note=64, velocity=64, time=time))
mid.save('new_song.mid')
Обратите внимание на параметр «time». Поподробней можно прочитать здесь.Обработка событий клавиатуры c keyboard.Классический пример:
import keyboard
def hook(key):
if key.event_type == "down":
print("{} press".format(key.name))
if key.event_type == "up":
print("{} release".format(key.name))
keyboard.hook(hook)
keyboard.wait("esc")
Словарь {key: note} можно сделать так (начинается с малой октавы):
import keyboard
keys = {}
note = 48
def hook(key):
global note
if key.event_type == "down":
if key.name != "esc":
keys.update({key.name: note})
note += 1
if key.event_type == "up":
if key.name == "esc":
print(keys)
keyboard.hook(hook)
keyboard.wait()
Воспроизведения нот в реальном времени с помощью mido.Сперва надо установить python-rtmidi.Получаем список портов (у меня всего один):
>>> mido.get_output_names()
['Microsoft GS Wavetable Synth 0']
При нажатии на клавишу передаем порту сообщение о включении или выключении ноты:
import keyboard
import mido
port = mido.open_output('Microsoft GS Wavetable Synth 0')
keys = keys = {'1': 48, '2': 49, '3': 50, '4': 51, '5': 52, '6': 53, '7': 54, '8': 55, '9': 56, '0': 57, '-': 58, '=': 59, 'q': 60, 'w': 61, 'e': 62, 'r': 63, 't': 64, 'y': 65, 'u': 66, 'i': 67, 'o': 68, 'p': 69, '[': 70, ']': 71, 'a': 72, 's': 73, 'd': 74, 'f': 75, 'g': 76, 'h': 77, 'j': 78, 'k': 79, 'l': 80, ';': 81, "'": 82, 'enter': 83}
pressed_keys = {key: False for key in keys.keys()}
def hook(key):
if key.event_type == "down":
if key.name in keys:
if not pressed_keys[key.name]:
port.send(mido.Message('note_on', note=keys[key.name]))
pressed_keys[key.name] = True
if key.event_type == "up":
if key.name in keys:
port.send(mido.Message('note_off', note=keys[key.name]))
pressed_keys[key.name] = False
keyboard.hook(hook)
keyboard.wait()
Но у этого способа есть одна проблема – качество звучания. Да и превратить midi в wav просто так нельзя.Воспроизведения нот в реальном времени с помощью fluidsynth.Fluidsynth – это бесплатный программный синтезатор.Установка fluidsynth (в Windows):1) Скачайте fluidsynth для Windows и распакуйте в любой папке.2) Добавьте подкаталог «fluidsynth\bin» в свой path. Для этого в поисковой строке напишете «Изменение системных переменных среды», запустите; далее по порядку «Переменные среды», «Path», «Изменить», «Создать» и введите путь к подкаталогу «fluidsynth\bin».3) Скачайте музыкальный шрифт.4) Теперь нужно проверить работоспособность fluidsynth. Скачайте любой midi файл и выполните в консоли «fluidsynth FluidR3_GM.sf2 file_name.mid». Не забудьте перейти в необходимый каталог.Теперь нужно установить pyfluidsynth.1) Скачайте pyfluidsynth (разработка ведется на github) и распакуйте.2) Чтобы додуматься до этого шага мне пришлось потратить 1.5 дня (еще один намек на то, чтобы нормально выучить язык, а не с помощью статей в интернете). Перейдите в каталог «fluidsynth\bin» и найдите там файл «libfluidsynth-3.dll» (Быть может, у вас другая цифра). Теперь откройте файл «fluidsynth.py» в каталоге «pyfluidsynth», найдите строчку «lib = find_library('fluidsynth') or…» (она должна быть в начале) и поменяйте «fluidsynth» или любой другой аргумент на «libfluidsynth-3.dll» (У вас может быть другая цифра).3) В каталоге «pyfluidsynth» выполните команду «py setup.py install». После чего данный каталог можно удалить.Также может потребоваться установить numpy.Классический пример:
import time
import fluidsynth
fs = fluidsynth.Synth()
fs.start()
sfid = fs.sfload("FluidR3_GM.sf2")
fs.program_select(0, sfid, 0, 0)
for i in range(10):
fs.noteon(0, 60, 30)
fs.noteon(0, 67, 30)
fs.noteon(0, 76, 30)
time.sleep(1.0)
fs.noteoff(0, 60)
fs.noteoff(0, 67)
fs.noteoff(0, 76)
time.sleep(1.0)
fs.delete()
Соединяем с keyboard:
import keyboard
import mido
import fluidsynth
fs = fluidsynth.Synth()
fs.start()
sfid = fs.sfload("FluidR3_GM.sf2")
fs.program_select(0, sfid, 0, 41)
keys = {'1': 48, '2': 49, '3': 50, '4': 51, '5': 52, '6': 53, '7': 54, '8': 55, '9': 56, '0': 57, '-': 58, '=': 59, 'q': 60, 'w': 61, 'e': 62, 'r': 63, 't': 64, 'y': 65, 'u': 66, 'i': 67, 'o': 68, 'p': 69, '[': 70, ']': 71, 'a': 72, 's': 73, 'd': 74, 'f': 75, 'g': 76, 'h': 77, 'j': 78, 'k': 79, 'l': 80, ';': 81, "'": 82, 'enter': 83}
pressed_keys = {key: False for key in keys.keys()}
def hook(key):
if key.event_type == "down":
if key.name in keys:
if not pressed_keys[key.name]:
fs.noteon(0, keys[key.name], 127)
pressed_keys[key.name] = True
if key.event_type == "up":
if key.name in keys:
fs.noteoff(0, keys[key.name])
pressed_keys[key.name] = False
keyboard.hook(hook)
keyboard.wait()
Из midi в wav.Выполните в консоли:
fluidsynth -F melody.wav FluidR3_GM.sf2 melody.mid
Спасибо за прочтение статьи. Удачи!
===========
Источник:
habr.com
===========
Похожие новости:
- [Информационная безопасность, Разработка веб-сайтов, PHP, Программирование] Слабые места PHP: думай как хакер
- [Программирование, PowerShell, Разработка под Windows] Если вы пишете код в Windows, вы заслуживаете лучшего терминала (перевод)
- [Программирование, Разработка игр, DIY или Сделай сам, Игры и игровые приставки, Визуальное программирование] Признайтесь: вы в этом не ориентируетесь
- [Программирование, Научно-популярное] Языки программирования с однобуквенным названием (перевод)
- [Программирование, Совершенный код] Золотой век программирования окончен? (перевод)
- [JavaScript, Программирование, Разработка игр, Canvas, Математика] Есть ли жизнь после жизни?
- [Python, Математика, Машинное обучение, Физика] Применение машинного обучения к кинетике ядерных реакторов (перевод)
- [Python, API, SQLite] Подключаем Sqlite3 к Telegram боту
- [Высокая производительность, Информационная безопасность, Программирование, Будущее здесь] Безопасность в масштабе HighLoad — магия или realtime?
- [Программирование, Конференции] Фронтенд и современные приложения. Можно без ошибок? Узнаем на DUMP-2021
Теги для поиска: #_python, #_programmirovanie (Программирование), #_python, #_fluidsynth, #_mido, #_midi, #_python, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:14
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Как-то заинтересовался я теорией музыки. Но пианино, увы, у меня нет, поэтому я отправился в поиски программы со следующий функционалом: после нажатия на кнопку звучит определенная нота. Сперва я посмотрел высокопрофессиональные программы, но в них слишком, уж слишком много функций. И это очень хорошо, но на текущем моменте моей жизни мне это попросту ненужно. Это будет только мешать и отвлекать. В программах с меньшим функционалом максимально неудобный интерфейс. Потому я решил просто написать такую программу сам. Подробности под катом.Немножко о MIDI.MIDI - стандарт цифровой звукозаписи на формат обмена данными между электронными музыкальными инструментами. Это отдельный большой мир, который заслуживает отдельного разговора. Но нам необходимо знать лишь некоторые правила:1) В каждом файле midi есть неограниченное количество треков, которые запускаются одновременно.2) В каждом треке хранятся определенные команды для синтезатора. Например, noteon – включить определенную ноту; noteoff – выключить определенную ноту; change_program – изменить инструмент, control_change – изменение настроек, влияющих на воспроизведение нот, их смену, и тп. Все команды можно посмотреть здесь.3) Каждая команда характеризуется несколькими параметрами: значение – это, например, номер ноты, номер инструмента и т.п; время от прошлой команды, через которое необходимо выполнить эту команду; номер канала (всего их 16), в котором играет данная нота или применяется соответствующая настройка, или изменяется инструмент. Если не включена полифония, то в канале не может звучать две одинаковые ноты одновременно.Запись MIDI-файлов с помощью Mido.Mido – это библиотека на python, созданная для работы с MIDI-сообщениями и портами. Установка.Классический пример прочтения файла: from mido import MidiFile
mid = MidiFile('song.mid') for i, track in enumerate(mid.tracks): print('Track {}: {}'.format(i, track.name)) for msg in track: print(msg) from mido import Message, MidiFile, MidiTrack, second2tick
mid = MidiFile() track = MidiTrack() mid.tracks.append(track) time = int(second2tick(0.1, 480, 500000)) for i in range(100): track.append(Message('program_change', program=12, time=0)) track.append(Message('note_on', note=64, velocity=64, time=time)) track.append(Message('note_off', note=64, velocity=64, time=time)) mid.save('new_song.mid') import keyboard
def hook(key): if key.event_type == "down": print("{} press".format(key.name)) if key.event_type == "up": print("{} release".format(key.name)) keyboard.hook(hook) keyboard.wait("esc") import keyboard
keys = {} note = 48 def hook(key): global note if key.event_type == "down": if key.name != "esc": keys.update({key.name: note}) note += 1 if key.event_type == "up": if key.name == "esc": print(keys) keyboard.hook(hook) keyboard.wait() >>> mido.get_output_names()
['Microsoft GS Wavetable Synth 0'] import keyboard
import mido port = mido.open_output('Microsoft GS Wavetable Synth 0') keys = keys = {'1': 48, '2': 49, '3': 50, '4': 51, '5': 52, '6': 53, '7': 54, '8': 55, '9': 56, '0': 57, '-': 58, '=': 59, 'q': 60, 'w': 61, 'e': 62, 'r': 63, 't': 64, 'y': 65, 'u': 66, 'i': 67, 'o': 68, 'p': 69, '[': 70, ']': 71, 'a': 72, 's': 73, 'd': 74, 'f': 75, 'g': 76, 'h': 77, 'j': 78, 'k': 79, 'l': 80, ';': 81, "'": 82, 'enter': 83} pressed_keys = {key: False for key in keys.keys()} def hook(key): if key.event_type == "down": if key.name in keys: if not pressed_keys[key.name]: port.send(mido.Message('note_on', note=keys[key.name])) pressed_keys[key.name] = True if key.event_type == "up": if key.name in keys: port.send(mido.Message('note_off', note=keys[key.name])) pressed_keys[key.name] = False keyboard.hook(hook) keyboard.wait() import time
import fluidsynth fs = fluidsynth.Synth() fs.start() sfid = fs.sfload("FluidR3_GM.sf2") fs.program_select(0, sfid, 0, 0) for i in range(10): fs.noteon(0, 60, 30) fs.noteon(0, 67, 30) fs.noteon(0, 76, 30) time.sleep(1.0) fs.noteoff(0, 60) fs.noteoff(0, 67) fs.noteoff(0, 76) time.sleep(1.0) fs.delete() import keyboard
import mido import fluidsynth fs = fluidsynth.Synth() fs.start() sfid = fs.sfload("FluidR3_GM.sf2") fs.program_select(0, sfid, 0, 41) keys = {'1': 48, '2': 49, '3': 50, '4': 51, '5': 52, '6': 53, '7': 54, '8': 55, '9': 56, '0': 57, '-': 58, '=': 59, 'q': 60, 'w': 61, 'e': 62, 'r': 63, 't': 64, 'y': 65, 'u': 66, 'i': 67, 'o': 68, 'p': 69, '[': 70, ']': 71, 'a': 72, 's': 73, 'd': 74, 'f': 75, 'g': 76, 'h': 77, 'j': 78, 'k': 79, 'l': 80, ';': 81, "'": 82, 'enter': 83} pressed_keys = {key: False for key in keys.keys()} def hook(key): if key.event_type == "down": if key.name in keys: if not pressed_keys[key.name]: fs.noteon(0, keys[key.name], 127) pressed_keys[key.name] = True if key.event_type == "up": if key.name in keys: fs.noteoff(0, keys[key.name]) pressed_keys[key.name] = False keyboard.hook(hook) keyboard.wait() fluidsynth -F melody.wav FluidR3_GM.sf2 melody.mid
=========== Источник: habr.com =========== Похожие новости:
Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:14
Часовой пояс: UTC + 5