0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

64パッドの指位置図示とノート変換のためのJSFXを作った

Posted at

動機

  • ブラウザで動く64パッドのレイアウト図示用MIDIモニタを作った
    • 主に受け取ったコード演奏を図示する
    • 一つのMIDIノート(音高)に複数のパッドが対応するので、実際に何を押しているのか分かりにくい
    • 押した位置を図時するためのモードも作ったが不便
      • ブラウザとDAWを切り替えたりデスクトップ録画するのが面倒
      • 音を出せるようにしたいがMIDIのルーティングや遅延を考えるとブラウザではやりたくない
  • DAW内で動くものを作りたい
    • ReaperのJSFX(EEL2)、Effects/midi/MIDI Transpose Notesあたりを見てたらできそうな気がしてきた
    • ReaperのJSFXをVSTとして別のDAWで動かすソフトが存在する(YSFX)
      • 他のDAWでも動かせそう

作ったもの

  • 64 Pad Software Note Mode JSFX
    • Ableton LiveのDrumrack相当のMIDI入力を、押した位置の図示しながら音高を変換する
    • 自分で使いたいレイアウトとP4thに対応
  • Mm3rdRotatedLayout
    Mm3rdRotatedLayout
  • P4thLayout(完全四度クロマチック、4ths String Layout)
    P4thLayout
  • コードは長くなったので記事末尾参照

動かしてみた

  • 注意:素人が作ったプラグインなので何かあっても責任は負えません

動作例:Reaper

  • JSFX/VSTを並べて配置するだけ
    Reaper Setting
  • コード演奏(Mm3rdRotatedLayout)
    Reaper Chord Play Sample

動作例:Ableton Live + ysfx-s instrument

  • VSTi・VST(FX)の後にVSTiを置けないので、2トラック使ってルーティングする
  • スクリーンショット 2024-10-13 125107_書き込み.png
  • コード演奏(Mm3rdRotatedLayout)
    AbletonLive Code Play Sample
  • ドラムラック演奏の可視化(MonitorOnly)Ableton Live Drumrack Play Sample

動作例:Dorico + Modalics Plugin Buddy + ysfx-s instrument

  • Doricoは譜面ソフトなのでMIDIのルーティングはほとんどできない
  • Modalics Plugin Buddy(VSTをロードできるVST)でysfx-sをMIDI FXスロットに入れ、Instrumentスロットに演奏用のVSTを入れて使用している

Dorico Setting Sample

動作例:Bitwig 8-Track + ysfx-s instrument

  • 順番に並べるだけ(P4th Layout)
  • Bitwig Setting Sample

この記事のJSFXのプラグインを動かすには

  • Reaper

    • プラグイン(VST/JS等)の選択画面でメニューのエフェクト→新規JSエフェクトを作成、で空のJSFXを作れるのでそこに貼り付ける
    • image.png
  • Reaper以外

    • YSFXのフォーク(※ReadMe)を使用する(VST/CLAPプラグイン)

    • image.png

    • この記事では v0.0.26 を使用(頻繁に更新されているようなので注意)

    • 任意の場所・ファイル名でJSFXを保存しておき、YSFSにLoadして使用する

    • DAW側でMIDIルーティングができない場合は、Modalics Plugin BuddyなどのVSTコンテナホストを使うのが簡単

  • 音高変換後のMIDI Noteの記録は各DAWのMIDI Burn機能か、BirdBird MIDICapを使うと便利

余談:BirdBird MIDICapはとてもおすすめ(レトロスペクティブMIDIキャプチャ)

  • https://www.birdsthings.com/midi-cap
  • レトロスペクティブMIDIキャプチャ機能を提供するVSTi/CLAPプラグイン
    • 直近60秒のMIDI入力から好きな部分を切り出して保存できる
    • 好きなDAWの好きな場所に置けるのでものすごくお勧め
      • アルペジエーター等MIDI-FXの出力も直感的にキャプチャできる
  • 操作方法
    • MIDI Cap
    • 保存したいところを選択し(上の画像の背景白)、DAWやエクスプローラーにドラッグドロップで保存する
    • マウスホイールを押しながらドラッグでスクロール
      • テンポを合わせてくれないので、DAWと同じか1/2のテンポで弾くと後が楽になる
    • Ctrl+クリックでキャプチャ停止・再開
    • Shift+Rでリセット
  • Lite版(無償)と有償版の違いは記録できる時間の長さだけ

作成したJSFXのコード

64PadSwNoteMode.eel2
desc:64Pad Software Note Mode
//tags: MIDI processing


