FreePiano — Виртуальная MIDI-клавиатура
Приложение для практики и улучшения навыков игры на фортепиано с компьютерной клавиатуры или MIDI-клавиатуры любым VST-инструментом.
Приложение для практики и улучшения навыков игры на фортепиано с компьютерной клавиатуры или MIDI-клавиатуры любым VST-инструментом.
Характеристики:
- поддержка DirectSound, WASAPI, ASIO и MIDI;
- поддержка инструментов VST 2;
- полностью настраиваемая клавиатура;
- запись музыки и экспорт в MP4.
Поскольку это портативная программа, она не оставляет никаких следов в реестре Windows.
Её можно скопировать на любой USB-накопитель или в другое устройство и брать с собой всякий раз, когда нужно играть на виртуальном пианино, без необходимости выполнять установку.
FreePiano отличается чистым и интуитивно понятным интерфейсом, который позволяет выполнять большинство операций с минимальными усилиями.
Программа отображает клавиши, которые необходимо нажать для воспроизведения звука, и автоматически выявляет соответствующие клавиши пианино.
Более того, можно записать сеанс воспроизведения и заставить утилиту воспроизводить его, импортировать данные из файлов FPM или LYT, прослушивать аудиофайл и просматривать, как он воспроизводится правильно, а также экспортировать записанный элемент в формат файла MP4 или WAV.
Одна из главных функций этого инструмента в том, что он позволяет назначить для каждой клавиши ноту, октаву и канал.
Когда дело доходит до настроек конфигурации, можно устанавливать специальные параметры с точки зрения скорости, октавы, канала, аудиоустройства, громкости и скорости воспроизведения.
Характеристики
Virtual MIDI Piano Keyboard
Rating: 1.0/5 (Total Votes: 1)
Виртуальный MIDI-клавиатура фортепиано (или VMPK для краткости) является открытым исходным кодом, свободно распространяться и мультиплатформенный графический программный проект разработан с нуля, чтобы действовать как самостоятельный инструмент MIDI-контроллера. Программное обеспечение работает на всех основных операционных систем и может быть использовано для привода MIDI синтезатор, несмотря на тот факт, что она не может быть использована для получения звуков.
Основные характеристики включают в себя поддержку вождения программного обеспечения или аппаратных средств MIDI синтезаторы, поддержка вождения внутренние или внешние MIDI синтезаторы, поддержку мыши и клавиатуры периферийных устройств, которые могут быть использованы, чтобы играть MIDI отмечает, поддержка просмотра играет MIDI отмечает, другого MIDI проигрыватель файлов или инструмент, поддержка для получения MIDI события, поддержка MIDI генерации события, а также современный графический интерфейс пользователя, написанный на Qt.
в дополнение к выше, программное обеспечение имеет буквенно-цифровой раскладки клавиатуры, которая может быть легко настроить с помощью графического интерфейса (XML-файлы используются для хранения настроек), поддержка французского, испанского и немецкого раскладки клавиатуры, а также способность Чтобы отправить контроллеры и программные изменения к MIDI синтезатора. Все MIDI функциями ввода / вывода получают питание от кросс-платформенной рамках Голень РТ.
Содержит определения для различных устройств и стандартов
Обратите внимание, что виртуальный MIDI-клавиатура фортепиано может дать определения для различных устройств и стандартов, как INS-файлы, которые могут быть записаны с помощью популярных приложений, таких как QTractor и TSE3.
Под капотом, доступности и поддерживаемых ОС
Приложение написано в языке программирования С ++, используя инструментарий Qt GUI для своей красивой графическим пользовательским интерфейсом. Виртуальный MIDI-клавиатура фортепиано является обеспечение кросс-платформенный, поддерживает на GNU / Linux, Microsoft Windows и операционных систем Mac OS X. На GNU / Linux, является, и Rsquo, S доступен для скачивания как универсальных инсталляторов в формате .run файла, а также в качестве источника архива
Что нового в этой версии:
- Исправлены ALSA (Linux) и Windows драйвера ввода (предоставляемые ГОЛЕНЬ 1.0.1 библиотеки)
- упаковывали с использованием Qt 5.5.0 Каркасы
- Исправлена билет # 27: сохранить клавиатуры карты с расширением XML по умолчанию
- Исправлена билет # 29: дисплей событие ввода noteon со скоростью = 0 noteoff
исправления - Цвет управления палитры
- Обновлен русский и сербский перевод
Что нового в версии 0.6.0:
- Qt5 миграция завершена. XCB замены библиотеки X11 на Linux / Unix
- RtMIDI заменен ОБРЕЗЬ-RT с подключаемыми движков:. ALSA послед, ОСС, Windows, Mac OSX, Сеть и FluidSynth
- Ticket # 39: клавиатура может начинаться в любой ноте
- Разрешить настроить любое количество ключей, а не полный октав
- Новые переводы: Сербский и галисийский
Неистовые потуги или как поиграть на midi-клавиатуре в стиле linux-way
При использовании KeyStation c LMMS или любым другим синтезирующим звук софтом в системе Windows, проблем не возникает, там всё автоматически подключается без необходимости дополнительных действий и настроек. Но поскольку я являюсь фанатом Linux, то по максимуму стараюсь вертеться исключительно в приделах OpenSource / Freeware программного обеспечения. По этому Windows-way когда всё начинает работать с минимальными усилиями это не про меня.
Собственно небольшая предыстория
Сначала я пытался подключить midi-клавиатуру с помощью родных средств системы, но результата добиться не получилось. Потом по относительно древним инструкциям устанавливал пакеты Ubuntu-Studio, но мои отношения с аудиоподсистемой Jack не сложились. Но в моментах попытки всё настроить периодически поглядывал на то что устройство всё-таки определяется с помощью утилиты lsusb и наличии устройства в директории /dev в которой мой миди-девайс определялся как dmmidi1 ( Естественно что это именно она, определял методом втыка-вытыка USB провода в хаб ). Из большого любопытства я открыл этот файлик с помощью cat, и обнаружил что при взаимодействии с девайсом, в этот файлике пролетают байтики. Тут у меня и проскочила мысль, что если у меня не складываются отношения с «родными» аудио подсистемами линуха, то стоит попробовать провзаимодействовать с клавиатурой напрямую. Да бы разобраться с пролетающими там последовательностями накидал простейший код чтения потока данных из файла —
try < var fis = new FileInputStream("/dev/" + MIDI_DEVICE_NAME); int data = 0; int counter = 0; boolean playOn; while(data != -1) < data = fis.read(); System.out.printf("--- %d --- %s --- ", ++counter, (char) data); System.out.println(data); >fis.close(); > catch (IOException io)
Произвел следующие нажатия по клавиатуре —
- С1 х2 быстрое сильное нажатие,
- С1 х1 cильное долгое нажатие
- D1 х1 быстрое нажатие
- E1 x1 быстрое нажатие
Где первая буква это нота, а рядом стоящая цифра это октава ( относительно расположения на клавиатуре) ( Для получения более точных результатов громкость на клавиатуре стоит на максимум, отклонение ( хоть как потом выяснилось это не влияет )
По итогу в аутпуте терминала я получил следующее —
Counter Char Byte --- 1 --- $ --- 36 --- 2 --- j --- 106 --- 3 --- --- 146 --- 4 --- $ --- 36 --- 5 --- --- 0 --- 6 --- --- 146 --- 7 --- $ --- 36 --- 8 --- g --- 103 --- 9 --- --- 146 --- 10 --- $ --- 36 --- 11 --- --- 0 --- 12 --- --- 146 --- 13 --- $ --- 36 --- 14 --- L --- 76 --- 15 --- --- 146 --- 16 --- $ --- 36 --- 17 --- --- 0 --- 18 --- --- 146 --- 19 --- & --- 38 --- 20 --- Z --- 90 --- 21 --- --- 146 --- 22 --- & --- 38 --- 23 --- --- 0 --- 24 --- --- 146 --- 25 --- ( --- 40 --- 26 --- b --- 98 --- 27 --- --- 146 --- 28 --- ( --- 40 --- 29 --- --- 0
( Логи специально разбил пустыми строками для удобности чтения )
Зная какие клавиши и как нажимались, можно догадаться что — за одно нажатие (имеется виду полное совершённое действие — клавиша зажата и в дальнейшем отпущена ) мы в среднем получаем по 6-байт полезной информации, от этого и будем отталкиваться. (в логе я уже вручную специально разбил информацию по 6 строк да бы было проще читать) — Значение 112 как я понял — является чем-то типа заголовка канала, поэтому будем отталкиваться от него — Следующим байтом мы видим значения 36, 38, 40, что вполне логично, так как между нотами С и D, D и E есть ещё и полутона С# и D# соответственно ( Черный клавиши на клавиатуре ) — Третьим же байтом мы получаем силу удара по клавише, иначе же — громкость с которой нужно воспроизводить ноту от 1 до 127, и 0 когда клавиша отпущена.
97-119 идентификатор канала
Зная что в поставке с Java есть неплохой инструментарий для работы с midi возвращаемся к магии «прогрузирования«. —
Код получившейся программы
package dev.xred.ServlessMidiSynth; import java.io.*; import java.util.HashMap; public class ServerLessMidiSynthesizer < private static final String MIDI_DEVICE_NAME = "dmmidi1"; static HashMapplaying = new HashMap<>(); public static void main(String[] args) throws IOException < SimpleLogger logger = new SimpleLogger(ServerLessMidiSynthesizer.class); try(var fis = new FileInputStream("/dev/" + MIDI_DEVICE_NAME); var buf = new BufferedInputStream(fis))< byte[] in = buf.readNBytes(3); while(loop) < NotePlayer notePlayer = null; Thread thread = null; logger.print((in[2] != 0 ? "pull in " : "pull out") + in[0] + " " + in[1] + " " + in[2]); // Cмотрим является ли новый набор байт командой играть ноту или же терминальной командой if(in[2] != 0 )< // Играем ноту notePlayer = new NotePlayer(in[1], in[2]); thread = new Thread(notePlayer); thread.start(); playing.put(in[1], thread); >else < //Прекращаем воспроизведение ноты thread = playing.get(in[1]); if(thread != null)< thread.interrupt(); thread.stop(); playing.remove(in[1]); >> in = buf.readNBytes(3); > > catch (IOException io) < logger.print(io.getLocalizedMessage()); >> >
package dev.xred.ServlessMidiSynth; import javax.sound.midi.*; public class NotePlayer implements Runnable < private int note; private int velocity; public boolean playOn; public NotePlayer(int note, int velocity)< this.note = note; this.velocity = velocity; >public int getNote() < return note; >public int getVelocity() < return velocity; >@Override public void run() var midiPlayer = MidiPlayer.getInstance(); var mc = midiPlayer.getMidiChannel(); velocity += 50; mc.noteOn(note, velocity); // Стоит тут не просто так, нужен для того чтобы - // выдержать длинну играемой ноты while(!Thread.interrupted()); mc.noteOff(note); > >
package dev.xred.ServlessMidiSynth; import javax.sound.midi.*; public class MidiPlayer < private int lastOutputed = 0; private static MidiPlayer instance; private MidiChannel[] mChannels; private Instrument[] instr; // Полный список инструментов можно получить пройдясь по массиву instr private int instrumentNum = 0; private MidiPlayer()< Synthesizer midiSynth = null; try < midiSynth = MidiSystem.getSynthesizer(); midiSynth.open(); >catch (MidiUnavailableException e) < e.printStackTrace(); >instr = midiSynth.getDefaultSoundbank().getInstruments(); mChannels = midiSynth.getChannels(); if(midiSynth.loadInstrument(instr[instrumentNum])) System.out.println("instrument - " + instrumentNum + "has been loaded");; > public static MidiPlayer getInstance() < if(instance == null) instance = new MidiPlayer(); return instance; >public MidiChannel getMidiChannel() < // Не большой костыль - пришлось раскидать звук на несколько каналов, т.к. // при тестах(игре) почему-то происходило переполнение канала // из-за чего вылетало исключение if (lastOutputed >3) lastOutputed = 0; return mChannels[lastOutputed++]; > >
FileInputStream решил использовать только как промежуточную стадию, и грузить все через BufferedStream. Когда мы получили доступ к «буферному читале» забираем сразу по 3 байта которые нам так необходимы. Если забирать по одному, то кода для обработки будет намного больше и работать будет намного медленнее, чего нам по максимум нужно избегать. В плане обработчика начала и конца воспроизведения ноты сделал отдельный класс NotePlayer реализующий Runnable, куда скидываю в конструктор параметры т.е. 2 и 3 байт. Запихиваю всё в новый поток, а уже поток в HashMap для хранения и слежения за ним, и параллельно с чтением смотрю, проигрывается ли нота, и если да, при нуле в 3-ем байте вызываю interupt().
Собственно завершив «колдовать» получаем готовый результат и возможность насладиться игрой на инструменте.
P.S. С помощью ALSA уже позже получилось прикрутить клавиатуру к LMMS и Reaper, просто не сразу дошли некоторые вещи.