/* Copyright (c) 2002-2004 by Stanley M. Swanson. Distributed under the GNU General Public License, version 2 (GPL v2). */ /* vamp_harm.c split harmonic analysis routines 037.31 */ # include "globals.h" int jota[100], jotb[100], histgc[NCHORDS+13], histch[2*NCHORDS]; char file[80], rem[132]; char *chord_names[37]= { "Cm", "C#m", "Dm", "Ebm", "Em", "Fm", "F#m", "Gm", "Abm", "Am", "Bbm", "Bm", "C", "C#", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B", "Cd", "C#d", "Dd", "Ebd", "Ed", "Fd", "F#d", "Gd", "Abd", "Ad", "Bbd", "Bd"," " }; FILE *fscore; int inkey[12]; /* mark non-accidentals for current key signature */ int chord_wts[36], mode_wts[36]; /* preferred chords for key (weighted) */ /* conversion scale degrees 1:7 to half tones */ int sc2ht[16] = { 11, 0, 2, 4, 5, 7, 9, 11, 0, 2, 4, 5, 7, 9, 11, 0 }; /* conversion half tones 0:11 to major scale degrees 1:7 (-1 == out ) */ int ht2sc[12] = { 1, -1, 2, -1, 3, 4, -1, 5, -1, 6, -1, 7 }; /* reduce half tones in range 12:23 to 0:11 */ int rht[24] = { 0,1,2,3,4,5,6,7,8,9,10,11, 0,1,2,3,4,5,6,7,8,9,10,11 }; /* triad types: minor==0, major==12, diminished==24 */ int triadtype[16] = { 0,12,0,0,12,12,0,24, 12,0,0,12,12,0,24,12 }; /* 030.20 revised Kaufmann chord preferences, offset<0 terminates */ typedef struct { int offset, type, score; } PREF_LIST; PREF_LIST *modepref, majorpref[] = {{0,12,9},{7,12,8},{5,12,7}, {2, 0,6}, {2,12,5},{9, 0,5},{9,12,4}, {4,12,4},{4, 0,3},{11,12,1},{10,12,1},{-1,-1,-1}}, mixpref[] = {{0,12,9},{7, 0,8},{5,12,7}, {2, 0,6}, {2,12,5},{9, 0,5},{9,12,4}, {4,12,4},{4, 0,3},{10,12,1},{11,12,1},{-1,-1,-1}}, minorpref[] = {{0, 0,9},{7, 0,8},{5, 0,7}, {2, 0,6}, {8, 0,5},{8,12,4},{3,12,4}, {3, 0,3},{2,12,3},{5,12,2}, {7,12,2}, {10,12,1},{11,12,1},{-1,-1,-1}}, dorianpref[] = {{0, 0,9},{7, 0,8},{5,12,7}, {2, 0,6}, {8, 0,5},{8,12,4},{3,12,4}, {3, 0,3},{2,12,3},{5, 0,2}, {7,12,2}, {10,12,1},{11,12,1},{-1,-1,-1}}; /* top level parse command line and call routines */ # define MXHOPT 17 char *harmopt[MXHOPT] = { NULL, "no","details","interactive", "measure","half","phrase","entire", "all","accented","bounding","restrict","guitar", "center", "statistics", "log", "?" }; int H_length=0, H_verbose=0, H_center=0, H_interact = 0, H_restrict=0, P_wt=0, H_guitar=1, H_mode=5, H_all=4, H_accent=0, H_bound=0, H_log=0, H_method=15, H_wtype=5, H_heur=1, H_split=1; double raw_part=1.00, root_wt=1.0; float stat_wt[12]; # define MXCHO 100 int krank; short rank[MXCHO][6]; /* tabulate ranked chords */ void print_all_chords(int tonic, int nchords) { int i,j,k,lf,le,m,kg; FILE *fo = stdout; char tie,minor; for (i=0; i<2; i++) { if (nchords) fprintf(fo,"\n"); if (H_verbose>0) { for (j=0; j<6; j++) { k = (tonic + chord_tone[j][0])%12; if (j<3) fprintf(fo," %s %s ",chord_name[j],key_name[k]); else fprintf(fo," %s %sm ",chord_name[j],key_name[k]); } fprintf(fo,"\n"); } if (nchords) fprintf(fo,"===============\n"); if (nchords>0) { /* top ranked chords in "iuvwjt" notation */ if (H_restrict) { for (k=0;k=0) kg++; if (j<0) { j = -j - 100; minor = '='; } if (j>11) j -= 12; else { tie = minor; minor = 'm'; } fprintf(fo,"%s%c%c",key_name[j],minor,tie); if (lf>=le) { fprintf(fo,"\n"); lf = 0; } } /* for (k) */ fprintf(fo,"\n"); if (kg>0) { char *blank = " ", *plus = "+", *dot=".", *gc1, *gc2; /* guitar chords seen */ if (bars[0].t=0) gc1 = guitar_ch + j; else gc1 = dot; m = rank[k][0]; if (m>=0) gc2 = guitar_ch + m; fprintf(fo," %s%s",gc1,gc2); if (lf>=le) { fprintf(fo,"\n"); lf = 0; } } /* for (k) */ fprintf(fo,"\n"); } /* if (kg>0 */ } /* if (H_restrict) ... else ... */ } /* if (nchords>0) */ if (!H_log) break; fo = flog; /* second time thru to log file */ } /* for (i) outputs */ } /* print_all_chords() */ int chord_number(char *gc) /* convert guitar chord string to internal code */ { int k=0, j=-1, m=12; if (!gc) return -1; while (gc[k]) { if (gc[k]>='A' && gc[k]<='G') { j = gc[k] - 'C'; if (j<0) j += 7; j *= 2; if (j>4) j--; } else if (gc[k]=='#') j++; else if (gc[k]=='b') j--; else if (gc[k]=='m') m = 0; k++; if (k>20) break; } /* while (gc[]) */ if (j>=0) return m + j; else return -1; } /* chord_number() */ void save_chord_scores(int meas, int *jot, int n) { int j,k; if (!fscore) return; fprintf(fscore,"%5d",meas); for (j=k=0; j11) { fprintf(fscore,"\n"); k = 0; if (j0) fscore = fopen(file,"w"); } */ break; case 16: printf("harmony options: "); for (j=1;j<8;j++) printf("%s ",harmopt[j]); printf("\n"); for (j=8;j>> check extra parameters Q_TESTA, Q_TESTB\n"); raw_part = 1.0; root_wt = 1.0; /* 044.16 temp bug fix */ } if (root_wt<0.0) { root_wt = -root_wt; H_split = 0; } if (stat) { set_chord_prefs(100*mode_delta+tonal_center); calc_wt_sums(jota,(float*)jotb,&k,&k); print_stats(stdout); for (k=0;k<36;k++) printf("% d",chord_wts[k]); printf(" pref\n"); for (k=0;k<12;k++) printf(" %4.1f",stat_wt[k]); printf("\n"); if (H_log) print_stats(flog); return; } if (H_center) H_mode = 0; else H_mode = H_all | H_accent | H_bound; if (H_verbose>1) printf("length %d mode %d center %d verbose %d\n", H_length, H_mode, H_center, H_verbose); if (H_verbose>0) printf("H_restrict %d H_method %d H_mode %d ixgch %d\n", H_restrict,H_method,H_mode,ixgch); if (last_mel<0) return; /* nothing to analyse */ nmeas = find_measures(last_mel, H_verbose); krank = 0; if (H_restrict==0 && H_method==0 ) { int g0, g1, g2, gp; /* guitar chords -> numbers */ g0 = -1; for (k=0; k=0) { gp = g1 + 100*(g2 + 1); g0 = g2; histgc[g2]++; } else { gp = g1; g0 = g1; } histgc[g1]++; } if (fscore) fprintf(fscore,"%5d",gp); if (guitar_ch_1) { printf("%3s",guitar_ch_1); if(flog) fprintf(flog,"%3s",guitar_ch_1); } else { printf(" "); if (flog) fprintf(flog," "); } if (guitar_ch_2) { printf("%-3s",guitar_ch_2); if(flog) fprintf(flog,"%-3s",guitar_ch_2); } else { printf(" "); if (flog) fprintf(flog," "); } if ((k+1)%8==0 || k>nmeas-2) { if (fscore) fprintf(fscore,"\n"); printf("\n"); if (flog) fprintf(flog,"\n"); } } /* for (k0) printf("%s ",chord_names[k]); } printf("\n\n"); } else if (H_interact) { print_all_chords(key_major, 0); P_wt = 0; halfmeas(0,nmeas); for (k=0;k<36;k++) printf("% d",chord_wts[k]); printf(" pref\n"); while (1) { printf("measure: "); n = finstring(line,80,stdin); if (n==0) break; k = 0; n = sscanf(line," %d",&k); if (n==0 || k<0 || k>nmeas) break; if (k>0) k--; /* consistent with printed measure numbers */ { nstart = select_notes(bars[k].s,bars[k].e,H_length,H_mode,1); smeas = k; analyse_notes(key_major, H_verbose, H_mode); test_all_chords(key_major, H_verbose, H_mode); /* do half measures */ select_notes(bars[k].s,bars[k].h,H_length,H_mode,1); test_all_chords(key_major, H_verbose, H_mode); select_notes(bars[k].h,bars[k].e,H_length,H_mode,1); test_all_chords(key_major, H_verbose, H_mode); halfmeas(k,k+1); } } /* while (1) */ } else if (H_mode) { if (H_guitar ) { if (H_heur<5) halfmeas(0,nmeas); else other_alg(0,nmeas); } else { print_all_chords(key_major, 0); if (fscore) fprintf(fscore,"%5d %s\n",H_method,title); for (k=0; k0) { for (j=0; j<12; j++) { tn = tones[j]; if (tn>m) { m = tn; k = j; } printf(" %4d",tn/dur); if (H_log) fprintf(flog," %4d",tn/dur); } if (H_log) fprintf(flog," center %d %s\n",k,key_name[k]); printf(" center %d %s\n",k,key_name[k]); } return k; } /* consonances() */ int find_center(int nstart, int nend, int meas, int tonic, int period, int verbose) { int i,j,k,m,n=0, dur=0, per=20000,tn, pn, inote,enote, rw, tones[12]; n = nstart; dur = 0; inote = enote = -1; if (period>0) per = period; for (j=0; j<12; j++) tones[j] = 0; /* collect statistics for duration or to measure bar*/ while (n -1 && dur < per) { pn = pitch[n]; tn = tics[n]; dur += tn; if (pn=nend) break; } /* while (pitch>-1 && dur0) { for (j=0; j<12; j++) printf(" %5d",tones[j]/dur); printf(" cons\n"); } return n; } /* while (n11) i -= 12; inkey[i] = 1; } for (k=0; k<36; k++) chord_wts[k] = 0; if (H_heur==1) { /* original Kaufmann preferences */ /* treat Dorian and Aeolian (minor) as minor), rest as major */ /* 03e.08 Matt: 1 5 4 6m 6 2m 3m 2 7 3 (for major) */ /* presumably : 1m 5m 4m 6 6m 2 3 2m 7 3m (for minor) */ j = mode_delta; if (j==2||j==9) m = 0; else m = 12; center = tonal_center; j = center + m; chord_wts[j] = 6; /* tonic */ j = (center + 7)%12 + m; chord_wts[j] = 5; /* dominant */ j = (center + 5)%12 + m; chord_wts[j] = 4; /* subdominant */ if (m==0) j = (center +8)%12; else j = (center +9)%12; chord_wts[j] = chord_wts[j+12] = 3; /* sixths */ if (m==0) j = (center +10)%12; else j = (center +11)%12; chord_wts[j+12] = 1; /* "major" seventh */ /* seconds and thirds */ j = (center +2)%12; chord_wts[j] = chord_wts[j+12] = 2; /* second */ if (m==0) j = (center +3)%12; else j = (center +4)%12; chord_wts[j] = chord_wts[j+12] = 1; /* thirds */ } else if (H_heur==2) { /* conventional modes: sms*/ int smode; center = key_major; smode = ht2sc[mode_delta] - 1; if (H_verbose>1) printf("smode %d ",smode); if (smode<0) { printf("bad mode_delta\n",mode_delta); smode = 0; } chord_wts[j = rht[center+sc2ht[smode+1]]+triadtype[smode+1]] = 6; if (H_verbose>1) printf(" tonic %d",j); chord_wts[j = rht[center+sc2ht[smode+5]]+triadtype[smode+5]] = 5; if (H_verbose>1) printf(" dominant %d",j); chord_wts[j = rht[center+sc2ht[smode+4]]+triadtype[smode+4]] = 4; if (H_verbose>1) printf(" subdom %d\n",j); chord_wts[rht[center+sc2ht[smode+6]]+triadtype[smode+6]] = 3; chord_wts[rht[center+sc2ht[smode+3]]+triadtype[smode+3]] = 3; chord_wts[rht[center+sc2ht[smode+2]]+triadtype[smode+2]] = 2; chord_wts[rht[center+sc2ht[smode+7]]+triadtype[smode+7]] = 2; /* if (heur==2) */ } else if (H_heur>2) { /* extended Kaufmann preferences */ /* 030.14 Matt: 1 5 4 2m 2 6m 6 3 3m 7 7b (for major) */ /* 030.14 Matt: 1 5 4 2m 2 6m 6 3 3m 7 7b (for major) */ /* : 1m 5m 4m 2m 6m 6 3 3m 2 4 5 7b 7 (for minor) */ /* : 1m 5m 4 2m 6m 6 3 3m 2 4m 5 7b 7 (for dorian) */ if (mode_delta==0) modepref = majorpref; else if (mode_delta==9) modepref = minorpref; else if (mode_delta==2) modepref = dorianpref; else if (mode_delta==7) modepref = mixpref; else if (mode_delta==5) modepref = majorpref; else if (mode_delta==4) modepref = minorpref; else modepref = majorpref; center = tonal_center; for (k=0; k<24; k++) { j = modepref[k].offset; if (j<0) break; j = (j + center)%12; j += modepref[k].type; chord_wts[j] = modepref[k].score; } } /* (heur>2) */ for (k=0; k<36; k++) mode_wts[k] = chord_wts[k]; /* master copy */ if (H_verbose>1) { for (k=0;k<36;k++) printf("% d",chord_wts[k]); printf(" pref\n"); printf("select_note key: %s %d center %s %d \n", key_name[key_major],key_major,key_name[tonal_center],tonal_center); } } /* set_chord_prefs() */ /* 038.17 before set_key was expanded to accept modes (Dorian, etc.) which change the tonal_center away from the tonic indicated by the key signature (major scale), I used tonic and tonal_center synonomously. "tonic" survives in the analysis code, but should be interpreted as key_major to define the conventional chord triads */ int analyse_notes( int tonic, int verbose, int mode) { int i,j,k,m,n=0, dur=0,tn, inote,enote, rw, chords[6]; if (snotes==0) return -1; for (j=0; j<12; j++) dwell[j] = 0; inote = (stone[0]-tonic+12) % 12; enote = (stone[snotes-1]-tonic+12) % 12; for (i=0; i=0) { if (verbose>1) { for (j=0; j<12; j++) printf(" %3d",dwell[j]); printf(" measure %d duration %d\n",smeas,dur); } if (verbose>1 && H_log) { for (j=0; j<12; j++) fprintf(flog," %3d",dwell[j]); fprintf(flog," measure %d duration %d\n",smeas,dur); } for (i=0;i<6;i++) { rw = tn = 0; for (j=0;j<3;j++) { k = chord_tone[i][j]; tn += dwell[k]; if (mode & 1) { /* require "bounding" flag to use first:last notes */ if (k==inote) rw += 2; if (k==enote) rw += 1; /* printf("%2d",k); */} } chords[i] = 100*tn + 10*rw + 6-i; if (verbose>1) printf(" %s %4d %d,",chord_name[i],tn,rw); if (verbose>1 && H_log) fprintf(flog," %s %4d %d,",chord_name[i],tn,rw); } sort_i(chords,6); if (verbose==1) printf("measure %3d [%5d %5d] ", smeas,chords[5]/10,chords[4]/10); if (verbose==1 && H_log) fprintf(flog,"measure %3d [%5d %5d] ", smeas,chords[5]/10,chords[4]/10); /* sort_i(chords,6); */ for (k=5; k> -1; k--) { i = 6 - (chords[k]%10); if (verbose>0) { printf(" %s",chord_name[i]); if (H_log) fprintf(flog," %s",chord_name[i]); } if (krank0) { printf(" %s",key_name[k]); if (i>2) printf("m"); else printf(" "); if (guitar_ch_1) printf(" [%s]",guitar_ch_1); if (guitar_ch_2) printf(" [%s]",guitar_ch_2); printf("\n"); if (H_log) { fprintf(flog," %s",key_name[k]); if (i>2) fprintf(flog,"m"); else fprintf(flog," "); if (guitar_ch_1) fprintf(flog," [%s]",guitar_ch_1); if (guitar_ch_2) fprintf(flog," [%s]",guitar_ch_2); fprintf(flog,"\n"); } /* if (H_log) */ } } /* (inote>0) */ return i; } /* analyse() */ /* seq. Matt Kaufmann discussions 03e.03: key independent chords */ int print_chord_matches(int n, int *jot, float *dwells, int dur, int verbose, FILE *f) { int j, k, kk=0, m, tn, thr = dur/4; if (verbose>1) { if (guitar_ch_1) fprintf(f,"[%s]",guitar_ch_1); if (guitar_ch_2) fprintf(f,"[%s]",guitar_ch_2); fprintf(f," measure %3d duration %4d ",smeas,dur); fprintf(f,"\n"); for (j=0; j<12; j++) fprintf(f,"%5d",(int)dwells[j]); fprintf(f,"\n"); } if (verbose>0) { for (j=n-1; j>=0; j--) { k = jot[50+j]; kk++; m = 0; if (k>11) { m = 1; k -= 12; } tn = jot[j]; if (verbose==1 && (tn<=0 || (tn4) ) ) { fprintf(f," // "); if (guitar_ch_1) fprintf(f,"[%s]",guitar_ch_1); if (guitar_ch_2) fprintf(f,"[%s]",guitar_ch_2); fprintf(f," %d\n",dur); return n-j; } fprintf(f," %s",key_name[k]); if (m==1) fprintf(f," "); else fprintf(f,"m "); if (verbose>1) fprintf(f," duration %5d index %2d\n",tn,k+12*m); else fprintf(f,"%4d",tn); } } return n; } int calc_wt_sums(int *jot, float *dwells, int *diver, int *durat) { int i,ii,ih,ir,is,it,j,k,m,n=0, off=50, dur=0,tn, inote,enote,divers=0; float wt[12], ti, sum, w,p, root_part; /* minor, major, diminished triads */ int template[3][3] = { { 0, 3, 7 }, { 0, 4, 7 }, { 0, 3, 6 } }; if (snotes==0) { for (j=0;j<12;j++) dwells[j] = 0.0; for (j=0;j<24;j++) jot[j] = 0; jot[j+50] = j; /* blank */ *diver = 0; *durat = 0; return -1; } if (H_heur==4) { for (k=0; k<36; k++) chord_wts[k] = mode_wts[k]; } /* H_wtype==2 chord notes (top) wtype==3 chord notes - half tone nbrs (all) [default] wtype==4 Matt's modified all 4 -2 ... -1 wtype==5 no penalty if half tone is in scale wtype==6 Matt's modified 1 -1 ... -0.5 with +quantum for inote==root wtype==7 no penalty if half tone is in scale of root */ for (j=0; j<12; j++) dwells[j] = 0.0; inote = (stone[0]+12) % 12; enote = (stone[snotes-1]+12) % 12; /* get total duration of all semitones in measure , reproduce at dwells[k+12] for wrap-around */ for (i=0; i0.0) divers++; *diver = divers; *durat = dur; root_part = root_wt/(float)dur; /* loop all chord templates (j) and all semitones (k) */ n = 0; w = p = 1.0; if (H_wtype==4) w = p = 2.0; if (H_wtype==2) p = 0.0; for (j=0; j<2; j++) for (k=0; k<12; k++) { sum = 0.0; for (i=0;i<12;i++) wt[i] = 0.0; /* construct wt[] from templates and rules */ for (it=0; it<3; it++) { i = k+template[j][it]; if (i>11) i -= 12; wt[i] = w; /* if (it==0 && k==key_major) sum +=0.0; */ /* wt[i] = 2.0 */ is = (inkey[i] && H_wtype==5); /* penalize half tone offsets in chord, unless note and half tone are both in scale (and wtype==5) */ ih = i+1; if (ih>11) ih -= 12; wt[ih] = -p; if (inkey[ih] && is) wt[ih] = 0.0; if (it==1 && H_wtype==7 && j==1) wt[ih] = 0.0; if (it==2 && H_wtype==7 && j==0) wt[ih] = 0.0; ih = i-1; if (ih<0) ih += 12; wt[ih] = -p; if (it==0 && H_wtype==7 && j==1) wt[ih] = 0.0; if (it==1 && H_wtype==7 && j==0) wt[ih] = 0.0; if (it==0 && H_wtype==6) wt[ih] = -0.5*p; if (inkey[ih] && is) wt[ih] = 0.0; } /* for (it) */ if (H_wtype==4) { wt[k] = w + w; /* Matt's wt[] */ ih = k-1; if (ih<0) ih += 12; wt[ih] = -0.5*p; } if (H_wtype==6 && k==inote) sum += quantum; if (H_verbose==3 && P_wt) { printf("wt: "); for (i=0;i<12;i++) printf("%5.1f",wt[i]); printf("\n"); } for (i=0; i<12; i++) sum += wt[i]*dwells[i]; sum *= raw_part; /* scale by Q_TESTB/100.0 */ if (sum>=0.0) jot[n] = sum + 0.5; else jot[n] = sum - 0.5; /* bias if preferred chord for key/tonal center */ if (H_heur>0) { /* heur==4 give more weight for chord root */ if (H_heur==4) { chord_wts[n] *= (1.0 + root_part*dwells[k]); } jot[n] += chord_wts[n]; } jot[n+off] = n; if (j==1 && k==0) /* 044.14 for "stat" */ for (ii=0; ii<12; ii++) stat_wt[ii] = wt[ii]; n++; } /* for (j) for (k) */ return n; } /* calc_wt_sums() */ int test_all_chords(int tonic, int verbose, int mode) { int i,ih,ir,is,it,j,k,m,n=0, dur=0,tn, inote,enote,wtype,heur,divers=0; float dwells[24], wt[12], ti, sum, w,p; /* minor, major, diminished triads */ int template[3][3] = { { 0, 3, 7 }, { 0, 4, 7 }, { 0, 3, 6 } }; if (snotes==0) return -1; n = calc_wt_sums( jot, dwells, &divers, &dur); save_chord_scores(smeas,jot,n); /* save numeric scores for analysis */ sort_ii(jot,jot+50,n); if (krank1; k--) { j = jot[k+68]; if (jot[k+18]==jot[k+17]) j = -j -100; rank[krank][k] = j; } if (guitar_ch_1) rank[krank][1] = guitar_ch_1 - guitar_ch; else rank[krank][1] = -10; if (guitar_ch_2) rank[krank][0] = guitar_ch_2 - guitar_ch; else rank[krank][0] = -10; } else over_flows++; krank++; print_chord_matches(n, jot, dwells, dur, verbose, stdout); if (flog) print_chord_matches(n, jot, dwells, dur, verbose, flog); P_wt = 0; return n; } /* test_all_chords() */ int halfmeas(int ki, int kf) { int j,k,nchord,na,nb, divera,diverb,divers,dur,top,off,sca,scb,scm; int kident,knonpref,kmat,tca,tcb,tcm,scg0,scg1,scg2,cn1,cn2; int ke1, ke2, kp1, kp2, k1g, k2g, kambig; float dwella[12], dwellb[12], dwells[24]; char *gc1, *gc2, *gc3, *gc4, ch, cr, ca, eqa, eqb, eqm; nchord = NCHORDS; top = nchord - 1; off = 50; for (k=0; k=0) scg1 = jota[cn1]; if (cn2>=0) scg2 = jotb[cn2]; select_notes(bars[k].s,bars[k].e,H_length,H_mode,1); calc_wt_sums( jot, dwells, &divers, &dur); if (cn1>=0) scg0 = jot[cn1]; else scg0 = 0; if (na != nchord || nb != nchord) { printf("short list %d %d halfmeas() %d\n",na,nb,k+1); if (flog) fprintf(flog,"short list %d %d halfmeas() %d\n",na,nb,k+1); } /* save numeric scores for analysis */ /* save_chord_scores(smeas,jot,nchord); save_chord_scores(smeas,jota,nchord); save_chord_scores(smeas,jotb,nchord); */ eqa = eqb = eqm = ' '; sort_ii(jota,jota+50,nchord); tca = jota[top+off]; sca = jota[top] - chord_wts[tca]; if (jota[top]==jota[top-1]) { eqa = '='; kambig++; } sort_ii(jotb,jotb+50,nchord); tcb = jotb[top+off]; scb = jotb[top] - chord_wts[tcb]; if (jotb[top]==jotb[top-1]) { eqb = '='; kambig++; } sort_ii(jot,jot+50,nchord); tcm = jot[top+off]; scm = jot[top] - chord_wts[tcm]; if (jot[top]==jot[top-1]) { eqm = '='; kambig++; } ch = ca = ' '; if (tca!=tcb) ch = 'u'; if (sca+scb>scm) { ch = '+'; histch[tca]++; histch[tcb]++; } else histch[tcm]++; cr = '.'; if (cn1>=0) { if (cn2<0) { if (cn1==tcm) ke1++; else cr = '-'; if (scm==(scg0-chord_wts[cn1])) kp1++; else { cr = '>'; k1g++; } } else { if (cn1==tca) ke2++; else cr = '~'; if (cn2==tcb) ke2++; else cr = '~'; if (sca==(scg1-chord_wts[cn1])) kp2++; else { cr = '#'; k2g++; } if (scb==(scg2-chord_wts[cn2])) kp2++; else { cr = '#'; k2g++; } } } /* if (cn1>=0) */ for (j=0; j<12; j++) if (dwells[j]>0.0 && ! inkey[j] ) ca = '@'; if (tca==tcb) kident++; if (chord_wts[tcm]<4) knonpref++; if (chord_wts[tca]<4) knonpref++;if (chord_wts[tcb]<4) knonpref++; if (cn1==tca && cn2==tcb) kmat++; else if (cn1==tcm) kmat++; if (H_verbose>1 || (cr != '.' && H_verbose==1) ) { printf("%2d%c%c %-3s %3d%c | %-3s %3d%c %-3s %3d%c .. %c",k+1,cr,ca, chord_names[tcm],jot[top],eqm, chord_names[tca],jota[top],eqa, chord_names[tcb],jotb[top],eqb,ch); if (gc1) printf(" %s",gc1); if (gc2) printf(" %s",gc2); if (cn1>=0) printf(" %3d %3d",scg0,scg1); if (cn2>=0) printf(" %3d",scg2); printf("\n"); if ((scg0>=scm) && (cn1!=tcm) && (H_method>=40)) { for (j=top;jot[j]>=scg0; j--) printf("%3s%4d",chord_names[jot[j+off]],jot[j]); printf("\n"); } if ((k&7)==7) printf("\n"); if (flog) { fprintf(flog,"%2d%c%c %-3s %3d | %-3s %3d %-3s %3d .. %c",k+1,cr,ca, chord_names[tcm],jot[top], chord_names[tca],jota[top], chord_names[tcb],jotb[top],ch); if (gc1) fprintf(flog," %s",gc1); if (gc2) fprintf(flog," %s",gc2); if (cn1>=0) fprintf(flog," %3d %3d",scg0,scg1); if (cn2>=0) fprintf(flog," %3d",scg2); fprintf(flog,"\n"); if ((k&7)==7) fprintf(flog,"\n"); } /* if (flog) */ } /* if (H_verbose...) */ if (krank1) { printf("%2d match, %2d identical, %2d ambiguous, (using method %2d )\n", kmat,kident,kambig,H_method); printf("exact %2d %2d sum %2d %2d gtr %2d %2d nonprefered %2d\n", ke1, ke2, kp1, kp2, k1g, k2g, knonpref); if (flog) { fprintf(flog,"%2d match, %2d identical, %2d ambiguous," " (using method %2d )\n", kmat,kident,kambig,H_method); fprintf(flog,"exact %2d %2d sum %2d %2d gtr %2d %2d nonprefered %2d\n", ke1, ke2, kp1, kp2, k1g, k2g, knonpref); } for (k=0; k0) printf("%s ",chord_names[k]); } printf("\n\n"); } /* summary for more than one measure */ } /* halfmeas() */ int other_alg(int ki, int kf) { int i,j,k,h,hh,m,n,nchord,na,nb,ne,nl, tcp, scp, tcl, scl, lp1, lp2, lp3, divera,diverb,divers,dur,top,off,sca,scb,scm; int kident,knonpref,kmat,tca,tcb,tcm,scg0,scg1,scg2,cn1,cn2; int ke1, km1, kr1, klp, kl1, kq1, tn, emph[12], leaps[12], interval[12], wt[24]; float dw, dwella[12], dwellb[12], dwells[24]; char *gc1, *gc2, *prch, *lpch, *rtch, *gc4, ch, cr, ca; nchord = NCHORDS; top = nchord - 1; off = 50; tcb = 37; ke1 = km1 = kr1 = klp = kl1 = kq1 = 0; for (k=0; k=0) scg1 = jot[cn1]; if (cn2>=0) scg2 = jot[cn2]; for (j=0; j<12; j++) { jotb[j] = dwells[j]; jotb[j+off] = j; leaps[j] = interval[j] = emph[j] = 0; } nl = 0; for (i=0; iquantum) emph[n] |= 4; if (down_beat&&on_beat) emph[n] |= 2; if (up_beat&&on_beat) emph[n] |= 1; if (i>0&&stone[i-1]2 && m<10) { nl++; m = stone[i-1]%12; leaps[m]++; leaps[n]++; } } } /* (j0 && on_beat && first_beat) printf("begin phrase %d\n",kphrase+1); pedometer(tn); } /* if (kphrase<2) printf("\n"); */ if (k==ki&&H_verbose>1) printf("major %2d wt %d\n", key_major, chord_wts[key_major+12]); /* determine most prevalent note(s) as root candidates */ sort_ii(jotb, jotb+off, 12); tn = jotb[11]; i = jotb[11+off]; na = ne = 0; lp1 = lp2 = lp3 = -1; /* for (j=11; jotb[j]==scb && j>=0; j--) na++; */ for (j=0; j<12; j++) { if (jotb[j]==tn) na++; /* count "roots" */ if (leaps[j]>0) { ne++; if (lp1<0) lp1 = j; else if (lp2<0) lp2 = j; else if (lp3<0) lp3 = j; } } /* major,minor root based chords */ tca = i+12; sca = jot[tca]; tcb = i; scb = jot[tcb]; if (scb>sca) { j = tca; tca = tcb; tcb = j; sca = scb; scb = jot[tcb]; } /* analyse leaps: ne==# of ends; lp1, lp2, lp3 == ends */ lpch = " "; scl = 0; if (nl>0) { if (H_verbose && ne>3) printf(">>>excess leap ends %d\n",ne); for (m=0; m<24; m += 12) for (n = 0; n<12; n++) { scl = 0; if (leaps[n]) scl = quantum; j = n + 7; if (j>11) j -= 12; if (leaps[j]) scl += quantum; j = n + 3; if (m) j++; if (j>11) j -= 12; if (leaps[j]) scl += quantum; j = n+m; jota[j] = scl + chord_wts[j]; jota[j+off] = j; } sort_ii(jota, jota+off, 24); tcl = jota[top+off]; scl = jot[tcl]; lpch = chord_names[tcl]; } /* if (nl>0) */ /* determine standard chord rankings and "top chord" */ sort_ii(jot,jot+off,nchord); tcp = tcm = jot[top+off]; scp = scm = jot[top]; prch = chord_names[tcm]; if (nl>0) { if (tcl==tcm) kl1++; klp++; } if (na>1) { j = tcm%12; dur = dwells[j]; if (tn==dur) ke1++; else { ch = '?'; kq1++; } } else { if (tcm%12==i) ke1++; else if (sca - scm + quantum +3 > 0) { kr1++; ch = '/'; tcp = tca; scp = sca; rtch = prch = chord_names[tca]; } } /* (na cf 1) */ if (tcp==cn1 || tcp==cn2) km1++; n = sprintf(rem, "%2d%c ",k+1,ch); n += sprintf(rem+n, " top %-3s %3d ", chord_names[tcm],scm); n += sprintf(rem+n, " root %-3s %3d ", rtch,sca); n += sprintf(rem+n, " leap %-3s %3d %d ..", lpch,scl,nl); n += sprintf(rem+n, " pref %-3s %3d ", chord_names[tcp],scp); if (cn1<0) n += sprintf(rem+n, "\n"); else if (cn2<0) n += sprintf(rem+n, " .. %s %d\n",gc1,scg1); else n += sprintf(rem+n, " .. %s %s %d %d\n",gc1,gc2,scg1,scg2); if (H_verbose) { printf("%s",rem); if (flog) fprintf(flog,"%s",rem); } if (H_verbose && (1 || nl>0 || na>1)) { printf(" leaps "); scb = jotb[11]; for (j=0; j<12; j++) printf("%2d",leaps[j]); printf(" longs "); for (j=11; jotb[j]==scb && j>=0; j--) { n = jotb[j+off]; printf(" %2d:%d",n,emph[n]); } printf("\n"); } pedometer(0); /* end of measure check */ histch[tcp]++; if (krank1) { rank[krank][5-h] = tcp; } rank[krank][1] = rank[krank][0] = -10; if (gc1) rank[krank][1] = gc1 - guitar_ch; if (gc2) rank[krank][0] = gc2 - guitar_ch; } else over_flows++; if (hh==1 || h==1) krank++; } /* for (k) */ if (kf-ki>1) { sprintf(rem,"\nmatch %d identical %d root> %d leap==top %d # %d ? %d\n", km1,ke1,kr1,kl1,klp,kq1); printf("%s",rem); if (flog) fprintf(flog,"%s",rem); for (k=0; k1) { tca = rank[k][5]; tcb = rank[k][4]; gc1 = chord_names[tca]; } else { tca = tcb = rank[k][3]; gc1 = chord_names[tca]; } if (tca==tcb) gc2 = " "; else gc2 = chord_names[tcb]; printf("%3s%-3s",gc1,gc2); if (flog) fprintf(flog,"%3s%-3s",gc1,gc2); } { printf("\n"); if (flog) fprintf(flog,"\n"); } printf("\nchords used: "); for (k=0; k0) printf("%s ",chord_names[k]); } printf("\n\n"); } /* summary for more than one measure */ } /* other_alg() */ void print_stats(FILE *fo) { int k, mtc, mode=0, modeticks=0, i,j; /* print measure lengths */ for (k=0; kmode) { mode = mtc; modeticks = meas_tick[k]; } fprintf(fo,"measure ticks %4d occurences %4d\n", meas_tick[k], mtc); } fprintf(fo,"ticks in modal measure %d, max ticks in measure %d\n", modeticks, ticks_in_meas); ticks_in_meas = modeticks; fprintf(fo,"tonal_center %s key_signature %s mode_delta %d\n", key_name[tonal_center], key_name[key_major], mode_delta); fprintf(fo," relative pitch, tonic %d\n",key_major); for (k=0; k<12; k++) fprintf(fo," %4d",doremi[k]); fprintf(fo,"\n"); for (k=0; k<12; k += 2) { if (k==6) k = 5; j = doremi[k]; if (j==0) fprintf(fo," missing scale tone %d\n",k); } for (k=1; k<11; k += 2) { if(k==5) k = 6; j = doremi[k]; if (j>0) fprintf(fo," accidental %d # %d\n",k,j); } fprintf(fo,"intervals %4d < -12, %4d > 12\n", intervals[26],intervals[25]); for (k=0; k<13; k++) fprintf(fo," %4d",intervals[k]); fprintf(fo,"\n"); for (k=12; k<26; k++) fprintf(fo," %4d",intervals[k]); fprintf(fo,"\n"); } /* print_stats() */