in_pin:none
out_pin:none
options:gfx_hz=60

slider1:layout=0<0, 5, 1{Mm3rdRotated,P5thRotated,P5th,P4th,MonitorOnly}>Layout
slider2:octave=0<-3, 3, 1>Octave
slider3:transpose=0<-12, 12, 1>Transpose
slider4:text_alpha=0.9<0.0, 1.0, 0.1>TextAlpha



@init

RECT_SIZE = 50;
PAD_COUNT = 64;
PAD_COLS = 8;
NOTE_NUM_MAX = 127;

notebuf = 0; // 4 entries per open note: orignote, channel, vel, transnote
buflen = 0;

// Midi Note Numberをパッドの位置として、pad_*_arrayインデックスに変換するための配列
n2p = 400; idx = 0; loop(NOTE_NUM_MAX, (n2p[idx]=0; idx+=1;));
n2p[64]=0;  n2p[65]=1;  n2p[66]=2;  n2p[67]=3;  n2p[96]=4;  n2p[97]=5;  n2p[98]=6;  n2p[99]=7;
n2p[60]=8;  n2p[61]=9;  n2p[62]=10;  n2p[63]=11;  n2p[92]=12;  n2p[93]=13;  n2p[94]=14;  n2p[95]=15;
n2p[56]=16;  n2p[57]=17;  n2p[58]=18;  n2p[59]=19;  n2p[88]=20;  n2p[89]=21;  n2p[90]=22;  n2p[91]=23;
n2p[52]=24;  n2p[53]=25;  n2p[54]=26;  n2p[55]=27;  n2p[84]=28;  n2p[85]=29;  n2p[86]=30;  n2p[87]=31;
n2p[48]=32;  n2p[49]=33;  n2p[50]=34;  n2p[51]=35;  n2p[80]=36;  n2p[81]=37;  n2p[82]=38;  n2p[83]=39;
n2p[44]=40;  n2p[45]=41;  n2p[46]=42;  n2p[47]=43;  n2p[76]=44;  n2p[77]=45;  n2p[78]=46;  n2p[79]=47;
n2p[40]=48;  n2p[41]=49;  n2p[42]=50;  n2p[43]=51;  n2p[72]=52;  n2p[73]=53;  n2p[74]=54;  n2p[75]=55;
n2p[36]=56;  n2p[37]=57;  n2p[38]=58;  n2p[39]=59;  n2p[68]=60;  n2p[69]=61;  n2p[70]=62;  n2p[71]=63;

note2name = 700;
note2name[0] = "C"; note2name[1] = "C#"; note2name[2] = "D"; note2name[3] = "D#";
note2name[4] = "E"; note2name[5] = "F"; note2name[6] = "F#"; note2name[7] = "G";
note2name[8] = "G#"; note2name[9] = "A"; note2name[10] = "A#"; note2name[11] = "B";
function get_note_name(note_num) (
    note2name[(note_num % 12)|0];
);
function get_note_name_diatonic(note_num) (
    num = (note_num % 12)|0;
    (num == 1) ? ""
        : num == 3 ? "" 
        : num == 6 ? "" 
        : num == 8 ? "" 
        : num == 10 ? "" 
        : note2name[num];
);
function set_note_name_array(n2t, n2n) (
    idx = 36; loop(PAD_COUNT,
        note = n2t[idx];
        pos  = n2p[idx];
        n2n[pos] = get_note_name(note);
        idx+=1;);
);
function set_note_name_array_note_num(n2t, n2n) (
    idx = 36; loop(PAD_COUNT,
        note = n2t[idx];
        pos  = n2p[idx];
        n2n[pos] = note;
        idx+=1;);
);
function apply_offset(n2t, offset) (
    idx = 36; loop(PAD_COUNT, (n2t[idx] += offset; idx += 1;));
);

