// Add ornaments to a MIDI file. // Last changed Feb 2, 2006 (x8) #include #include #include "h.h" BP bp; note * mus = 0; short tv; typedef void orn(note *, short); void Aug(note n){ if(1) if((n.dur < maxdur) && (n.start == 143.75*480) && (n.trk == 2)) mus = mus; aug(n, &mus);} int gwhen; void doa(note * on, short m){note n = *on; if(m<0) return; if(n.dur < maxdur && n.o.n.loud > 64) {printf("Too loud! %d at %d\n", n.o.n.loud, n.start/bp.den); exit (-3);} n.start = gwhen; gwhen += m; n.dur = m; Aug(n); } static int xp(int k){if (k >= 0 || 1) return k; printf("%d too small\n", k); exit(0);} void mordant(note * on, short ap){note a = *on; a.o.n.freq = ap; if(ap >= on->o.n.freq) {printf("Bad mordent\n"); exit(11);} doa(on, tv); doa(&a, tv); doa(on, xp(on->dur - 2*tv));} void trillo(note * on, short ap){note a = *on; a.o.n.freq = ap; if(on->dur < 5*tv) { printf("Note too short for trillo at %d d=%d tv=%d\n", gwhen/bp.den, on->dur, tv); exit(2);} doa(&a, tv); doa(on, tv); doa(&a, tv); doa(on, tv); doa(&a, tv); doa(on, xp(on->dur - 5*tv));} void trx(note * on, short ap, short loud){ note a = *on, b = *on; // http://www.iment.com/maida/familytree/henry/music/bachnotation.htm#o1 note * x = &a; note * y = &b; a.o.n.loud = loud; a.o.n.freq = ap; b.o.n.loud = loud; while(gwhenstart+on->dur) {doa(x, tv); {note * t = x; x = y; y = t;}}} void tr(note * on, short ap){trx(on, ap, on->o.n.loud);} void trq(note * on, short ap){trx(on, ap, 64);} void cadence(note * on, short ap) {note up = *on, dn = *on; up.o.n.freq = on->o.n.freq+(ap&2?2:1); dn.o.n.freq = on->o.n.freq-(ap&1?2:1); doa(&up, tv); doa(on, tv); doa(&dn, tv); doa(on, xp(on->dur - 3*tv));} void dn(note * on, int j, int msk, short ap) {int k=j; note up = *on, dn = *on; if(on->dur < j*bp.den/8) {printf("Bad ornament: dur=%d at %d\n", on->dur, gwhen/bp.den); exit(15);} up.o.n.freq = on->o.n.freq+(ap&2?2:1); dn.o.n.freq = on->o.n.freq-(ap&1?2:1); while(1) {doa(msk&(1<<(j-1))?&up:&dn, tv); if(!--j) break; doa(on, tv);} doa(on, xp(on->dur - (2*k-1)*tv));} void x3(note * on, short ap) {dn(on, 4, 14, ap);} void x5(note * on, short ap) {dn(on, 4, 7, ap);} void x6(note * on, short ap) {dn(on, 4, 11, ap);} void x6s(note * on, short ap){dn(on, 3, 5, ap);} void x7(note * on, short ap) {dn(on, 4, 6, ap);} void x7x(note * on, short ap) {dn(on, 6, 0x1E, ap);} void xx(note * on, short ap) {dn(on, 4, 10, ap);} void xy(note * on, short ap) {dn(on, 4, 13, ap);} void x8(note * on, short ap) { if(on->dur != 1.5*bp.den) {printf("Bad x8: dur=%d at %d\n", on->dur, gwhen/bp.den); exit(14);} dn(on, 6, 0x2E, ap);} typedef struct {float time; short nv1, nv2; orn * code;} doorn; doorn mods[] = {{3*93+2, 66, 1, x6}, {3*107, 72, 71, mordant}, {3*108, 72, 71, mordant}, {3*108+1, 74, 76, trillo}}; int main(int argc, char * * argv){ // if(argc < 2) {printf("include filename.\n"); exit(0);} note* music = Read("pr.mid", &bp); void fed(note n){int j = sizeof(mods)/sizeof(mods[0]); while(j--){ if(n.dur < maxdur && n.start == mods[j].time*bp.den && ((n.o.n.freq == mods[j].nv1))){ if(mods[j].nv2<0) {printf("Mod %d Seen twice.\n", j); exit(0);} gwhen = n.start; mods[j].code(&n, mods[j].nv2); mods[j].nv2 = -1; goto pan;}} Aug(n); pan: ;} if (bp.den&7) {printf("Resolution of clock, %d, too coarse for ornaments\n", bp.den); ex(38);} tv = bp.den>>3; scan(fed, music, 1); {int j = sizeof(mods)/sizeof(mods[0]); while(j--) if(mods[j].nv2>=0) printf("Ornament %d unused\n", j);} Write("", mus, &bp); return 0;}