brainChucK
名前から思いついたというか、名前だけ思いついたけど後は特に思いつけなかった。brainfuckを元にしてChucKで音を鳴らす。
ChucKの制約のために変更した仕様
- brainfuckコードの扱い
ChucKでは文字列操作がほとんどできないので、brainfuckの8種類の命令><+-.,[]はそれぞれ命令01234567に変換して、各命令をint型配列の要素へ直接格納することにした - メモリ領域の要素の型
ChucKにはbyte型が用意されていないので、int型で代替した
音を扱うために変更した仕様
- データの扱い
メモリ領域の各要素にある数値は音高(MIDIノート番号)とみなす - 命令4(.)のときの出力方法
ポインタの指している要素にある音高の音を1秒間鳴らす - 命令5(,)のときの入力方法
PCのキーボードの代わりにMIDIキーボードで音高を入力する
ChucKのプログラム。各種数値の範囲チェックなし。ここではbrainfuckコードとして、Hello worldを変換して使った。
second => dur T; MidiIn min; MidiMsg msg; if ( !min.open(0) ) me.exit(); SinOsc s => ADSR e => dac; .1 => s.gain; e.set(ms, .1::T, .3, .2::T); 1 => e.keyOff; [ // ここに変換したbrainfuckコードを格納する // Hello, world! 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 1, 1, 1, 3, 7, 0, 4, 0, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, // Hel 4, 2, 2, 2, 4, 0, 3, 4, // lo, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, // 1, 2, 2, 2, 2, 2, 2, 2, 2, 4, // w 3, 3, 3, 3, 3, 3, 3, 3, 4, 2, 2, 2, 4, // or 3, 3, 3, 3, 3, 3, 4, // l 3, 3, 3, 3, 3, 3, 3, 3, 4, 0, 2, 4 // d! ] @=> int code[]; int memory[1000]; int pointer; for (int ip; ip < code.cap(); ip++) { if (code[ip] == 0) { // > 1 +=> pointer; } else if (code[ip] == 1) { // < 1 -=> pointer; } else if (code[ip] == 2) { // + 1 +=> memory[pointer]; } else if (code[ip] == 3) { // - 1 -=> memory[pointer]; } else if (code[ip] == 4) { // . memory[pointer] => Std.mtof => s.freq; 1 => e.keyOn; .8::T => now; 1 => e.keyOff; .2::T => now; } else if (code[ip] == 5) { // , int isIn; min => now; while (min.recv(msg)) { // ノートオンかつベロシティが0以外のとき if (msg.data1 == 144 && msg.data3) { // ポインタの指している要素に音高を格納 msg.data2 => memory[pointer]; true => isIn; break; } } if (!isIn) 1 -=> ip; } else if (code[ip] == 6) { // [ if (memory[pointer] == 0) { 1 => int depth; while (depth != 0) { 1 +=> ip; if (code[ip] == 6) 1 +=> depth; else if (code[ip] == 7) 1 -=> depth; } } } else if (code[ip] == 7) { // ] if (memory[pointer] != 0) { 1 => int depth; while (depth != 0) { 1 -=> ip; if (code[ip] == 6) 1 -=> depth; else if (code[ip] == 7) 1 +=> depth; } 1 -=> ip; } } }