function set_layout_Mm3rdRotated(n2t, n2n, offset) (
    idx = 0; loop(NOTE_NUM_MAX, (n2t[idx]=0; idx+=1;));
    n2t[64]=43;  n2t[65]=47;  n2t[66]=50;  n2t[67]=54;  n2t[96]=57;  n2t[97]=61;  n2t[98]=64;  n2t[99]=68;
    n2t[60]=42;  n2t[61]=46;  n2t[62]=49;  n2t[63]=53;  n2t[92]=56;  n2t[93]=60;  n2t[94]=63;  n2t[95]=67;
    n2t[56]=41;  n2t[57]=45;  n2t[58]=48;  n2t[59]=52;  n2t[88]=55;  n2t[89]=59;  n2t[90]=62;  n2t[91]=66;
    n2t[52]=40;  n2t[53]=44;  n2t[54]=47;  n2t[55]=51;  n2t[84]=54;  n2t[85]=58;  n2t[86]=61;  n2t[87]=65;
    n2t[48]=39;  n2t[49]=43;  n2t[50]=46;  n2t[51]=50;  n2t[80]=53;  n2t[81]=57;  n2t[82]=60;  n2t[83]=64;
    n2t[44]=38;  n2t[45]=42;  n2t[46]=45;  n2t[47]=49;  n2t[76]=52;  n2t[77]=56;  n2t[78]=59;  n2t[79]=63;
    n2t[40]=37;  n2t[41]=41;  n2t[42]=44;  n2t[43]=48;  n2t[72]=51;  n2t[73]=55;  n2t[74]=58;  n2t[75]=62;
    n2t[36]=36;  n2t[37]=40;  n2t[38]=43;  n2t[39]=47;  n2t[68]=50;  n2t[69]=54;  n2t[70]=57;  n2t[71]=61;
    apply_offset(n2t, offset);
    set_note_name_array(n2t, n2n);
    n2n[0]=1?n2n[0]:"";  n2n[1]=1?n2n[1]:"";  n2n[2]=1?n2n[2]:"";  n2n[3]=0?n2n[3]:"";  n2n[4]=1?n2n[4]:"";  n2n[5]=0?n2n[5]:"";  n2n[6]=1?n2n[6]:"";  n2n[7]=0?n2n[7]:"";
    n2n[8]=0?n2n[8]:"";  n2n[9]=0?n2n[9]:"";  n2n[10]=0?n2n[10]:"";  n2n[11]=1?n2n[11]:"";  n2n[12]=0?n2n[12]:"";  n2n[13]=1?n2n[13]:"";  n2n[14]=0?n2n[14]:"";  n2n[15]=1?n2n[15]:"";
    n2n[16]=1?n2n[16]:"";  n2n[17]=1?n2n[17]:"";  n2n[18]=1?n2n[18]:"";  n2n[19]=1?n2n[19]:"";  n2n[20]=1?n2n[20]:"";  n2n[21]=1?n2n[21]:"";  n2n[22]=1?n2n[22]:"";  n2n[23]=0?n2n[23]:"";
    n2n[24]=1?n2n[24]:"";  n2n[25]=0?n2n[25]:"";  n2n[26]=1?n2n[26]:"";  n2n[27]=0?n2n[27]:"";  n2n[28]=0?n2n[28]:"";  n2n[29]=0?n2n[29]:"";  n2n[30]=0?n2n[30]:"";  n2n[31]=1?n2n[31]:"";
    n2n[32]=0?n2n[32]:"";  n2n[33]=1?n2n[33]:"";  n2n[34]=0?n2n[34]:"";  n2n[35]=1?n2n[35]:"";  n2n[36]=1?n2n[36]:"";  n2n[37]=1?n2n[37]:"";  n2n[38]=1?n2n[38]:"";  n2n[39]=1?n2n[39]:"";
    n2n[40]=1?n2n[40]:"";  n2n[41]=0?n2n[41]:"";  n2n[42]=1?n2n[42]:"";  n2n[43]=0?n2n[43]:"";  n2n[44]=1?n2n[44]:"";  n2n[45]=0?n2n[45]:"";  n2n[46]=1?n2n[46]:"";  n2n[47]=0?n2n[47]:"";
    n2n[48]=0?n2n[48]:"";  n2n[49]=1?n2n[49]:"";  n2n[50]=0?n2n[50]:"";  n2n[51]=1?n2n[51]:"";  n2n[52]=0?n2n[52]:"";  n2n[53]=1?n2n[53]:"";  n2n[54]=0?n2n[54]:"";  n2n[55]=1?n2n[55]:"";
    n2n[56]=1?n2n[56]:"";  n2n[57]=1?n2n[57]:"";  n2n[58]=1?n2n[58]:"";  n2n[59]=1?n2n[59]:"";  n2n[60]=1?n2n[60]:"";  n2n[61]=0?n2n[61]:"";  n2n[62]=1?n2n[62]:"";  n2n[63]=0?n2n[63]:"";
);
function set_layout_P4th(n2t, n2n, offset) (
    idx = 0; loop(NOTE_NUM_MAX, (n2t[idx]=0; idx+=1;));
    n2t[64]=71;  n2t[65]=72;  n2t[66]=73;  n2t[67]=74;  n2t[96]=75;  n2t[97]=76;  n2t[98]=77;  n2t[99]=78;
    n2t[60]=66;  n2t[61]=67;  n2t[62]=68;  n2t[63]=69;  n2t[92]=70;  n2t[93]=71;  n2t[94]=72;  n2t[95]=73;
    n2t[56]=61;  n2t[57]=62;  n2t[58]=63;  n2t[59]=64;  n2t[88]=65;  n2t[89]=66;  n2t[90]=67;  n2t[91]=68;
    n2t[52]=56;  n2t[53]=57;  n2t[54]=58;  n2t[55]=59;  n2t[84]=60;  n2t[85]=61;  n2t[86]=62;  n2t[87]=63;
    n2t[48]=51;  n2t[49]=52;  n2t[50]=53;  n2t[51]=54;  n2t[80]=55;  n2t[81]=56;  n2t[82]=57;  n2t[83]=58;
    n2t[44]=46;  n2t[45]=47;  n2t[46]=48;  n2t[47]=49;  n2t[76]=50;  n2t[77]=51;  n2t[78]=52;  n2t[79]=53;
    n2t[40]=41;  n2t[41]=42;  n2t[42]=43;  n2t[43]=44;  n2t[72]=45;  n2t[73]=46;  n2t[74]=47;  n2t[75]=48;
    n2t[36]=36;  n2t[37]=37;  n2t[38]=38;  n2t[39]=39;  n2t[68]=40;  n2t[69]=41;  n2t[70]=42;  n2t[71]=43;
    apply_offset(n2t, offset);
    set_note_name_array(n2t, n2n);
    n2n[0]=1?n2n[0]:"";  n2n[1]=1?n2n[1]:"";  n2n[2]=0?n2n[2]:"";  n2n[3]=1?n2n[3]:"";  n2n[4]=0?n2n[4]:"";  n2n[5]=1?n2n[5]:"";  n2n[6]=1?n2n[6]:"";  n2n[7]=0?n2n[7]:"";  
    n2n[8]=0?n2n[8]:"";  n2n[9]=1?n2n[9]:"";  n2n[10]=0?n2n[10]:"";  n2n[11]=1?n2n[11]:"";  n2n[12]=0?n2n[12]:"";  n2n[13]=1?n2n[13]:"";  n2n[14]=1?n2n[14]:"";  n2n[15]=0?n2n[15]:"";  
    n2n[16]=0?n2n[16]:"";  n2n[17]=1?n2n[17]:"";  n2n[18]=0?n2n[18]:"";  n2n[19]=1?n2n[19]:"";  n2n[20]=1?n2n[20]:"";  n2n[21]=0?n2n[21]:"";  n2n[22]=1?n2n[22]:"";  n2n[23]=0?n2n[23]:"";  
    n2n[24]=0?n2n[24]:"";  n2n[25]=1?n2n[25]:"";  n2n[26]=0?n2n[26]:"";  n2n[27]=1?n2n[27]:"";  n2n[28]=1?n2n[28]:"";  n2n[29]=0?n2n[29]:"";  n2n[30]=1?n2n[30]:"";  n2n[31]=0?n2n[31]:"";  
    n2n[32]=0?n2n[32]:"";  n2n[33]=1?n2n[33]:"";  n2n[34]=1?n2n[34]:"";  n2n[35]=0?n2n[35]:"";  n2n[36]=1?n2n[36]:"";  n2n[37]=0?n2n[37]:"";  n2n[38]=1?n2n[38]:"";  n2n[39]=0?n2n[39]:"";  
    n2n[40]=0?n2n[40]:"";  n2n[41]=1?n2n[41]:"";  n2n[42]=1?n2n[42]:"";  n2n[43]=0?n2n[43]:"";  n2n[44]=1?n2n[44]:"";  n2n[45]=0?n2n[45]:"";  n2n[46]=1?n2n[46]:"";  n2n[47]=1?n2n[47]:"";  
    n2n[48]=1?n2n[48]:"";  n2n[49]=0?n2n[49]:"";  n2n[50]=1?n2n[50]:"";  n2n[51]=0?n2n[51]:"";  n2n[52]=1?n2n[52]:"";  n2n[53]=0?n2n[53]:"";  n2n[54]=1?n2n[54]:"";  n2n[55]=1?n2n[55]:"";  
    n2n[56]=1?n2n[56]:"";  n2n[57]=0?n2n[57]:"";  n2n[58]=1?n2n[58]:"";  n2n[59]=0?n2n[59]:"";  n2n[60]=1?n2n[60]:"";  n2n[61]=1?n2n[61]:"";  n2n[62]=0?n2n[62]:"";  n2n[63]=1?n2n[63]:"";  
);
function set_layout_P5th(n2t, n2n, offset) (
    idx = 0; loop(NOTE_NUM_MAX, (n2t[idx]=0; idx+=1;));
    n2t[64]=85; n2t[65]=86; n2t[66]=87; n2t[67]=88; n2t[96]=89; n2t[97]=90; n2t[98]=91; n2t[99]=92;
    n2t[60]=78; n2t[61]=79; n2t[62]=80; n2t[63]=81; n2t[92]=82; n2t[93]=83; n2t[94]=84; n2t[95]=85;
    n2t[56]=71; n2t[57]=72; n2t[58]=73; n2t[59]=74; n2t[88]=75; n2t[89]=76; n2t[90]=77; n2t[91]=78;
    n2t[52]=64; n2t[53]=65; n2t[54]=66; n2t[55]=67; n2t[84]=68; n2t[85]=69; n2t[86]=70; n2t[87]=71;
    n2t[48]=57; n2t[49]=58; n2t[50]=59; n2t[51]=60; n2t[80]=61; n2t[81]=62; n2t[82]=63; n2t[83]=64;
    n2t[44]=50; n2t[45]=51; n2t[46]=52; n2t[47]=53; n2t[76]=54; n2t[77]=55; n2t[78]=56; n2t[79]=57;
    n2t[40]=43; n2t[41]=44; n2t[42]=45; n2t[43]=46; n2t[72]=47; n2t[73]=48; n2t[74]=49; n2t[75]=50;
    n2t[36]=36; n2t[37]=37; n2t[38]=38; n2t[39]=39; n2t[68]=40; n2t[69]=41; n2t[70]=42; n2t[71]=43;
    apply_offset(n2t, offset);
    set_note_name_array(n2t, n2n);
    n2n[0]=0?n2n[0]:"";  n2n[1]=1?n2n[1]:"";  n2n[2]=0?n2n[2]:"";  n2n[3]=1?n2n[3]:"";  n2n[4]=1?n2n[4]:"";  n2n[5]=0?n2n[5]:"";  n2n[6]=1?n2n[6]:"";  n2n[7]=0?n2n[7]:"";  
    n2n[8]=0?n2n[8]:"";  n2n[9]=1?n2n[9]:"";  n2n[10]=0?n2n[10]:"";  n2n[11]=1?n2n[11]:"";  n2n[12]=0?n2n[12]:"";  n2n[13]=1?n2n[13]:"";  n2n[14]=1?n2n[14]:"";  n2n[15]=0?n2n[15]:"";  
    n2n[16]=1?n2n[16]:"";  n2n[17]=1?n2n[17]:"";  n2n[18]=0?n2n[18]:"";  n2n[19]=1?n2n[19]:"";  n2n[20]=0?n2n[20]:"";  n2n[21]=1?n2n[21]:"";  n2n[22]=1?n2n[22]:"";  n2n[23]=0?n2n[23]:"";  
    n2n[24]=1?n2n[24]:"";  n2n[25]=1?n2n[25]:"";  n2n[26]=0?n2n[26]:"";  n2n[27]=1?n2n[27]:"";  n2n[28]=0?n2n[28]:"";  n2n[29]=1?n2n[29]:"";  n2n[30]=0?n2n[30]:"";  n2n[31]=1?n2n[31]:"";  
    n2n[32]=1?n2n[32]:"";  n2n[33]=0?n2n[33]:"";  n2n[34]=1?n2n[34]:"";  n2n[35]=1?n2n[35]:"";  n2n[36]=0?n2n[36]:"";  n2n[37]=1?n2n[37]:"";  n2n[38]=0?n2n[38]:"";  n2n[39]=1?n2n[39]:"";  
    n2n[40]=1?n2n[40]:"";  n2n[41]=0?n2n[41]:"";  n2n[42]=1?n2n[42]:"";  n2n[43]=1?n2n[43]:"";  n2n[44]=0?n2n[44]:"";  n2n[45]=1?n2n[45]:"";  n2n[46]=0?n2n[46]:"";  n2n[47]=1?n2n[47]:"";  
    n2n[48]=1?n2n[48]:"";  n2n[49]=0?n2n[49]:"";  n2n[50]=1?n2n[50]:"";  n2n[51]=0?n2n[51]:"";  n2n[52]=1?n2n[52]:"";  n2n[53]=1?n2n[53]:"";  n2n[54]=0?n2n[54]:"";  n2n[55]=1?n2n[55]:"";  
    n2n[56]=1?n2n[56]:"";  n2n[57]=0?n2n[57]:"";  n2n[58]=1?n2n[58]:"";  n2n[59]=0?n2n[59]:"";  n2n[60]=1?n2n[60]:"";  n2n[61]=1?n2n[61]:"";  n2n[62]=0?n2n[62]:"";  n2n[63]=1?n2n[63]:"";  
);
function set_layout_P5thRotated(n2t, n2n, offset) (
    idx = 0; loop(NOTE_NUM_MAX, (n2t[idx]=0; idx+=1;));
    n2t[64]=43;  n2t[65]=50;  n2t[66]=57;  n2t[67]=64;  n2t[96]=71;  n2t[97]=78;  n2t[98]=85;  n2t[99]=92;
    n2t[60]=42;  n2t[61]=49;  n2t[62]=56;  n2t[63]=63;  n2t[92]=70;  n2t[93]=77;  n2t[94]=84;  n2t[95]=91;
    n2t[56]=41;  n2t[57]=48;  n2t[58]=55;  n2t[59]=62;  n2t[88]=69;  n2t[89]=76;  n2t[90]=83;  n2t[91]=90;
    n2t[52]=40;  n2t[53]=47;  n2t[54]=54;  n2t[55]=61;  n2t[84]=68;  n2t[85]=75;  n2t[86]=82;  n2t[87]=89;
    n2t[48]=39;  n2t[49]=46;  n2t[50]=53;  n2t[51]=60;  n2t[80]=67;  n2t[81]=74;  n2t[82]=81;  n2t[83]=88;
    n2t[44]=38;  n2t[45]=45;  n2t[46]=52;  n2t[47]=59;  n2t[76]=66;  n2t[77]=73;  n2t[78]=80;  n2t[79]=87;
    n2t[40]=37;  n2t[41]=44;  n2t[42]=51;  n2t[43]=58;  n2t[72]=65;  n2t[73]=72;  n2t[74]=79;  n2t[75]=86;
    n2t[36]=36;  n2t[37]=43;  n2t[38]=50;  n2t[39]=57;  n2t[68]=64;  n2t[69]=71;  n2t[70]=78;  n2t[71]=85;
    apply_offset(n2t, offset);
    set_note_name_array(n2t, n2n);
    n2n[0]=1?n2n[0]:"";  n2n[1]=1?n2n[1]:"";  n2n[2]=1?n2n[2]:"";  n2n[3]=1?n2n[3]:"";  n2n[4]=1?n2n[4]:"";  n2n[5]=0?n2n[5]:"";  n2n[6]=0?n2n[6]:"";  n2n[7]=0?n2n[7]:"";  
    n2n[8]=0?n2n[8]:"";  n2n[9]=0?n2n[9]:"";  n2n[10]=0?n2n[10]:"";  n2n[11]=0?n2n[11]:"";  n2n[12]=0?n2n[12]:"";  n2n[13]=1?n2n[13]:"";  n2n[14]=1?n2n[14]:"";  n2n[15]=1?n2n[15]:"";  
    n2n[16]=1?n2n[16]:"";  n2n[17]=1?n2n[17]:"";  n2n[18]=1?n2n[18]:"";  n2n[19]=1?n2n[19]:"";  n2n[20]=1?n2n[20]:"";  n2n[21]=1?n2n[21]:"";  n2n[22]=1?n2n[22]:"";  n2n[23]=0?n2n[23]:"";  
    n2n[24]=1?n2n[24]:"";  n2n[25]=1?n2n[25]:"";  n2n[26]=0?n2n[26]:"";  n2n[27]=0?n2n[27]:"";  n2n[28]=0?n2n[28]:"";  n2n[29]=0?n2n[29]:"";  n2n[30]=0?n2n[30]:"";  n2n[31]=1?n2n[31]:"";  
    n2n[32]=0?n2n[32]:"";  n2n[33]=0?n2n[33]:"";  n2n[34]=1?n2n[34]:"";  n2n[35]=1?n2n[35]:"";  n2n[36]=1?n2n[36]:"";  n2n[37]=1?n2n[37]:"";  n2n[38]=1?n2n[38]:"";  n2n[39]=1?n2n[39]:"";  
    n2n[40]=1?n2n[40]:"";  n2n[41]=1?n2n[41]:"";  n2n[42]=1?n2n[42]:"";  n2n[43]=1?n2n[43]:"";  n2n[44]=0?n2n[44]:"";  n2n[45]=0?n2n[45]:"";  n2n[46]=0?n2n[46]:"";  n2n[47]=0?n2n[47]:"";  
    n2n[48]=0?n2n[48]:"";  n2n[49]=0?n2n[49]:"";  n2n[50]=0?n2n[50]:"";  n2n[51]=0?n2n[51]:"";  n2n[52]=1?n2n[52]:"";  n2n[53]=1?n2n[53]:"";  n2n[54]=1?n2n[54]:"";  n2n[55]=1?n2n[55]:"";  
    n2n[56]=1?n2n[56]:"";  n2n[57]=1?n2n[57]:"";  n2n[58]=1?n2n[58]:"";  n2n[59]=1?n2n[59]:"";  n2n[60]=1?n2n[60]:"";  n2n[61]=1?n2n[61]:"";  n2n[62]=0?n2n[62]:"";  n2n[63]=0?n2n[63]:"";  
);
function set_layout_nop(n2t, n2n, offset) (
    idx = 0; loop(NOTE_NUM_MAX, (n2t[idx]=0; idx+=1;));
    n2t[64]=64;  n2t[65]=65;  n2t[66]=66;  n2t[67]=67;  n2t[96]=96;  n2t[97]=97;  n2t[98]=98;  n2t[99]=99;
    n2t[60]=60;  n2t[61]=61;  n2t[62]=62;  n2t[63]=63;  n2t[92]=92;  n2t[93]=93;  n2t[94]=94;  n2t[95]=95;
    n2t[56]=56;  n2t[57]=57;  n2t[58]=58;  n2t[59]=59;  n2t[88]=88;  n2t[89]=89;  n2t[90]=90;  n2t[91]=91;
    n2t[52]=52;  n2t[53]=53;  n2t[54]=54;  n2t[55]=55;  n2t[84]=84;  n2t[85]=85;  n2t[86]=86;  n2t[87]=87;
    n2t[48]=48;  n2t[49]=49;  n2t[50]=50;  n2t[51]=51;  n2t[80]=80;  n2t[81]=81;  n2t[82]=82;  n2t[83]=83;
    n2t[44]=44;  n2t[45]=45;  n2t[46]=46;  n2t[47]=47;  n2t[76]=76;  n2t[77]=77;  n2t[78]=78;  n2t[79]=79;
    n2t[40]=40;  n2t[41]=41;  n2t[42]=42;  n2t[43]=43;  n2t[72]=72;  n2t[73]=73;  n2t[74]=74;  n2t[75]=75;
    n2t[36]=36;  n2t[37]=37;  n2t[38]=38;  n2t[39]=39;  n2t[68]=68;  n2t[69]=69;  n2t[70]=70;  n2t[71]=71;
    apply_offset(n2t, offset);
    set_note_name_array(n2t, n2n);
);
function select_layout(layout_num, n2t, n2n, offset) (
    layout_num == 0 ? set_layout_Mm3rdRotated(n2t, n2n, offset)
        : layout_num == 1 ? set_layout_P5thRotated(n2t, n2n, offset)
        : layout_num == 2 ? set_layout_P5th(n2t, n2n, offset)
        : layout_num == 3 ? set_layout_P4th(n2t, n2n, offset)
        : layout_num == 4 ? set_layout_nop(n2t, n2n, offset)
        : set_layout_nop(n2t, n2n, offset);
);
function calc_offset() (
    transpose + octave * 12;
);


