MIDIシーケンサー(レコーダー/プレイヤー)の作成

2008.3.30 プログラム修正
2001.3.3 公開



はじめに

今から十数年前「パソコン通信」が全盛の頃、PC(NECのPC98)でシンセサイザーを演奏させたい*1と思い、MIDIの世界に足を踏み入れました。当時、手頃なマルチティンバーユニットとしてRolandのMT-32*2を購入して、暇をみてはMIDIデータの「打ち込み」(クラシック曲が多かったです)をしてパソ通のMIDIフォーラムに投稿したり、その後はRolandのCM-64、SC-88と機種を更新していきましたが、最近は根性が続かなくなったこともあり、DTMからは遠ざかっていました。
昨年、子供の情操教育?も兼ねてカシオのLK-60キーボードを購入してから再びDTMにぼちぼちと復活しています。このキーボードは「光ナビ」というモノで、キーが光って次に弾くキーを教えてくれるため演奏の練習にもなり、子供にも好評です。
出来のいい演奏は記録しておきたいのですがLK-60には残念ながら録音機能が無いため、外付けのレコーダーを買うか、PCに接続してシーケンサーで記録する必要があります。
いちいちPC側で記録操作するのも面倒ですし、キーボードを持ち歩けなくなるので、PIC工作で簡単なシーケンサーを作ってみることにしました。

*1 富田勲とかジャン・ミッシェル・ジャールとかYMOとか・・・そういう世代の人です(^^)
*2 「ミュージ君」シリーズでヒットしましたねー。

MIDIとシーケンサについて

MIDI(Musical Instrument Digital Interface)とは読んで字のごとく、異なる楽器やシーケンサー等を接続して演奏情報をやりとりするための規格を指します。パソコンの世界では大方MIDIインタフェースと音源を接続して演奏させたり、SMF(標準MIDIファイル)までひっくるめて言う事が多いようですが、MIDIポートを利用した外部機器のコントロールやデータ取得のようにシリアルインタフェース的な使い方など、別の応用も可能です。

MIDIインタフェースによる通信は31.25Kbit/secの非同期シリアル(歩調同期方式)で動作し、1バイトのMIDIデータ(MIDIバイト)は、スタートビット+ビット0〜ビット7+ストップビットの計10ビットで転送されます。次々送られてくるMIDIメッセージ(複数のMIDIバイトで構成される指示)を受信した機器は、そのMIDIメッセージに従って音源の設定や発音などの処理を行います。

つまり、最も簡単なシーケンサを作るには、MIDIインタフェースを通じて送られたシリアルデータをそのまま保存と送信ができれば良いわけです。一つ注意しなければいけないのは、データの間に任意の空白時間(次のメッセージまでの時間;音符の長さや、休符の長さなどを意味する)が存在し、このタイミングもちゃんと再現できなければ演奏のテンポが狂ってしまうという点で、この時間情報は例えばSMFファイルではデルタタイム(dt)というデータによって表現されています。

シーケンサの概要

マイクロコントローラーはPIC16F84(これしか使ったことない・・)、メモリには以前買い置きしておいたシリアルメモリ(24LC256)を使うことにしました(CMOSのEEPROMですので、電源を切ってもデータは保持されます)。

上記のようにMIDIデータの1バイトは320usで送られてきますが、シリアルメモリのWriteには少々時間がかかるため、条件(デルタタイムに続きMIDIデータが連続した場合など)によっては3バイト以上を一気にWriteしなければならず、RandomWriteシーケンスでは書き込みが間に合わなくなりデータの取りこぼしが起きてしまうことがわかりました。
そこで、PIC内に32bytesのバッファを設け、メモリの書き込みにはPageWriteシーケンスを併用することにより、ある程度連続データが来てもバッファに溜めておき、メモリには最大32bytesをまとめて書き込む方法を取ることで何とか問題は回避できそうな見込みが立ちました。

スタートビットの検出後、1bitあたり32usの割り込み処理によって1バイトのデータを受信し、これをバッファに逐次転送します。割り込みが発生していない時はこのバッファを監視してメモリへの転送とメモリ内部の書き込みサイクル発動を制御します。

