2005年03月09日(水)の日記
可変長16進数表記への変換
SMFにおける可変長16進数への変換の関数が、
検索しても2バイトまでとか中途半端なものしかなかったので自作。
SMFでは可変長16進数は最大4バイトまでなのでそれ以上になる値は弾く。
コードの横幅節約のためにビット演算のオペランドに16進数を用いたので読みにくいかもしれませんが、
変換アルゴリズム(というほどたいそうなものか分かりませんが)はコードの下に書いてあります。
検索しても2バイトまでとか中途半端なものしかなかったので自作。
SMFでは可変長16進数は最大4バイトまでなのでそれ以上になる値は弾く。
コードの横幅節約のためにビット演算のオペランドに16進数を用いたので読みにくいかもしれませんが、
変換アルゴリズム(というほどたいそうなものか分かりませんが)はコードの下に書いてあります。
unsigned int variableLength(unsigned int unsignedInt) {
enum { HTBMIDIInvalidValue = 0xFFFFFFFF };
if (unsignedInt <= 0x7F) return unsignedInt; /* 0x7F以下ならそのまま。 */
else if (unsignedInt > 0x0FFFFFFF) return HTBMIDIInvalidValue;
/* 0x0FFFFFFFを超える数字は4バイト以内で表せない。 */
else {
/* ↓変数bnは最下位からn番目のバイトの値 */
unsigned int b1 = unsignedInt & 0x7F;
unsigned int b2 = ((unsignedInt & 0x3F80) << 1) | 0x8000;
if (unsignedInt <= 0x3FFF) return b1 + b2;
else {
unsigned int b3 = ((unsignedInt & 0x1FC000) << 2) | 0x800000;
if (unsignedInt <= 0x1FFFFF) return b1 + b2 + b3;
else {
unsigned int b4 = ((unsignedInt & 0x0FE00000) << 3) | 0x80000000;
return b1 + b2 + b3 + b4;
}
}
}
}
▼結果が1バイトとなる場合 = 0x7F以下
そのまま
▼結果が2バイトとなる場合 = 0x3FFF以下
00aa bbbb cccc dddd (bit表記)
↓
1aab bbbc 0ccc dddd
▼結果が3バイトとなる場合 = 0x1FFFFF以下
000a bbbb cccc dddd eeee ffff
↓
1abb bbcc 1ccd ddde 0eee ffff
▼結果が4バイトとなる場合 = 0x0FFFFFFF以下
0000 aaaa bbbb cccc dddd eeee ffff gggg
↓
1aaa abbb 1bcc ccdd 1dde eeef 0fff gggg
そのまま
▼結果が2バイトとなる場合 = 0x3FFF以下
00aa bbbb cccc dddd (bit表記)
↓
1aab bbbc 0ccc dddd
▼結果が3バイトとなる場合 = 0x1FFFFF以下
000a bbbb cccc dddd eeee ffff
↓
1abb bbcc 1ccd ddde 0eee ffff
▼結果が4バイトとなる場合 = 0x0FFFFFFF以下
0000 aaaa bbbb cccc dddd eeee ffff gggg
↓
1aaa abbb 1bcc ccdd 1dde eeef 0fff gggg
この日記へのトラックバック
この日記へのトラックバックはありません。
この日記へのコメント