// 64パッドの各パッドの状態を管理するための配列 インデックス0は左上 値は変換後の音程(値0はオフ)
pad_state_array = 330; idx = 0; loop(PAD_COUNT, (pad_state_array[idx]=0; idx+=1;));
pad_name_array  = 530; // idx = 0; loop(PAD_COUNT, (pad_name_array[idx]=sprintf("%i", idx); idx+=1;));
// Midi Note Numberを新しいNote Numberに変換するための配列
n2t = 200;
select_layout(layout, n2t, pad_name_array, calc_offset());

function set_pad_state(note_num, val) (
    pad_state_array[n2p[note_num]] = val;
);


// color setting
function set_color_panel_off() (
    gfx_r = 0.17; gfx_g = 0.17; gfx_b = 0.25;
);
function set_color_panel_on() (
    gfx_r = 0.92; gfx_g = 0.88; gfx_b = 0.08;
);
function set_color_label_on() (
    set_color_panel_off();
);
function set_color_label_off() (
    // gfx_r = 0.41; gfx_g = 0.4; gfx_b = 0.03;
    gfx_r = 0.31; gfx_g = 0.3; gfx_b = 0.02;
);
function set_color_panel_zero() (
    gfx_r = 0; gfx_g = 0; gfx_b = 0;
);



