PiSTARTERでUARTをループバックさせて、MIDIメッセージを入力するテスト Part.2(生データ高速版)
1.はじめに
前回の改良として、生データのままSmileBasicへ送信するように変更したところ、遅延がかなり改善されましたヾ(*´∀`*)ノ
あと、コマンドプロンプトを使わず、SmileBasicのSYSTEM$()コマンドで、MIDI-INからのメッセージをUARTに転送するコマンドを自動起動するようにしたので、ソフトウェア的な前準備が要らなくなりました(≧∇≦)b
2.準備
下記の通り、ハードウェアの準備だけでOKです。
3.PiSTARTER(smilebasic)のプログラム
以下のプログラムを実行すると、MIDI-INから入力したノートオン/オフメッセージに従い、ピアノロールが表示されます。なお、キーボードで0~9/a~fを押すと、指定したチャネルの表示/非表示を変更可能です。
' 'UARTからMIDIメッセージを受信するテスト(生データ版) by みなつ ' option strict '画面初期化 acls var gw=1280,gh=1024 'GRP Width,Height var sw=1280/4,sh=720/4 'SCREEN Width,Height xscreen sw,sh '以前に起動したプロセスがあればkillする var dq$=chr$(&h22) ?system$("sudo /bin/sh -c "+dq$+"/bin/ps auxww|/bin/grep '/bin/cp /dev/snd/midiC1D0'|/bin/grep -v grep|/usr/bin/awk '{print \$2}'|/usr/bin/xargs -r /bin/kill"+dq$) 'MIDIメッセージをシリアルに出力するプロセスをバックグラウンドで起動 ?system$("sudo /bin/sh -c '/usr/bin/nohup /bin/cp /dev/snd/midiC1D0 /dev/serial0 > /dev/null 2>&1 &'") 'シリアルポートをスタート uartstart 4000000 '変数定義 var i dim rx[1024] 'UART受信バッファ var s 'UARTからの受信サイズ var KR$=chr$(&h1c),KL$=chr$(&h1d),KU$=chr$(&h1e),KD$=chr$(&h1f) 'ピアノロール表示パラメータ var gw2=gw/4,gh8=gh/8 dim mute[16] dim chCol[16] dim chR[16],chG[16],chB[16] for i=0 to 15 var br=255-64-((i>>3) and 1)*64 var r=((i>>2) and 1)*255 var g=((i>>1) and 1)*255 var b=((i>>0) and 1)*255 chR[i]=r+br chG[i]=g+br chB[i]=b+br chCol[i]=rgb(r+br,g+br,b+br) next var ox=0,last_cnt gpage 0,1 sppage 1 while true '0〜9、a〜fで、指定チャネルの表示/非表示切り替え var k$=inkey$() if k$!="" then var m=instr("0123456789abcdef",k$) if m!=-1 then mute[m]=!mute[m] endif endif 'UARTからMIDIメッセージを受信 uartrecv rx out s for i=0 to s-1 if !(rx[i] and &h80) then continue 'データバイトをスキップ var cmd=rx[i] and &hf0 var ch=rx[i] and &hf var note=rx[i+1] var vel=rx[i+2] var gx=(ch div 8)*gw2+ox var gy=(ch mod 8)*gh8 if cmd==&h90 || cmd==&h80 then '&h8n [note] [velocity] (nはチャンネル番号):ノートOFF '&h9n [note] [velocity] (nはチャンネル番号):ノートON vel=vel*!!(cmd==&h90) var v=vel/127 gpset gx,gy+gh8-1-note,rgb(chR[ch]*v,chG[ch]*v,chB[ch]*v)*!!v elseif cmd==&hb0 && (note==&h78 || note==&h7b) then '&hBn &h78 (nはチャンネル番号):オールサウンドオフ '&hBn &h7B (nはチャンネル番号):オールノートオフ gline gx,gy,gx,gy+gh8-1,0 endif next '描画位置を1ドット右に変更し、画面を1ドット左にスクロール var cnt=maincnt if last_cnt!=cnt then last_cnt=cnt var nx=(ox+1) mod gw2 gcopy ox,0,ox,gh-1,nx,0,1 gcopy gw2+ox,0,gw2+ox,gh-1,gw2+nx,0,1 view_scroll (ox+2) mod gw2 ox=nx endif wend '画面(スプライト)を指定位置にスクロール def view_scroll x var sclX=sw/gw2 var ch for ch=0 to 15 var sp=ch*2 if mute[ch] then if spused(sp) then sphide sp if spused(sp+1) then sphide sp+1 continue endif var gx=(ch div 8)*gw2 var gy=(ch mod 8)*gh8 spset sp,gx+x,gy,gw2-x,gh8,1+#spadd spofs sp,0,0 spcolor sp,rgb(200,255,255,255) spscale sp,sclX,sh/gh8 if x>0 then spset sp+1,gx,gy,x,gh8,1+#spadd spofs sp+1,(gw2-x)*sclX,0 spcolor sp+1,rgb(200,255,255,255) spscale sp+1,sclX,sh/gh8 else if spused(sp+1) then sphide sp+1 endif next end