MIDI音源の実装方法について
音源を自作する際のメモ書きです。
アクティブセンシング
アフタータッチ ポリフォニックキープレッシャー チャンネルプレッシャー
ビブラート
ピッチベンド
ポルタメント
音源の発音の仕組みを実装する
MIDI音源では同時発音数の制限があります。
これは単音を生成する発振器が何個内蔵されているかということです。
以下、発振器を「ボイス」と表現します。
ポリフォニックモード
和音を発音可能なモードです。
特定のチャンネルに来たメッセージにより、ボイス数の許す限り発音されます。
ボイス数が3として例を書いています。
初期化
フリーボイス配列を用意する
発音可能なボイスを記憶する配列。
内容はボイスナンバー(1~)とし、0の値が入っている場合は割当不可とする。
配列 | 内容 | 概要 |
---|---|---|
0 | 1 | ボイス1は使用可能 |
1 | 2 | ボイス2は使用可能 |
2 | 3 | ボイス3は使用可能 |
配列数はボイス数と同等用意する。
ボイスノート配列を用意する
発音中のノートナンバー、発音状態を記憶する配列。
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | -1 | ボイス1の発音状況 |
1 | -1 | ボイス2の発音状況 |
2 | -1 | ボイス3の発音状況 |
配列のインデックス+1の値がボイスナンバー。
配列数はボイス数と同等用意する。
内容はsignedで持ち、ノートナンバーは0~127の値を取るため、それ以外の値(例:-1)を発音無しとする。
ラストボイス変数を用意する
最後に発音したボイスナンバーを記録する変数
ノートONメッセージを受信
例としてノートナンバー60のノートONメッセージを受信し、ボイス1で発音する際の処理内容です。
発音可能なボイスがあるかどうかを確認
具体的にはフリーボイス配列の先頭0番目を参照する。
ここで、値が1~であれば、ボイスが有効なため、発音処理が可能です。
発音処理が可能な場合
フリーボイス配列の先頭から発音可能なボイスナンバーを取得
先頭の内容は1のため、ボイス1が使用可能。
配列は先頭以降の内容を前方に移動させる。
配列 | 内容 | 概要 |
---|---|---|
0 | 2 | ボイス2は使用可能 |
1 | 3 | ボイス3は使用可能 |
2 | 0 | ボイスは使用不可能 |
ボイスノート配列に発音状態を代入
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | 60 | ボイス1の発音状況 |
1 | -1 | ボイス2の発音状況 |
2 | -1 | ボイス3の発音状況 |
ラストボイス変数に代入
最後に使用したボイスナンバー1を代入する
ここまででMIDIの内容が処理しおわりました。
ボイス1に対して、発音処理を行います。
ノートOFFメッセージを受信
例としてノートナンバー60のノートOFFメッセージを受信し、ボイス1の発音を取り消す際の処理内容です。
ボイスノート配列からノートナンバーを検索
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | 60 | ボイス1の発音状況 |
1 | -1 | ボイス2の発音状況 |
2 | -1 | ボイス3の発音状況 |
頭からノートナンバーを検索します。
今回は60なので配列0番目で一致します。
配列のインデックス+1がボイスナンバーのため、ここでボイス1と分かります。
ボイス1の発音処理を停止します。
ボイスノート配列内容の書き換え
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | -1 | ボイス1の発音状況 |
1 | -1 | ボイス2の発音状況 |
2 | -1 | ボイス3の発音状況 |
発音状況を書き込みます。
フリーボイス配列に発音可能ボイスを追加
配列 | 内容 | 概要 |
---|---|---|
0 | 2 | ボイス2は使用可能 |
1 | 3 | ボイス3は使用可能 |
2 | 0 | ボイスは使用不可能 |
配列の先頭から0を探し、今回空いたボイス1を書き込みます。
配列 | 内容 | 概要 |
---|---|---|
0 | 2 | ボイス2は使用可能 |
1 | 3 | ボイス3は使用可能 |
2 | 1 | ボイス1は使用可能 |
次回のノートONが行われる際には、先頭にあるボイス2が使用されます。
ノートONメッセージを受信(ボイス上限時)
例としてノートナンバー60, 64, 67のノートONメッセージを受信している状態で、ノートナンバー72を受信した際の処理内容です。
発音可能なボイスがあるかどうかを確認
具体的にはフリーボイス配列の先頭0番目を参照する。
配列 | 内容 | 概要 |
---|---|---|
0 | 0 | ボイスは使用不可能 |
1 | 0 | ボイスは使用不可能 |
2 | 0 | ボイスは使用不可能 |
すでに3ボイス使用していて、発音可能なボイスは存在しない。
発音処理が不可能な場合
ラストボイス変数から最後に使用したボイスナンバーを取得する
現状でこのようなボイスノート配列になっている。
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | 60 | ボイス1の発音状況 |
1 | 64 | ボイス2の発音状況 |
2 | 67 | ボイス3の発音状況 |
つまり、ラストボイス変数の内容はボイス3を表す3となる。
最後に使用したボイスを発音停止
ラストボイス変数から最後に使用したボイスが3ということがわかりました。
ボイス3の発音を停止させます。
ボイスノート配列内容の書き換え
新しく来たノートナンバーは、最後に使用したボイスで発音します。
ボイス3で新しいノートナンバーを発音します。
配列 | 内容(ノート) | 概要 |
---|---|---|
0 | 60 | ボイス1の発音状況 |
1 | 64 | ボイス2の発音状況 |
2 | 72 | ボイス3の発音状況 |
発音状況を書き込みます。
モノフォニックモード
単音のみ発音可能なモードです。
残念ながらポリモードと同様に複雑です。
押さえられてるキーを記憶しておく必要があるためです。
初期化
スタック配列を用意する
十分な数を用意しておく
スタックポインタ変数を用意する
ノートONメッセージを受信
スタック配列にノート番号を追加していく
1番目にすでにノート番号が入っていれば、その次に追加していく
スタックポインタはノート番号が追加されるたびにインクリメントされていく
ノート番号はその都度おくられる
ノートOFFメッセージを受信
スタック配列の最後からノート番号を検索する
配列にあった場合には、削除して、残りの内容は移動される
スタックポインタをデクリメントする
スタックポインタが指す位置にノート番号がある場合は、その発音に切り替える
ノート番号が無い場合(押されている鍵盤が存在しない状態)では発音をOFFにする
参考リンク