[TOP][シンセサイザ技術][CMU-800関連][DCB関連][電子楽器・電子工作等] | ||
[さるべーじ][ばいく][リンクなど] | [戻る] |
今後CMU-800の駆動をやってみようという人(がいるかは不明ですが)に、「こんなしょぼいプログラムでもMIDI化できるぞ」という応援と「こんなことはやっちゃいけない」という教訓になればと思い、コントロールプログラムの解説です。ただし、このプログラム、一部のMIDIインターフェースで誤動作することを確認しています。MIDIデコード部分は参考にならないかもしれません 右がプログラムの全体の流れです。MIDIのデータ受信は割り込みを使い最優先で行い、MIDIメッセージのデコードや音源の駆動はメインループで暇な時にやっています。 CVは4051で構成したS/Hで保持しているので、常に値を入れてあげないと電圧が下がってくるのでメインループに入れています。PIT(8253)の設定は、MIDIデコードルーチンのNote-ONだった時に入れています。 MIDIデータ受信
SCIの割込みで受信バッファにデータを積み、すぐにメインループに戻っています(ソースのGET_MIDIルーチン)。MIDIデータは取り逃すと即誤動作に繋がるので、最優先で処理しています。
受信バッファはプログラムによる擬似FIFOで、とりあえず64バイト確保しています。H8のCPUパワーのおかげか、あんまりきっついMIDIデータを送ってないのか、ウチではオーバーフローを起こしていません。また、R5はFIFOリードカウンタ専用、R6はFIFOライトカウンタ専用になっています。FIFO以外のルーチンで使用してないので退避等の処理は一切してません。バッファサイズは2の倍数にして、FIFOカウンタをANDでマスクを掛けているのでのオーバーフローチェックもしてません。エラー処理も、FIFOのオーバーフローか、SCIエラーがでたら強制リセットするだけです。かなり適当です。
MIDIデータデコード1(メッセージの分離) すでにバグが潜んでいる事が確からしいMIDIデコードルーチンです。変な所があったら教えていただければ有り難いです。 そもそもMIDIフルスペックを考えてないのでかなりはしょってます。システムエクスクルーシブ開始(F0)受信から終了(F7)受信まで、及び頭がFで始まる、コモン&リアルタイムメッセージは全部無視してます。 MIDIメッセージは1〜3バイトの可変長なので、受信したデータを一度MIDIメッセージバッファに置き、最終バイトを受信後に音源のアサインルーチンに飛びます。
すでにコモン&リアルタイムメッセージは取り除いているので、データの頭に1が立っていたら(80hより大きかったら)1バイト目ですので、メッセージバッファの1バイト目にデータを置き戻ります。それ以外は、2バイト目もしくは3バイト目になります。 MIDIデータデコード2(ボイスアサイン)
まず、Note-OFFだった場合、MIDIメッセージバッファをNote-ONのベロシティ0に変更します。これは、MIDIの仕様でNote-ONベロシティ0は、Note-OFFと解釈せよとあるからです。(発音停止がNote-Onで表現できると、発音→停止にランニングステータスが使えるからだと思います。) ノート番号の補正は、CVを0V=Cにチューニングしたときにあわせています。次に、Note-Onかつ、CMUのチャンネルだった場合それぞれのアサインルーチンに飛びます。
リズムトリガーは、まずPPIのポートをクリアします。次に受信ノートに対応した太鼓のPPIポートをOnにして戻ります。頭でPPIをクリアしている理由はこれです。リズム音源をトリガする時間を計算するのが面倒だったのでへぼい処理をしているためです。
ポリトリガーは、ボイスアサインカウンタをくるくる回し、空きボイスだったら発音します。発音中だったら次を捜しカウンタが一周したらそのボイスで発音します。発音停止は、ボイスを順番にみて受信ノートが発音中だったら止めます。 PITとPPIの設定 音程の周波数は、ベース周波数×2^(ノート/12)という式になります。さらにPITには分周比を入れなくてはいけないため計算が厄介ですので、分周比テーブルを使用しています。低音ほど分周比が高い(数値が大きい)ので、最低音の1オクターブ分のテーブルを用意してそれを元に計算しています。 まず、ノート番号をオクターブとノート(12音階)に分離します。H8には割り算命令があるので簡単です。ノートに対応した分周比をテーブルより持ってきて、オクターブ分ビットシフト(2倍)しています。後は、出てきた値をPITに突っ込んでいるだけです。 アナログシンセでは、生楽器の様に高音部はちょっと高め、低音部ではちょっと低めにチューニングをしたりするのですが、これはそういった処理は一切していません。
CV/GATEは、PPIのポートBからデータを、ポートCからチャンネルとストローブを出しています。ですので、ポートBに出力するビットマップ(CVとGate)をそのままMIDIデコードルーチンで使用し、わざわざ生成しなくていいようにしています。MIDIデコードルーチンの発音バッファの値をそのまま出力PPIに出力できます。 その他 MIDIチャンネルの設定は、起動時にH8のP8xから順番にビットを立ててPBxから読み込んでいます。本当は、ソフト的にやったほうがスマートでコストもかからないと思いますが、個人的な趣味でロータリースイッチを使っています(これだと、どれが何チャンネルなのかすぐわかりますし、設定方法を忘れる心配も無いので…、でもロータリースイッチ6個分でCPUカードより高いです)。試作の段階では、自照式ドットマトリクスディスプレイと、設定キーを付けて色々な設定が出来る様になっていたのですが、ディスプレイとスイッチをつける穴を開けるのが面倒だったので取っちゃいました。(ただ、ソースには若干痕跡が残ってるかもしれません。) 以上です。開発中は、ローランドのシリアルMIDIドライバをPCに入れ、H8側のSCIクロックをPCにあわせ(38400b/s)行いました。MIDI端子をつけてしまうと、シリアル経由でのファームの流し込みやデバッグが厄介なので、動作が安定するまではシリアルドライバで動かすといいかもしれません。(おかげで、ローランドのUSBインターフェースで誤動作するというバグに気づかなかったのですが。) |
このサイトは特に断りのあるコンテンツを除きリンク・転載フリーです。うるさい事は言いません。 | ||
(c)1995-2017 LITZHAUS |