Não faço programação MIDI há anos, mas sua ideia fundamental é muito sólida (sem trocadilhos).
MIDI é um fluxo de "eventos" (ou "mensagens"), dois dos mais fundamentais sendo "note on" e "note off" que carregam com eles o número da nota (0 = C cinco oitavas abaixo do meio C, através de 127 = G cinco oitavas acima do G acima do meio C, em semitons). Esses eventos carregam um número de "velocidade" em teclados sensíveis à velocidade ("sensíveis ao toque"), com uma força de (você adivinhou) entre 0 e 127.
Entre a velocidade, as cordas e os pedais, acho que você poderia criar uma interface de "digitação" bastante boa para o teclado do piano. A gravação em particular pode ser uma técnica muito poderosa - como mencionei nos comentários, é por isso que os estenógrafos comuns podem usar uma máquina de estenótipo para acompanhar as pessoas conversando por horas seguidas, quando até os datilógrafos de primeira linha não ' por um longo período de tempo através de teclados normais no estilo de máquinas de escrever. Como na estenografia de máquinas, você precisa de um "dicionário" dos significados dos acordes e das seqüências de acordes. (Você pode dizer que eu costumava trabalhar no lado do software da estenografia da máquina?)
Para fazer isso, as peças fundamentais são:
- Recebendo entrada MIDI. Não tente fazer isso sozinho, use uma biblioteca. Edit : Aparentemente, a Java Sound API suporta MIDI , incluindo o recebimento de eventos de controladores MIDI. Legal. Esta página também pode ser útil.
- Convertendo esses dados nas teclas que você deseja enviar, por exemplo, através do dicionário que mencionei acima.
- Saída das teclas digitadas no computador.
Para ser o mais amplamente compatível com o software, você teria que escrever isso como um driver de dispositivo do teclado. Este é um plug-in para o sistema operacional que serve como fonte para eventos do teclado, conversando com o hardware subjacente (no seu caso, o teclado do piano). Para Windows e Linux, você provavelmente vai querer usar C para isso.
No entanto, como você está apenas gerando pressionamentos de tecla (sem tentar interceptá-los, o que eu estava tentando fazer anos atrás), você poderá usar os recursos que o sistema operacional tiver para enviar pressionamentos de teclas artificiais. O Windows tem uma interface para fazer isso (provavelmente várias, a única em que estou pensando é, SendInput
mas sei que há alguma interface de "diário" que faz algo semelhante) e tenho certeza que outros sistemas operacionais também o fazem. Isso pode ser suficiente para seus propósitos - é onde eu começaria, porque a rota do driver de dispositivo será estranha e você provavelmente precisará usar uma linguagem diferente do Java. (Sou um grande fã de Java, mas as interfaces que os sistemas operacionais usam para conversar com os drivers de dispositivo tendem a ser mais facilmente consumidas via C e similares.)
Atualização : Mais informações sobre o "dicionário" de acordes para pressionamentos de teclas:
Basicamente, o dicionário é um trie (obrigado, @Adam) que pesquisamos com a correspondência de prefixo mais longo. Detalhes:
Na estenografia da máquina, o estenógrafo escreve pressionando várias teclas na máquina de estenótipo ao mesmo tempo e, em seguida, liberando todas elas. Eles chamam isso de "toque" do teclado; é como tocar um acorde no piano. Os traços freqüentemente (mas nem sempre) correspondem a uma sílaba da língua falada. Assim como as sílabas, às vezes um toque (acorde) tem significado por si só, outras vezes ele só tem significado combinado com os movimentos seguintes. (Pense "bom" vs. "bom" seguido de "tchau"). Embora eles sejam fortemente influenciados pela escola em que estudaram, cada estenógrafo terá seu próprio "dicionário" de quais traços eles usam para significar o que, um dicionário que eles continuamente aprimorarão ao longo de suas vidas profissionais. O dicionário terá entradas em que a parte estenográfica ("steno", para abreviar) tem um curso ou vários tempos. Freqüentemente, haverá várias entradas com o mesmo golpe inicial, diferenciadas pelo comprimento e pelos movimentos subsequentes. Por exemplo (e eu não usarei o steno real aqui, apenas espaços reservados), pode haver estas entradas:
A = alfa
A / B = alfabeto
A / B / C = alfabético
A / C = ar condicionado
B = abelha
B / C = porque
C = mar
D = cachorro
D / D = Dee Dee
(Essas cartas não devem ser notas musicais, apenas marcadores abstratos.)
Observe que A
inicia várias entradas e também como a tradução de um C
traçado depende se você já viu um A
, a B
ou se está começando de novo.
Observe também que (embora não seja mostrado na amostra muito pequena acima), pode haver várias maneiras de "reproduzir" a mesma palavra ou frase, em vez de apenas uma. Os estenógrafos fazem isso para facilitar o fluxo de uma palavra anterior para a seguinte, dependendo da posição da mão. Existe uma analogia óbvia com a música, e você pode usar isso para tornar a digitação mais parecida com a música, tanto para impedir que isso afete negativamente a execução do seu piano quanto para maximizar a probabilidade de realmente ajudar com o RSI.
Ao traduzir steno em texto padrão, novamente usamos uma pesquisa de "correspondência de prefixo mais longo": o algoritmo de tradução começa com o primeiro toque já escrito e procura entradas que começam com esse toque. Se houver apenas uma entrada e for um toque, poderemos dizer com segurança "essa é a entrada a ser usada", produzir o texto correspondente e começar novamente com o próximo toque. Mas o mais provável é que esse traçado inicie várias entradas de diferentes comprimentos. Então, olhamos para o próximo traço e vemos se há entradas que começam com esses dois traços em ordem; e assim por diante até conseguirmos uma partida.
Portanto, com o dicionário acima, suponha que vimos essa sequência:
ACBBCABCABD
Veja como o traduziríamos:
A
é o início de três entradas de comprimentos variados; veja o próximo golpe:C
A/C
corresponde apenas a uma entrada; saída "ar condicionado" e começar de novo com o próximo curso:B
B
inicia duas entradas; veja o próximo golpe:B
B/B
não inicia nada; pegue a correspondência anterior mais longa ( B
) e produza que ("bee")
- Tendo output
B
= "bee", ainda temos um B
acidente vascular cerebral em nosso buffer. Ele inicia duas entradas, então veja o próximo traço:C
B/C
corresponde a uma entrada; output "because" e comece do zero com o próximo golpe:A
A
inicia três entradas; veja o próximo golpe:B
A/B
inicia duas entradas; veja o próximo golpe:C
A/B/C
corresponde apenas a uma entrada; output "alfabético" e comece do zero com o próximo toque:A
A
inicia três entradas; veja o próximo golpe:B
A/B
inicia duas entradas; veja o próximo golpe:D
A/B/D
não corresponde a nada, portanto, pegue a correspondência anterior mais longa ( A/B
) e use-a para gerar "alfabeto". Isso nos deixa D
ainda no buffer.
D
inicia duas entradas, para que normalmente analisássemos o próximo golpe - mas processamos todos os movimentos, então considere-o isoladamente. Isoladamente, ele se traduz como "cachorro", então é isso.
Aspectos acima para observação:
- Você tem um buffer de traços que leu, mas ainda não traduziu.
- Você sempre deseja combinar o maior número de traços com uma única entrada possível.
A/B
deve ser traduzido como "alfabeto", não "alfa" e "abelha".
- (Não mostrado acima) Você pode ter sequências de traços que não pode traduzir, porque elas não correspondem a nada no dicionário. (As pessoas Steno usam o substantivo "não traduzido" - por exemplo, em nosso dicionário, os traços
E
seriam "não traduzidos".)
- (Não mostrado acima) Algumas teorias do steno permitem que o mesmo conjunto de traços signifique mais de uma coisa, com base em um contexto mais amplo. Os steno chamam esses "conflitos". Você provavelmente deseja proibi-los em seu projeto e, de fato, quando o steno costumava ser traduzido manualmente pelo estenógrafo, os conflitos eram bons porque eles sabiam exatamente onde na sentença estavam qual era a escolha certa, mas com o aumento da tradução automática, surgiram teorias de steno sem conflito especificamente para evitar a necessidade de passar pelo texto traduzido resultante e "consertar" os conflitos.
- Traduzir em tempo real (o que você faria) significa que, se você receber uma correspondência parcial, vai querer se apegar a ela enquanto aguarda o próximo acorde - mas provavelmente apenas com um tempo limite, no momento em que deseja traduza o que você tem no buffer da melhor maneira possível. (Ou talvez você não queira um tempo limite; a decisão é sua.)
- Provavelmente é melhor ter um derrame que diga "desconsidere o derrame anterior"
- Provavelmente é melhor ter um golpe que diga "limpe completamente o buffer sem emitir nada"