MIDIデータが来ていない時は約1ms毎にdtをカウントしておき、次のデータが来た時に、dtとそれに続けて受信データをメモリに記録します。メモリに記録する形式として、通常のMIDIバイトとdtを区別するために、RealTimeMessageのうちMIDI規格では未定義とされているIDを勝手に使い、これをdtのインジケータとしました。

回路図

回路図(1000*750gif 17kb)

PIC16F84(10MHz)とメモリ(24LC256:32KB)、フォトカプラ、の他はSW,LED,R,Cくらいの簡単な回路です。
24LC256は1個〜最大8個(32KB〜256KB)までI2Cバスに追加することができます。
MIDI INは割り込みのトリガとして使うため、INT/RB0に接続します。

プログラム

(2008.3.30)
イタリアのAldo氏よりバグと改善要望の報告を頂きました。
(1)PLAY/STOPを繰り返すとメモリの不正な位置から再生される場合がある
(2)再生途中のSTOPでノートオフを送出した方がよい

(1)はI2Cのアクセス停止タイミングが悪かったので修正
(2)はSTOP時に全チャンネルにAll-Notes-Offを送出するように修正
(3)その他、アセンブラをPAからCVASMに変更

ソース+Hexファイル 修正版(midirec2.zip 8kb)

MIDIデータの記録・送信では、データビット送受信のため、31.25kHz(32us)のタイマ割り込みを使用します。dtの計測もこの32usをベースにカウントします。記録時には受信と平行してバッファへの書き込みやメモリへの転送を行うため、かなりギリギリの処理となっています。(プログラミングがヘタクソなせいでもありますが(^^;)ゞ

記録の処理に関して、dtのカウントもタイマ割り込みで行った関係上、dtのカウント処理中にスタートビットが来た場合、データ受信に十数usの遅延が発生してしまいます。何度か実験してうまく動作するように調整しましたが、使用するMIDIインタフェース機器によっては受信データにエラーが混入してしまう場合があるかもしれません。(私の使用しているRoland UM-2では全く問題ありませんでしたが)

再生に関しては処理的にも余裕がありきちんとタイミングが取れているので、どの機器に接続しても大丈夫だと思います。
オマケとして再生時にdtのカウントベースを変更できるようにして、テンポを速くしたり遅くしたりの調整機能をつけてみました。

初期化処理でメモリの接続状況を調べるようにしたので、ソケットを何個か余分に取り付けておくとメモリの追加を自由に行うことができます。

ケースの作成

これまで、ケースは市販の物を使ったりアクリル板で自作することがありましたが、今回は初めて発泡塩ビ板(商品名:セルラ)を使って制作してみました。
たまたまホームセンターで見かけたので購入したのですが、工作がとても簡単で仕上がりもまずまずなので、もしご存じない方がいらっしゃったら、一度使ってみてはいかがでしょうか。

工作の感想ですが、

○ 切るのが簡単 カッターで楽に切れる
○ 簡単に曲げ加工が出来る
○ ドリルで穴を開けても割れない
○ 接着も楽で意外と強度がある(専用の接着剤を使用)
○ プラモデルのように塗装できる
○ 軽い
× 普通のプラスチックより柔らかいので表面が傷つきやすい
× 発泡素材なので表面に微妙な凹凸がある
× アクリルのような透明色がない

と、短所もありますが用途によって使い分ければかなり楽しい素材です。

下図のように2mm厚の板を使って基板に合わせた大きさのケースを作り、塗装とインレタで文字入れしてみました。

 

 

操作等

 

さいごに

ケースの出来も意外に良く、手のひらサイズに仕上がったので、今まで作った中でもお気に入りの作品となりました。
最近はVBにも手を出し始めたので、Windowsのアプリを作ってこれを制御したり、SMFの転送・再生など出来たら面白いなぁと思っています。(SMF再生はPIC16F84だと荷が重すぎる気がするので、別の種類がいいんでしょうか・・?)


*参考文献 MIDI 1.0規格書(MIDI規格協議会)


戻る