// slider
octave_last = octave;
transpose_last = transpose;
layout_last = layout;

@slider

octave_last != octave ? (
    select_layout(layout, n2t, pad_name_array, calc_offset());
    octave_last = octave;
);
transpose_last != transpose ? (
    select_layout(layout, n2t, pad_name_array, calc_offset());
    transpose_last = transpose;
);
layout_last != layout ? (
    layout_last = layout;
    select_layout(layout, n2t, pad_name_array, calc_offset());
);

@block


while 
(
  midirecv(offs, m1, m2) ?
  (
    s = m1&$xF0;
    s == $x90 || s == $x80 ? // note-on or note-off
    (
        n = m2&$xFF; // original note
        c = m1&$xF; // channel
        v = (m2&$xFF00)/256; // velocity
        t = n2t[n]; // transposed note
        m2 = m2+t-n; // apply transposition      

        i = -1;
        while // look for this note|channel already in the buffer
        (
          i = i+1;
          i < buflen && (notebuf[4*i]|0 != n || notebuf[4*i+1]|0 != c);
        );

        (s == $x90 && v > 0) ? // note-on, add to buffer
        (
          set_pad_state(n, t); // pad_state_array[n2p[n]] = t;

          notebuf[4*i] = n;
          notebuf[4*i+1] = c;
          notebuf[4*i+2] = v;
          notebuf[4*i+3] = t;
          i == buflen ? buflen = buflen+1;
        ) 
        : // note-off, remove from buffer
        (
          set_pad_state(n, 0); // pad_state_array[n2p[n]] = 0;

          i < buflen ?
          (
            memcpy(notebuf+4*i, notebuf+4*(i+1), 4*(buflen-i-1));  // delete the entry
            buflen = buflen-1;
          );
        );
    );
    midisend(offs, m1, m2);
  );
);


