#include "midi.h" /* Copright 1988, G.E.S. Consulting NORMAL MODE tutorial, RECORD and PLAY for those who like to do all the work themselves! NOTE: struct eventlist { struct event *f; ptr to first event on que struct event *c; ptr to current event on que struct event *l; ptr to last event on que } Library does NOT maintain (or have knowledge of) this structure. You are free to devise you own way to manage event lists if you wish. */ main() { struct event *p,*op, *qp = (struct event *)0; unsigned char r,sr;/* running status storage for get_event and show_event */ int count= 0, eventno = 0; /* counters for show_event */ init_event_list(10); /* allocate 10000 events */ mpu_init(); /* install driver */ /* tell em how to stop */ printf("Playback will begin when you hit middle C\n"); /* initialize running status */ r = 0; sr = 0; /* note MIDI_START is necessary to get mpu to actually do something the first time around. see tech manual p. 20 */ mpu_control(START_RECORD|MIDI_START); /* while MPU is still talking */ while(p = get_event(&r,10)) { show_event(++eventno,&count,&sr,p); /* show em what they did */ if (!qp) /* chain events together */ { qp = p; op = p; } else { op->n = p; op = p; } /* test for middle c pressed */ if (p->d.data[0] == 60 /* middle c */ && ((p->status == 0 && r == 0x90) || p->status == 0x90)) break; /* ON or OFF */ /* all done */ } /* tell MPU to finish up */ mpu_control(STOP_RECORD|MIDI_STOP); /* wait for END of DATA */ while(p = get_event(&r,10)) { show_event(++eventno,&count,&sr,p); op->n = p; op = p; if (p->tbyte < 240 && p->status == 0xfc) /* end of data */ break; } /* reset running status */ r = 0; /* tell MPU which tracks to play */ active_tracks(TRACK_1); clear_play_counters(); /* start playing */ mpu_control(START_PLAY|MIDI_START); op = qp; /* satisy requests for data */ while(p = get_event(&r,10)) { show_event(++eventno,&count,&sr,p); if (p->tbyte == 255 && p->status >= 0xf0 && p->status <= 0xf7) { send_message(op); op = op->n; } /* check for end of track */ if (p->tbyte == 255 && p->status == 0xfc) /* end of data */ break; } mpu_control(STOP_PLAY|MIDI_STOP); reset_mpu(); mpu_close(); } /* a handy routine to make an event human readable */ char *etab[] = { "Note Off ", "Note On ", "Key Pres ", "Cntrl Chg", "Program ", "Chan Pres", "Ptch Weel", "MIDI MARK" }; /* Midi Message Length table */ int ltab[] = {2,2,2,2,1,1,2,0}; show_event(int eventno,int *rcount,unsigned char *running,struct event *p) { printf("Event %03d ", eventno); if (p->tbyte < 0xf0) /* MIDI MESSAGE OR MPU MARK */ { int etype; int chan; if (!p->status) p->status = *running; else if (p->status < 0xf0) *running = p->status; etype = (p->status >> 4) & 7; if (etype == 1 && p->d.data[1] == 0) etype--; chan = (p->status & 7); *rcount += p->tbyte; printf("Timng (%02x) %3d ",p->tbyte,*rcount); printf("%s ",etab[etype]); switch(etype) { case 0: printf("Pitch (%03d) ",p->d.data[0]); break; case 1: printf("Pitch (%03d) Velocity (%03d) ",p->d.data[0], p->d.data[1]); break; case 2: printf("Pitch (%03d) Pressure (%03d) ",p->d.data[0], p->d.data[1]); break; case 3: printf("Number (%03d) Value (%03d) ",p->d.data[0], p->d.data[1]); break; case 4: printf("Number (%03d) ",p->d.data[0]); break; case 5: printf("Pressure (%03d) ",p->d.data[0]); break; case 6: printf("LSB (%03d) MSB (%03d) ",p->d.data[0], p->d.data[1]); break; case 7: switch(p->status) { case 0xf8: printf("NOP "); break; case 0xf9: *rcount = 0; printf("Measure End "); break; case 0xfc: printf("Data End "); break; default: printf("INVALID! "); } break; } } else /* MPU MESSAGE */ { int chan = p->status & 7; int stat = p->status; printf("Timng (%02x) %3d ",0,*rcount); printf("MPU MESSAGE "); if (stat >= 0xf0 && stat <= 0xf7) printf("Data Request: Channel %1d :",chan); else switch(stat) { case 0xf8: *rcount += 240; printf("Timer Overflow"); break; case 0xf9: printf("Conductor Data Request"); break; case 0xfa: printf("Midi Start"); break; case 0xfb: printf("Midi Continue"); break; case 0xfc: printf("Midi Stop"); break; case 0xfd: printf("CLOCK to HOST"); break; case 0xfe: printf("ACK"); break; case 0xff: { int i; printf("SYS EX DATA["); for (i = 0; i < p->dlen; i++) printf("%02x",p->dlen > 4 ? p->d.dptr[i] : p->d.data[i]); printf("]"); } break; } } printf("\n"); }