Я не занимался программированием MIDI годами, но ваша фундаментальная идея очень здравая (без каламбура).
MIDI - это поток «событий» (или «сообщений»), два из самых фундаментальных из которых - «примечание включено» и «примечание выключено», которые несут с собой номер ноты (0 = C на пять октав ниже среднего C, через 127 = G на пять октав выше G над серединой C, в полутонах). Эти события несут число «скорость» на клавиатурах, которые чувствительны к скорости («чувствительны к прикосновению»), с силой (как вы уже догадались) между 0 и 127.
Между скоростью, звуком и педалями, я думаю, вы могли бы придумать довольно неплохой «набор текста» для клавиатуры пианино. В частности, запись может быть очень мощной техникой - как я уже упоминал в комментариях, именно поэтому рядовые стенографисты могут использовать машину с использованием стенотипа, чтобы не отставать от людей, разговаривающих часами подряд, даже если машинистки высшего звена этого не сделают. не может быть в течение любого промежутка времени с помощью обычных клавиатур в стиле пишущей машинки. Как и в случае с машинной стенографией, вам понадобится «словарь» значений аккордов и последовательностей аккордов. (Можете ли вы сказать, что я работал в программной части машинной стенографии?)
Чтобы сделать это, основные части:
- Получение MIDI-входа. Не пытайтесь сделать это самостоятельно, используйте библиотеку. Редактировать : Очевидно, Java Sound API поддерживает MIDI , включая получение событий от контроллеров MIDI. Круто. Эта страница также может быть полезной.
- Преобразование этих данных в нажатия клавиш, которые вы хотите отправить, например, через словарь, который я упомянул выше.
- Вывод нажатий клавиш на компьютер.
Чтобы быть наиболее совместимым с программным обеспечением, вы должны написать это как драйвер устройства клавиатуры. Это плагин для операционной системы, который служит источником событий клавиатуры, общаясь с базовым оборудованием (в вашем случае, клавиатурой пианино). Для Windows и Linux вы, вероятно, захотите использовать C для этого.
Однако, поскольку вы просто генерируете нажатия клавиш (не пытаясь перехватить их, что я пытался сделать несколько лет назад), вы можете использовать любые функции операционной системы для отправки искусственных нажатий клавиш. В Windows есть интерфейс для этого (возможно, несколько, тот, о котором я думаю, SendInput
но я знаю, что есть какой-то «журнальный» интерфейс, который делает нечто подобное), и я уверен, что другие операционные системы делают то же самое. Этого вполне может быть достаточно для ваших целей - это то, с чего я начну, потому что маршрут драйвера устройства будет неудобным, и вам, вероятно, придется использовать для него другой язык, чем Java. (Я большой поклонник Java, но интерфейсы, которые операционные системы используют для общения с драйверами устройств, как правило, легче использовать через C и тому подобное.)
Обновление : Подробнее о «словаре» аккордов для нажатия клавиш:
По сути, словарь - это три (спасибо, @Adam), который мы ищем с соответствием по длинному префиксу. Подробности:
В машинной стенографии стенографист пишет, нажимая одновременно несколько клавиш на машине стенотипа, затем выпуская их все. Они называют это «ударом» клавиатуры; это как играть аккорд на пианино. Удары часто (но не всегда) соответствуют слогу разговорной речи. Подобно слогам, иногда один удар (аккорд) имеет значение само по себе, в других случаях он имеет значение только в сочетании с последующими штрихами. (Думайте «хорошо» против «хорошо», а затем «пока»). Хотя они будут находиться под сильным влиянием школы, в которой они учились, у каждого стенографа будет свой «словарь» того, какие штрихи они используют для обозначения чего, словарь, который они будут постоянно оттачивать в течение своей трудовой жизни. В словаре будут записи, в которых стенографическая часть (сокращенно «steno») имеет длину одного хода или длину нескольких ходов. Часто будет несколько записей с одинаковым начальным ходом, которые различаются по длине и последующим ударам. Например (и я не буду использовать реальное стено здесь, только заполнители), могут быть эти записи:
A = альфа
A / B = алфавит
A / B / C = буквенный
A / C = кондиционер
B = пчела
B / C = потому что
C = море
D = собака
D / D = Ди Ди
(Эти буквы не предназначены для музыкальных нот, просто абстрактные маркеры.)
Обратите внимание, что A
начинается несколько записей, а также обратите внимание, что способ перевода C
штриха зависит от того, видели ли вы ранее a A
, a B
или вы начинаете заново.
Также обратите внимание, что (хотя это не показано в очень небольшом примере выше), может быть несколько способов «воспроизвести» одно и то же слово или фразу, а не только один. Стенографы делают это, чтобы облегчить переход от предыдущего слова к следующему в зависимости от положения руки. Там есть очевидная аналогия с музыкой, и вы можете использовать ее, чтобы сделать процесс набора текста более похожим на воспроизведение музыки, чтобы не допустить, чтобы это отрицательно сказалось на игре на пианино, и максимально увеличить вероятность того, что это действительно поможет с RSI.
При переводе steno в стандартный текст мы снова используем поиск «поиск по самому длинному префиксу»: алгоритм перевода начинается с первого написанного штриха и ищет записи, начинающиеся с этого штриха. Если есть только одна запись длиной в один штрих, то мы можем с уверенностью сказать «это запись, которую нужно использовать», вывести соответствующий текст, а затем начать заново со следующего удара. Но, скорее всего, этот штрих запускает несколько записей разной длины. Итак, мы смотрим на следующий штрих и видим, есть ли записи, начинающиеся с этих двух штрихов по порядку; и так до тех пор, пока мы не получим совпадение.
Итак, со словарем выше, предположим, что мы видели эту последовательность:
ACBBCABCABD
Вот как мы могли бы перевести это:
A
является началом трех записей различной длины; посмотрите на следующий штрих:C
A/C
соответствует только одной записи; Выведите «кондиционер» и начните заново со следующего хода:B
B
начинается две записи; посмотрите на следующий штрих:B
B/B
ничего не запускается; возьмите самый длинный предыдущий match ( B
) и выведите это ("пчела")
- Имея output
B
= "bee", у нас все еще есть B
штрих в нашем буфере. Он запускает две записи, поэтому посмотрите на следующий штрих:C
B/C
соответствует одной записи; выведите «потому что» и начните заново со следующего удара:A
A
начинается три записи; посмотрим на следующий штрих:B
A/B
начинается две записи; посмотрите на следующий штрих:C
A/B/C
соответствует только одной записи; выведите «буквенный» и начните заново со следующего удара:A
A
начинается три записи; посмотрите на следующий штрих:B
A/B
начинается две записи; посмотрите на следующий штрих:D
A/B/D
ничего не совпадает, поэтому возьмите самый длинный предыдущий match ( A/B
) и используйте его для вывода «алфавита». Это оставляет нас D
в буфере.
D
запускает две записи, поэтому мы обычно просматриваем следующий штрих - но мы обработали все штрихи, поэтому рассмотрим его изолированно. В отдельности это переводится как "собака", поэтому вывод, что.
Аспекты вышесказанного отметить:
- У вас есть буфер штрихов, которые вы прочитали, но еще не перевели.
- Вы всегда хотите сопоставить наибольшее количество ударов с одной записью, которую вы можете.
A/B
следует переводить как «алфавит», а не «альфа» и «пчела».
- (Не показано выше) У вас вполне могут быть последовательности штрихов, которые вы не можете перевести, потому что они не совпадают с чем-либо в словаре. (Люди Steno используют существительное «непереведенный» - например, в нашем словаре штрихи
E
будут «непереведенными».)
- (Не показано выше) Некоторые теории steno допускают, чтобы один и тот же набор штрихов означал более чем одну вещь, основываясь на более широком контексте. Стено люди называют эти «конфликты». Вы, вероятно, хотите запретить их в своем проекте, и на самом деле, когда стенографист переводил steno вручную, конфликты были хорошими, потому что они знали бы только, где в предложении они были, каков был правильный выбор, но с ростом машинного перевода, бесконфликтные теории steno возникли специально, чтобы избежать необходимости просматривать полученный переведенный текст и «исправлять» конфликты.
- Перевод в реальном времени (что вы и делаете) означает, что если вы получите частичное совпадение, вы захотите удержать его в ожидании следующего аккорда - но, вероятно, только до тайм-аута, в этот момент вы бы переведите то, что у вас есть в буфере, как можно лучше. (Или, может быть, вы не хотите тайм-аут; это ваш звонок.)
- Вероятно, лучше всего иметь инсульт, который говорит «не обращать внимания на предыдущий инсульт»
- Вероятно, лучше всего иметь штрих, который говорит: «полностью очистить буфер, ничего не выводя»