/* *** smf.c: output smf sequence (preliminary version) *** */ #include "baresir.h" #define MAXLEN 100000 /* MIDI ファイル書き出しバッファの大きさ */ #define MAXNEV 50000 /* maximum number of note events */ static int format = 0; /* フォーマット: 0/1/2 */ static int tracks = 1; /* トラック数 */ static int channel = 0; /* チャネル */ static int quantum = 480; /* time quantum = quarter note */ int tempo = 500000; /* tempo */ static int ntrack; // 現在のトラック番号 (0, 1, 2, ...) static int delta; // イベントのデルタ・タイム static int offset; // 現在のトラック中の通算時間 static int prevstatus, prevtrack; // static int firsttrack=1; static int status; // イベントのステータス・バイト static int start; // イベント(ないしチャンク)の先頭バイト static int trackbytes; // トラック・データセクションのバイト数 static int events; // 総イベント数 static int tevents; // トラックのイベント数 int mmlrc=0; // return code struct MIDITRACK miditrack; static struct NOTE *notes; static int lmeasure = 0, lbeat = 0; extern struct MMLTRACK mmltrack[NTRACK]; extern void endfailure(); struct NOTEEVENT { int track, instrument; int onoff, offset; unsigned char bytes[3]; } noteevent[MAXNEV]; static int nep = 0; FILE *fout; static unsigned char mbuf[MAXLEN]; // MIDI ファイル読み込みバッファ static int mlen; // MIDI ファイルの長さ(バイト数) static int mp, save_mp; // 現在のバイト位置 /* *** 入力 *** */ #define mloc() (mbuf + mp) #define putb(b) mbuf[mp++] = b void putstr(s) unsigned char *s; { while (*s) putb(*s++); } void putn(n, b) /* 固定長数値 b: バイト数 */ int n, b; { if (b == 0) return; putn(n >> 8, b-1); putb(n & 0xff); } void putv(n) /* 可変長数値 */ int n; { static unsigned char buf[10]; int i; buf[0] = 0; for (i=0; n>0;) { buf[i++] = n & 0x7f; n >>= 7; } for (i--; i>0; i--) putb(buf[i] | 0x80); putb(buf[0]); } /* *** Put_MThd(): ヘッダ・チャンク *** */ void Put_MThd() { int len; putstr("MThd"); putn(6, 4); putn(format, 2); putn(tracks, 2); putn(quantum, 2); } /* *** */ int offcmp(n1, n2) struct NOTEEVENT *n1, *n2; { if (n1->track != n2->track) return(n1->track - n2->track); if (n1->offset == n2->offset) { if (n1->onoff) return(-1); if (n2->onoff) return(1); return(0); } else return(n1->offset - n2->offset); return(0); } void Setup_notes(pc) struct PIECE *pc; { int i; struct NOTEEVENT *ne; nep = 0; for (i=0, tracks=0; i 1) format = 1; for (i=0; inn; i++) { struct NOTE *nt = &(pc->notes[i]); if (nt->pitch > 0) { if (nep >= MAXNEV) { printf("*** note event buffer overflow\n"); exit(1); } ne = ¬eevent[nep++]; ne->track = nt->track; ne->instrument = nt->instrument; ne->offset = nt->offset; ne->onoff = 0; ne->bytes[0] = 0x90 | nt->channel; ne->bytes[1] = nt->pitch; ne->bytes[2] = nt->velocity; if (nep >= MAXNEV) { printf("*** note event buffer overflow\n"); exit(1); } ne = ¬eevent[nep++]; ne->track = nt->track; ne->instrument = nt->instrument; ne->offset = nt->offset + nt->duration; ne->onoff = 1; ne->bytes[0] = 0x90 | nt->channel; ne->bytes[1] = nt->pitch; ne->bytes[2] = 0; } } qsort(noteevent, nep, sizeof(struct NOTEEVENT), offcmp); } void Put_MTrk(pc) struct PIECE *pc; { int i, j; putstr("MTrk"); save_mp = mp; putn(0, 4); // trackbytes: temporary offset = 0; if (firsttrack) { putv(0); putb(0xff); putb(0x51); putb(0x03); putn(tempo, 3); // set tempo if (pc->ntime > 0) { // set time-sig (if any) putv(0); putb(0xff); putb(0x58); putb(0x04); putn(pc->ntime, 1); for (i=0, j=pc->dtime; j>1; i++, j>>=1) ; putn(i, 1); putn(24, 1); putn(8, 1); } firsttrack = 0; ntrack = 0; } prevtrack = ntrack; putv(0); // program change putb(0xc0 | mmltrack[ntrack].channel); putb(mmltrack[ntrack].instrument); putv(0); // control change putb(0xb0 | mmltrack[ntrack].channel); putb(0x07); putb(80); prevstatus = 0; } void End_track() { int bytes, sav; putv(0); putb(0xff); putb(0x2f); putb(0x00); bytes = mp - save_mp - 4; sav = mp; mp = save_mp; putn(bytes, 4); mp = sav; } void Put_tracks(pc) /* トラック・チャンク処理 */ struct PIECE *pc; { int i; offset = 0; firsttrack = 1; ntrack = 0; Put_MTrk(pc); for (i=0; itrack != prevtrack) { if (!firsttrack) End_track(); ntrack = ne->track; Put_MTrk(pc); } delta = ne->offset - offset; putv(delta); offset = ne->offset; if ((prevtrack != ne->track) || (prevstatus != ne->bytes[0])) putb(ne->bytes[0]); putb(ne->bytes[1]); putb(ne->bytes[2]); prevtrack = ne->track; prevstatus = ne->bytes[0]; } End_track(); } /* *** トップレベル *** */ struct PIECE *pc; FILE *fsmf; void main(argc, argv, arge) int argc; char **argv, **arge; { int i; FILE *fdat; cgimain(argc, argv, arge); pc = mml2dat(); Setup_notes(pc); Put_MThd(); Put_tracks(pc); if ((fsmf = fopen(smffile, "w")) != NULL) { for (i=0; i