シンセサイザーをコンピューターのキーボードとして使用する

最近、アイデアが思いつきました。シンセサイザーをコンピューターに接続することで、テキストを入力することは可能ですか? 私はこれを実装しようとしましたが、成功しました。 私のプログラムは、シンセサイザーでキーストロークを読み取り、通常のキーボードでキーストロークをエミュレートします。 この記事では、これを実装する方法を説明します。 Qtを使用してC ++上のLinuxで記述します。









シンセサイザーからのデータの読み取り



そのため、LinuxとYamaha DGX-200シンセサイザーを搭載したラップトップがあります。 USBコネクタを介してシンセサイザーをラップトップに接続し、デバイスが認識されたことを確認します。







シンセサイザーのキーを押すと他の記号が表示されますが、デバイスからは常に質問が流れます。 ところで、興味深い事実:この出力をファイルに書き込んでからファイルから読み取り、/ dev / midi2に書き戻すと、シンセサイザーは列を介して、録音中に押されたノートを一時停止せずに再生します。



次のタスクは、このスレッドを解析することです。 Googleで長時間検索した後、 portmidiライブラリを使用することにしました。 そのドキュメントはかなり不足しており、実際の例はまったく見つかりませんでした。 さて、もう1つの例があります。 デバイスのリストを取得します。

int count = Pm_CountDevices(); for(int i = 0; i < count; i++) { const PmDeviceInfo* info = Pm_GetDeviceInfo(i); qDebug() << i << ": " << info->name << " input: " << info->input << " output: " << info->output; }
      
      





私は次の結果を得ました:

 0: Midi Through Port-0 input: 0 output: 1 1: Midi Through Port-0 input: 1 output: 0 2: YAMAHA Portable G MIDI 1 input: 0 output: 1 3: YAMAHA Portable G MIDI 1 input: 1 output: 0
      
      





デバイスをさらに操作するには、行の先頭に示されているIDのみを知る必要があります。 デバイス3が私たちに合っています-シンセサイザーからの入力(入力= 1)ストリーム。 目的のストリームを開きます。

 PortMidiStream* stream = 0; PmError e = Pm_OpenInput(&stream, good_id, 0, 100, 0, 0); if (e != pmNoError) { qWarning() << "Can't open input, error: " << e << endl; return 2; }
      
      





その後、定期的にデータを読み取ります。 定期的なタイマーコールでQtスロットを使用しましたが、通常のwhile(true)とsleepは実行します。

 PmEvent event; // ,       int c = Pm_Read(stream, &event, 1); //      if (c > 0 && Pm_MessageStatus(event.message) == 144) { unsigned int note = Pm_MessageData1(event.message), volume = Pm_MessageData2(event.message); //   note  volume }
      
      





これらのマジックナンバーが何であるかを説明するために、MIDIコマンドがどのように機能するかを説明します。



MIDIコマンド



各メッセージ(別名MIDIコマンド)は、portmidiでstatus、data1、data2と呼ばれる3つの整数で構成されます。 可能性のあるステータスの表はここにあります 。 ステータス144(最初のチャネルのノートの状態の変化)にのみ関心があります。 この場合、ノート番号はdata1に転送され、そのボリュームはdata2に転送されます。 たとえば、シンセサイザーの最初のオクターブの「上」キーを押すと、コマンドは144 60 95になり、離すと-144 60 0になります。



ボリュームは0から127の範囲で変化し、キーのヒットの強さに依存します。 理論的には、ユーザーがキーボードを強く押すと、小文字ではなく大文字を表示できます。 さて、ノート番号は単なるシリアル番号であり、ノートと番号の対応はこの写真で見ることができます:



音符と和音をマークする



