#include #include typedef unsigned int ui; char * oc, // Running cursor in buffer for collecting output * oe, // End of buffer * bb; // Befinning of buffer // Routine ex is just an easy way out. int ex(int d){printf("Bye %d\n", d); exit(4);} // Deposit character in buff if there is room. void pc(char x){if(oc==oe) ex(1); *(oc++) = x;} // Deposit string. void ps(char * s){while(*s) pc(*(s++));} // Deposit binary number v in c bytes. void pn(int c, ui v){if(c) {pn(c-1, v>>8); pc(v&255);}} // Next two routines for depositing variable length binary numbers. void pvlr(ui n){if(n > 127) pvlr(n>>7); pc(0x80 | n&127);} void pvl(ui n){if(n > 127) pvlr(n>>7); pc(n&127);} // Ensure a note down for channel 1 as running status. static char cst=0; static void e9(){if(cst != 9) {pc(0x90); cst=9;}} // Play note n for duration d. void n(int n, int d) {pvl(0); // Emit dt. e9(); // Emit status byte if not already running. pc(n); // Emit note value. pc(64); // Standard loundess pvl(d*120); // dt for note duration pc(n); // Which note to stop pc(0); // loudness=0 means to stop } int main(){ char * suspense; // Remember where to fill in track length. // Get a buffer for output. {int sp = 1000000; bb=oc = (char*)malloc(sp); if(!oc) ex(2); oe = oc+sp;} ps("MThd"); pn(4, 6); // MIDI file header and length of next three fields. pn(2, 1); // Format 1 file pn(2, 1); // Just one track pn(2, 240); // 240 ticks per quarter note. // Introduce the music track and remember where to put its length. ps("MTrk"); suspense = oc; pn(4, 0); // The music: pvl(0); pc(0xC0); pc(6); cst=12;// change voice n(60,2); n(62,2); n(64,2); n(60,2); n(60,2); n(62,2); n(64,2); n(60,2); n(64,2); n(65,2); n(67,4); n(64,2); n(65,2); n(67,4); n(67,1); n(69,1); n(67,1); n(65,1); n(64,2); n(60,2); n(67,1); n(69,1); n(67,1); n(65,1); n(64,2); n(60,2); n(60,2); n(55,2); n(60,4); n(60,2); n(55,2); n(60,4); // The "end of track" meta-event. pvl(0); pc(0xFF); pc(47); pvl(0); // Fill in the now known track length. {char*t = oc; oc = suspense; pn(4, t-(oc+4)); oc = t;} // Next three lines: copy the buffer into the file. {FILE * out = fopen("song.midi", "w"); {char * c; for(c = bb; c < oc; ++c) putc(*c, out);} fclose(out);} // release buffer. free(bb); return 0;}