LoginSignup
3
2

More than 5 years have passed since last update.

8bitバイナリを7bitバイナリ列にする

Last updated at Posted at 2017-09-24

MIDIメッセージのデータ

MIDIの通信で使われるMIDIメッセージは1バイトづつシリアルで送られます。この中で命令を指すステータの部分はbit7 がHi ,データ部分はbit7がLo と決められています。bit7=Hiのバイトのデータはそのままでは通信に使えません。

システムエクスクルーシブ

MIDIのメッセージに任意のデータ列を送るためのシステムエクスクルーシブメッセージがあります。他のメッセージと同じく F0h で始まり F7h で終わる一連のバイト列ですが、その間のデータ部分も必ずbit7=Loでないといけません。送りたいデータ列が普通のバイナリデータでもbit7をLoにした変換処置をして送出/受取しないといけないわけです。

8bit->7bit , 7bit->8bit

今回YMF825boardを使ったシンセサイザモジュールを作るにあたり、音色データをシステムエクスクルーシブメッセージで送る様な機能がどうしても必要になると考えました。
このため8bitデータ列を7bitデータ列に変換/戻す処理が必要になるわけです。この手の処理コードは以前は雑誌の記事か、どこかのサイトに転がっていたと記憶するのですが、最近は用途もない様で検索しても見つかりませんでした。そこで改めてコードを書いてみました。何か役に立てれてばとお思います。無保証ですが自由にお使い下さって結構です。

int encode87(unsigned char* src,unsigned char* dst,int n)

8bitデータ列 7バイト分を7bitデータ列8バイトへ変換します

src : 変換元ポインタ
dat : 変換先ポインタ
n : 変換データバイト数

int decode87(unsigned char* src,unsigned char* dst,int n)

7bitデータ列 8バイト分を8bitデータ列7バイトへ変換します

src : 変換元ポインタ
dat : 変換先ポインタ
n : 変換データバイト数

やっている事は 7バイトのデータ列の各々8bitめを8バイト目の各bit0-bit6へ格納して一連のデータ列に変換しています。デコード時はその反対の処理を行います。
これで任意のバイナリーデータをMIDIシステムエクスクルーシブメッセージの中に入れ込む事ができます。

byt78.c

/*

    8bit Binary String  <->  7bit Binary String

    Ringoro

*/

#include <stdio.h>

unsigned char indata[]={0x85,0x85,0x85,0x81,0x85,0x82,0x88,
            0x71,203,135,230,122,232,0x80,
            0x71,203,135,230,122,232,0x00,
            0x81,110,120,230,100,100,0xFE,
            0x81,0x92,0x12};

unsigned char outdata[sizeof(indata) * 8 / 7 + 1];
unsigned char decoded[sizeof(indata)];

int encode87(unsigned char* ,unsigned char* ,int );
int decode87(unsigned char* ,unsigned char* ,int );

int main()
{
    int max,c,i,j,n,pt;
    unsigned char b8;

    max=sizeof(indata);     // max input data count
    pt = 0;                 // data out point

    n = encode87(indata,outdata,max);


    puts("");
    for(i=0;i<max;i++){
        printf("%02X",indata[i]);
        if( (i % 7)== 6)
            {printf("  ");}
    }
    puts("");
    for(i=0;i<=n;i++){
        printf("%02X",outdata[i]);
        }

    n = decode87(outdata,decoded,n);

    puts("");
    for(i=0;i<n;i++){
        printf("%02X",decoded[i]);
        if( (i % 7 ) == 6 )
            {printf("  ");}
        }
    puts("");


}

/*
    encode 8bit x 7  to 7bit x 8
    src : input data ponter.
    dst : output data pointer.
    max : input data bytes.
    return : encoded data bytes.
*/
int encode87(unsigned char *src,unsigned char *dst,int max)
{
    int n,i,pt;
    unsigned char b8;
    pt = 0;
    n=0;
    while(n < max){
        b8=0;
        for(i=0; i<7 && n < max;i++,n++){
            *(dst+pt)=*(src+n) & 0x7F;
            // printf("%02X ",*(src+n));
            pt++;
            b8= b8 | ((*(src+n) & 0x80) >> 7) << i;
            // printf("%02X ",b8);
            }
        *(dst+pt++)=b8;
        //printf("%d ",pt);
    }

    return pt-1;

}

/*
    decode 7bit x 8 to 8bit x 7
    src : input data ponter.
    dst : output data pointer.
    max : input data bytes.
    return : encoded data bytes.
*/
int decode87(unsigned char *src,unsigned char *dst,int max)
{
    int n,i,j,pt;
    unsigned char b8;
    pt = 0;
    n=0;
    while(n < max){
        for(i=0; i< 7 && n < max;i++,n++){
            *(dst+pt)=*(src+n);
            pt++;
            }
        b8=*(src + n++);
        // printf("n:%d  B8:%02X \n",n,b8 );
        for(j=0;j<i;j++){
            *(dst+pt-i+j) = (*(dst+pt-i+j)) | ((b8 >> j) << 7);
            }
    }

    return pt;

}

3
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2