私は持っているRSSI問題があり、30 種類のコンピューター キーボードを試しましたが、すべて痛みを感じました。ピアノを弾くことは痛みを引き起こしません。私は 20 年ほどピアノを弾いていますが、痛みはまったくありません。MIDI キーボードから MIDI をキャプチャして、キーボード ストロークを出力する方法があるかどうか知りたいです。私は MIDI についてはまったく知りませんが、この信号をキーストロークに変換する方法についてアドバイスをいただきたいです。
ベストアンサー1
私は何年も MIDI プログラミングをしていませんが、あなたの基本的な考え方は非常にしっかりしています (しゃれではありません)。
MIDI は「イベント」(または「メッセージ」) のストリームであり、最も基本的な 2 つは「ノート オン」と「ノート オフ」で、これらはノート番号 (0 = 中央 C の 5 オクターブ下、127 = 中央 C の G の 5 オクターブ上、半音単位) を伴います。これらのイベントは、速度に敏感な (「タッチ センシティブ」) キーボードの「速度」番号を伴い、その強さは (ご想像のとおり) 0 から 127 までです。
ベロシティ、コード、ペダルを組み合わせれば、ピアノキーボード用のかなり優れた「タイピング」インターフェースが実現できると思います。特にコードは非常に強力なテクニックです。コメントで述べたように、一般の速記者が速記機通常のタイプライター スタイルのキーボードでは、一流のタイピストでも長時間は話し続けることができないのに、何時間も続けて話し続ける人々についていくには、機械速記が必要です。機械速記と同様に、コードの意味とコード シーケンスの「辞書」が必要になります。(私が機械速記のソフトウェア側で働いていたことがわかりますか?)
これを実現するための基本的な要素は次のとおりです。
- MIDI入力の受信。自分でやろうとせず、ライブラリを使用してください。編集:どうやら、Java Sound APIMIDIをサポートMIDI コントローラーからのイベントの受信も含みます。クールですね。このページも役に立つかもしれません。
- そのデータを、たとえば上で述べた辞書を介して、送信したいキーストロークに変換します。
- キーストロークをコンピューターに出力します。
ソフトウェアとの互換性を最も広くするには、これをキーボード デバイス ドライバーとして記述する必要があります。これは、キーボード イベントのソースとして機能し、基盤となるハードウェア (この場合はピアノのキーボード) と通信するオペレーティング システムへのプラグインです。Windows および Linux の場合、おそらく C を使用することになるでしょう。
しかし、キーストロークを生成するだけなので(私が数年前に試みたように、キーストロークを傍受しようとしているのではない)、オペレーティングシステムが人工的なキーストロークを送信するために備えている機能を使用できる可能性があります。Windowsには、そのためのインターフェイスがあります(おそらくいくつかありますが、私が考えているのは次のものです)。SendInput
しかし、同様の機能を持つ「ジャーナル」インターフェイスがあることは知っています)。他のオペレーティング システムでも同様の機能があるはずです。これで十分でしょう。デバイス ドライバーのルートは扱いにくく、Java 以外の言語を使用する必要があるため、ここから始めることをお勧めします。(私は Java の大ファンですが、オペレーティング システムがデバイス ドライバーと通信するために使用するインターフェイスは、C などを使用した方が簡単に使用できる傾向があります。)
更新: コードからキーストロークまでの「辞書」についての詳細:
基本的に辞書はトライ(ありがとう、@Adam) 最長プレフィックス一致で検索します。詳細:
機械速記では、速記者は速記機の複数のキーを同時に押し、その後すべて放すことで書きます。これはキーボードの「ストローク」と呼ばれ、ピアノでコードを弾くようなものです。ストロークは多くの場合 (常にではありませんが) 話し言葉の音節に対応します。音節と同様に、1 ストローク (コード) だけで意味を持つ場合もあれば、後続のストロークとの組み合わせでのみ意味を持つ場合もあります (「good」と「good」の後に「bye」が続く場合を想像してください)。速記者は学んだ学校から大きな影響を受けますが、どのストロークを何を意味するかを示す独自の「辞書」を持ち、仕事を通じて継続的に磨きをかけていきます。辞書には、速記部分 (略して「ステノ」) が 1 ストロークの場合と複数ストロークの場合のエントリがあります。多くの場合、同じ開始ストロークを持つ複数のエントリが、長さと後続のストロークによって区別されます。たとえば (ここでは実際の速記は使用せず、プレースホルダーのみを使用します)、次のエントリがあります。
A = アルファ A/B = アルファベット A/B/C = アルファベット A/C = エアコン B = ハチ B/C = なぜなら C = 海 D = 犬 D/D = ディーディー
(これらの文字は音符を表すものではなく、単なる抽象的なマーカーです。)
は複数のエントリを開始することに注意してくださいA
。また、ストロークの変換方法は、C
以前に 、 を見たことがあるか、または最初から始めるかによって異なるA
ことB
にも注意してください。
また、(上記の非常に小さなサンプルには示されていませんが)同じ単語やフレーズを「演奏」する方法が 1 つだけではなく複数ある場合があることにも注意してください。速記者は、手の位置に応じて前の単語から次の単語に流れやすくするためにこれを行います。そこには音楽との明らかな類似点があり、これを使用して、タイピングの流れを音楽の演奏に近づけることができます。これにより、ピアノ演奏に悪影響が及ぶのを防ぎ、実際に RSI に役立つ可能性を最大限に高めることができます。
速記を標準テキストに翻訳する場合も、「最長プレフィックス一致」検索を使用します。翻訳アルゴリズムは、最初に書かれたストロークから開始し、そのストロークで始まるエントリを検索します。エントリが 1 つしかなく、長さが 1 ストロークである場合は、「それが使用するエントリです」と確実に判断し、対応するテキストを出力して、次のストロークから新たに開始できます。ただし、そのストロークは、長さが異なる複数のエントリを開始する可能性が高いです。そのため、次のストロークを調べて、その 2 つのストロークで順番に始まるエントリがあるかどうかを確認し、一致が見つかるまでこれを繰り返します。
上記の辞書で、次のシーケンスを見たとします。
ABCABD
これを翻訳すると次のようになります:
A
長さの異なる 3 つのエントリの始まりです。次のストロークを見てください。C
A/C
1 つのエントリのみに一致します。「エアコン」を出力し、次のストロークから新しく開始します。B
B
2 つのエントリを開始します。次のストロークを見てください。B
B/B
何も開始しません。最も長い前の一致 (B
) を取得し、それを出力します ("bee")- 出力が
B
「bee」の場合、B
バッファーにはまだストロークが残っています。2 つのエントリが開始されるので、次のストロークを見てみましょう。C
B/C
1 つのエントリに一致します。「because」を出力し、次のストロークで新しく開始します。A
A
3 つのエントリを開始します。次のストロークを見てください。B
A/B
2 つのエントリを開始します。次のストロークを見てください。C
A/B/C
1 つのエントリのみに一致します。「アルファベット」を出力し、次のストロークから新しく開始します。A
A
3 つのエントリを開始します。次のストロークを見てください。B
A/B
2 つのエントリを開始します。次のストロークを見てください。D
A/B/D
は何も一致しないので、最も長い前の一致 (A/B
) を取得し、それを使用して「アルファベット」を出力します。これにより、D
バッファー内にまだ が残ります。D
2 つのエントリで始まるので、通常は次のストロークを調べますが、すべてのストロークを処理したので、これを単独で検討します。単独では、「dog」と翻訳されるため、これを出力します。
上記の点について注意すべき点:
- 読んだがまだ翻訳していないストロークのバッファがあります。
- 常に、できるだけ多くのストロークを単一のエントリと一致させる必要があります。は
A/B
、「alpha」や「bee」ではなく、「alphabet」と翻訳する必要があります。 - (上記には示されていません) 辞書内のどの単語とも一致しないため、翻訳できないストロークのシーケンスがある可能性があります。(速記家は「untranslate」という名詞を使用します。たとえば、私たちの辞書では、ストロークは
E
「untranslate」になります。) - (上記には示されていません) 速記の理論の中には、より広い文脈に基づいて、同じストロークのセットが複数の意味を持つことを許容するものもあります。速記の人々はこれを「競合」と呼びます。おそらく、プロジェクトではこれを禁止したいでしょう。実際、速記が速記者によって手動で翻訳されていた頃は、文のどこにそれがあるのかだけで正しい選択がわかるので競合は問題ありませんでした。しかし、機械翻訳の台頭により、結果として得られる翻訳テキストを調べて競合を「修正」する必要を回避するために、競合のない速記の理論が生まれました。
- リアルタイムで翻訳する (実際に行う) ということは、部分的な一致を受け取った場合、次のコードを待つ間それを保持する必要があることを意味しますが、おそらくタイムアウトまでしか保持されず、その時点でバッファにあるものをできる限り翻訳することになります。 (または、タイムアウトは不要かもしれません。それはあなたの判断次第です。)
- おそらく、「前のストロークを無視する」というストロークが最適でしょう
- おそらく、「何も出力せずにバッファを完全にクリアする」というストロークがあるのが最善でしょう。