@gfx 400 400

gfx_x = 0;
gfx_y = 0;

// clear canvas
gfx_w = PAD_COLS*RECT_SIZE; gfx_h = gfx_w;
set_color_panel_off();
gfx_rect(0, 0, PAD_COLS*RECT_SIZE, PAD_COLS*RECT_SIZE);

function draw_pad_label(label)(
    gfx_setfont(1, "Arial", 36);
    tmp_x = gfx_x; gfx_x += 4;
    tmp_a = gfx_a; gfx_a = text_alpha;
    gfx_drawstr(label, 8, gfx_x+RECT_SIZE, gfx_y+RECT_SIZE);
    gfx_a = tmp_a;
    gfx_x = tmp_x;
);
function draw_pad_label_num(num)(
    gfx_setfont(1, "Arial", 24);
    tmp_x = gfx_x; gfx_x += 4;
    tmp_a = gfx_a; gfx_a = text_alpha;
    gfx_printf("%i", num);
    gfx_a = tmp_a;
    gfx_x = tmp_x;
);
// draw note-on pad
idx = 0; loop(64, 
    next_x = gfx_x + RECT_SIZE;
    label = pad_name_array[idx];
    (pad_state_array[idx]>0) ? (
        // rect
        set_color_panel_on();
        gfx_rect(gfx_x+1, gfx_y+1, RECT_SIZE-1, RECT_SIZE-1);
        // label text color
        set_color_label_on();
        // draw_pad_label(label);
        draw_pad_label(get_note_name(pad_state_array[idx]));
    ) : (
        // label text color
        set_color_label_off();
        draw_pad_label(label);
    );
    // draw_pad_label(get_note_name(pad_state_array[idx]));
    // draw_pad_label_num(label);
    gfx_x = next_x;
    (PAD_COLS-1) == (idx % PAD_COLS) ? (
        gfx_x = 0;
        gfx_y += RECT_SIZE;
        );
    idx += 1;
);

// draw grid
set_color_panel_zero();
idx = 0; loop(9,
    unit = idx*RECT_SIZE;
    last = RECT_SIZE*PAD_COLS;
    gfx_x = unit; gfx_y = 0;
    end_x = unit; end_y = last;
    gfx_lineto(end_x, end_y);
    idx += 1;
);
idx = 0; loop(9,
    unit = idx*RECT_SIZE;
    last = RECT_SIZE*PAD_COLS;
    gfx_x = 0;    gfx_y = unit;
    end_x = last; end_y = unit;
    gfx_lineto(end_x, end_y);
    idx += 1;
);

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?