ノートを「3C」または「3C#」に指定することにしました。3はオクターブ番号(オクターブは「la」で始まる方が簡単です)、Cはノート指定(「前」)、必要に応じてシャープが追加されます。 実装方法は次のとおりです。

 class Note { public: Note(int midi_number); QString to_string() const; int tone, octave; }; Note::Note(int midi_number) { int n = midi_number - 21; octave = n / 12; tone = (n - octave * 12); } QString Note::to_string() const { return QObject::tr("%1%2").arg(octave).arg( tone == 0? "A": tone == 1? "A#": tone == 2? "B": tone == 3? "C": tone == 4? "C#": tone == 5? "D": tone == 6? "D#": tone == 7? "E": tone == 8? "F": tone == 9? "F#": tone == 10? "G": tone == 11? "G#": "??" ); }
      
      





ユーザーが和音(同時に複数の音)を押すと、いくつかのメッセージがほとんどすぐに到着します。 この状況をプログラムで追跡し、シングルプレスとコードを区別できます。 私のプログラムでは、さまざまなコードを異なる文字にマッピングできます。 コードの表記法を取得するには、それに含まれるキーのプラス表記法を接続します:「3C#+ 3E + 3G#」。 ユーザーが音符または和音を押すと、プログラムはこの表記に一致する文字列をレイアウトで検索し、対応するキーを押すことをエミュレートします。 シンセサイザーのキーがリリースされると、キーのリリースがエミュレートされます。 ここでの修飾キー(Shift、Ctrlなど)は、他のキーと同じです。 すべての組み合わせは期待どおりに機能します。



キーエミュレーション



ほら、メモが押されてリリースされるタイミングを判断できます。 次に、キーボードのキーストロークをエミュレートする方法を学びます。 Stack Overflowで見つけたソリューションを使用します。

 #include <X11/Xlib.h> #include <X11/keysym.h> #include <X11/extensions/XTest.h> Display* display = XOpenDisplay(0); void emulate_key(QString key, bool pressed) { KeySym sym = XStringToKeysym(key.toAscii()); if (sym == NoSymbol) { qWarning() << "Failed to emulate key: " << key; return; } XTestFakeKeyEvent(display, XKeysymToKeycode(display, sym), pressed, 0); XFlush(display); }
      
      





XStringToKeysym関数の使用を追加して、構成ファイルから取得する名前でキーをエミュレートします。 有効なキーのリストは、ヘッダーファイル/usr/include/X11/keysymdef.hにあります。



レイアウトは、次の形式のlayout.iniファイルに保存されます。

 ; letters X = 3C#+3G# Y = 3D#+3G# Z = 3E+3G# ; navigation Space = 2E Return = 1A+2A BackSpace = 4C# Delete = 4D# Left = 4A Right = 4C
      
      





レイアウト



残った最後のタスクは、レイアウトを作成することです。 単純なオプション-キーの各文字-は不便でした。 十分なキーがありますが、それに加えて、シンセサイザーのサイズが大きいために、多くの場合手を動かす必要があります。 幸いなことに、キーボードショートカットを使用できます。コンピューターのキーボードよりもシンセサイザーで押す方がはるかに便利です。



26個のキー(AからG#まで)26個のラテン文字に合わせてみましょう。 7つの白いキーの文字の選択は明らかです-これらはAからGの文字で、対応する音符の表記として一般に受け入れられています。 次に、使用頻度の高い順に残りの文字を書き、リストの一番上に近い文字から単語を構成しようとしました。 ヒントという言葉をもらい、これらの文字に5つの黒いキーを付けました。 残りのキーについては、同じオクターブ内で大小の3分の1をアルファベット順に割り当てました。 他の文字(ロシア語など)を配置するためのオプションはまだたくさんあります。



残りのキーもキーボード上の場所を見つけました。 私はこのレイアウトを得ました:







楽譜エディタMuseScoreが使用されました。



投稿に添付されているビデオは、Hello worldプログラムのセットと、キーボードではなくシンセサイザーを使用したコンパイルを示しています。



プログラムコードはGithubに投稿されています。



All Articles