/* Copyright (c) 2002-2004 by Stanley M. Swanson. Distributed under the GNU General Public License, version 2 (GPL v2). */ /* vamp_utils.c from midivamp.c 035.26 */ # include "globals.h" /* insertion sort: Knuth, Numerical Recipes */ void sort_i(int *v, int m) /* single array of integers */ { int j,k; int vt; for (j=1; j=0; k--) { if (v[k]=0; k--) { if (v[k]<=vt) break; v[k+1] = v[k]; u[k+1] = u[k]; } v[k+1] = vt; u[k+1] = ut; } } void sort_dd(double *v, double *u, int m) { int j,k; double vt,ut; for (j=1; j=0; k--) { if (v[k]6 && V_CLASS==3) printf("scan_list type %d n==%d, last==%d\n",k,n,list[n+2]); } int finstring(char *ch, int max, FILE *f) /* reads line from FILE *f, makes 0 terminated string, returns length */ { int i; char *got, c, z='\0'; if (f==NULL) { printf("bad file in finstring\n"); return EOF; } got = fgets(ch,max,f); if (!got) return EOF; for (i=0;i6 && (filin!=stdin) && V_CLASS==3) printf("%s\n",line); */ lch = 0; cur_chr = line[lch]; if (nline<0) cur_chr = nline; /* 038.08 if (cur_chr==0) printf("zero length input line \n"); */ return nline; } int next_chr(void) /* next character in line, but don't over run */ { if (line[lch]==0 || lch >= nline) { cur_chr = 0; return 0; } lch++; cur_chr = line[lch]; return cur_chr; } void deblank(void) { while (cur_chr == ' ' || cur_chr == '\t') next_chr(); } int get_integer(int *ival) /* convert digit string into decimal integer */ { int jval = 0, digits=0; while (cur_chr>='0' && cur_chr<='9') { jval = 10*jval + cur_chr - '0'; digits++; next_chr(); } if (digits) *ival = jval; return digits; } /* get_integer() */ void copy_line(void) /* make copy of line so find_token can put '\0' to end strings */ { int j; tok_start = token_buf; for (j=0; j<=nline; j++) token_buf[j] = line[j]; } void lower_the_case(char *s, char *d, int n) { int i; char c; /* change to lower case for key matching */ for (i=0; i='A' && c<='Z') c += 'a' - 'A'; d[i] = c; if (c==0) break; } } /* parse token_buf[] into white-space delimited strings, one at a time. */ /* return string pointer and pointer after inserted '\0'; return NULL if no string; possible problem if *start is NULL (code to catch, longjmp on error ??) */ char *find_token(char **start) { int j,k,n; char *buf=*start, *tok=NULL, c, z='\0'; if (buf==NULL) { printf("NULL start in find_token()\n"); return NULL; } n = (token_buf+nline) - buf; if (n>nline) { *start = NULL; return NULL; } j = 0; c = *buf; while (c == ' ' || c == '\t') /* remove some white space */ { j++; buf++; c = *buf; if (j>n) break; } if (c == '\0') { *start = NULL; return NULL; } /* end of line */ tok = buf; while (c != ' ' && c != '\t' && c != '\0') /* search for white space or end */ { j++; buf++; c = *buf; if (j>n) break; } if (c == '\0') { *start = buf; return tok; } *buf = '\0'; *start = buf+1; return tok; } /* match token string to list[1:n]; 0 if no match, >0 if exact, <0 for "best approximate match" ("longest" partial match) */ /* 035.17 nlist<0 means search backwards (from top of list) */ int match_token(char *token, char **list, int nlist, int exact) { int i,j,k=0,mk=0,m,nt,ni,n, nla=nlist, jj, ambig=0; char *item; nt = strlen(token)+1; /* include terminating null char */ if (nla<0) nla = -nla; for (jj=1; jjnt) n = nt; /* search over shortest length */ for (i=m=0; imk) { mk = m; k = j; ambig = 0;} else if (m>0 && m==mk && exact==0) { ambig++; error_count++; printf(" %s ambiguous between %s and %s\n",token,list[k],item); } } if (ambig) k = 0; /* 044.23 treat as non-match (error) Matt Kaufmann */ return -k; /* approximate match */ } int save_token(char *token, char **list, int *nlist) { int j=0,n = *nlist; /* transfer token to string buffer, pointer into list[] */ if (Q_VERBOSE>6 && V_CLASS==3) printf("save_token %s %d\n",token,n); list[n] = &sav_strings[n_save_chr]; *nlist = n+1; while (token[j] != '\0') { sav_strings[n_save_chr] = token[j]; j++; n_save_chr++; if (j>MAXIN || n_save_chr>=MXCHAR) { if (flog) fprintf(flog,"*******overflow in save_token()\n"); printf("******overflow in save_token()\n"); break; } } sav_strings[n_save_chr] = '\0'; if (n_save_chr6 && V_CLASS==3) printf("make_id ***%s***\n",made_id); return made_id; } FILE* new_file(char* name, char* how) { int ic=0,lc,n,k; char chr=name[0]; FILE* fi; while(chr==' ' && ic0) { fclose(fin[at_file]); at_file--; return 0; } at_file=0; return -1; /* bottom of stack */} /* ============== from vamp_harm.c 042.20 ====================*/ int find_measures(int mel, int verbose) { int i,j,k,m,n,dur,per,inote,enote, pn,tn, nstart,nend,kbar=0,rep,alt; int ip, lp, ifrag, lfrag, kount, kf, koda=0, type, nukey, h, inkord, korknt; n = nstart = efirst[mel]; nend = elast[mel]; dur = rep = alt = nukey = 0; bars[0].s = nstart; if (mel<0 || mel>=chunks) { printf("chunk index %d out of range (find_measures)\n",mel); return 0; } type = chunk[mel].type; if (type != T_MEL) { printf("NOT melody chunk\n"); return 0; } ip = ifrag = chunk[mel].ix; lp = lfrag = chunk[mel].lx; kount = chunk[mel].count; /* zero means one fragment [ip:lp-1] */ /* if (verbose>2 && V_CLASS==5) printf("<<< -1) { /* do not check for bad chord syntax */ if (inkord==0) dur += tn; else { if (korknt==0) dur += tn; else stick[j-1] = -tn; korknt++; } } else if (pn==E_REP) rep = B_REP; else if (pn==E_REP_1 || pn==E_REP_2 || pn==E_REP_last) alt = B_END; else if (pn==E_KEY) nukey = B_KEY; else if (pn==E_START_CHORD) { inkord = 1; korknt = 0; } else if (pn==E_END_CHORD) { inkord = 0; korknt = 0; } if (pn==E_BAR && dur>0) { bars[kbar].e = n; bars[kbar].t = dur; bars[kbar+1].s = n + 1; i = alt | rep | nukey; if (dur!=ticks_in_meas) i = i | B_LEN; if (verbose>2 && V_CLASS==5) printf(" bar %2d b %4d e %4d dur %4d marks %d\n", kbar,bars[kbar].s,n,dur,i); /* 03e.07 find half measure point (may not be correct if there are chords) */ /* 030.29 will still have problems for a single note measure */ /* 030.29 old code:: k = 0; for (h=bars[kbar].s;h -1) k += tn+tn; if (k>dur) break; } */ k = m = 0; for (h=bars[kbar].s; h0) k += tn+tn; if (k>dur) break; } if ( k - 2*tn != dur ) { printf(" bad break in measure %d dur %d half %d\n",kbar+1,dur,k/2-tn); if (k -2*tn<=0 && h2 && V_CLASS==5) { int ii; printf("meas %2d k %4d tn %3d m %2d stick",kbar+1,k,tn,m); for (ii=0; ii0) { bars[kbar].e = n; bars[kbar].t = dur; i = alt | rep | nukey; if (dur!=ticks_in_meas) i = i | B_LEN; if (verbose>3) printf(" bar %2d b %4d e %4d dur %4d marks %d end frag\n", kbar,bars[kbar].s,n,dur,i); k = m = 0; for (h=bars[kbar].s; h0) k += tn+tn; if (k>dur) break; } if ( k - 2*tn != dur ) { printf(" bad break in measure %d \n",kbar); if (k -2*tn<=0 && h=lfrag) break; /* loop thru fragments */ n = nstart = frags[kf]; nend = frags[kf+1]; } /* while (1) outer fragment loop */ return kbar; } /* find_meas() */ /* select notes from abc sequence, depending on mode (all, accent, bound) */ /* ?? print notes if verbose and interactive ?? */ int select_notes(int nstart, int nend, int period, int mode, int barbreak) { int i,j,k,m,n,dur,per,inote,enote, pn,tn,center; n = nstart; dur = 0; snotes = 0; inote = enote = -1; per = 20000; if (period>0) per = period; guitar_ch_1 = guitar_ch_2 = NULL; /* select notes for period or to measure bar */ /* pitch in range [0,127], otherwise various marks */ while (n -1) { dur += tn; if (pn1 && V_CLASS==5) printf("set key %d key %d mode %d\n",tn,key_major,mode_delta); if (snotes>0) printf("key set inside measure %d\n",smeas); } if (n=nend) break; if (dur>=per) break; if (pn==E_BAR) { smeas++; if (dur>0 && barbreak) break; } /* may need better logic for lead-ins...*/ } /* while (n0) smallest = k; } if (total != ticks_in_meas || smeas < 5) printf("oddball measure length %d small %d\n",total, smallest); if ( meter_num=kt ) { stone[k] = stone[j]; stick[k] = stick[j]; kt += nt; k++; } tt += stick[j]; } if (smeas<5) printf("nacc %d select %d\n",nacc,k); snotes = k; } /* select_accented() */ int abc_ticks(int ip, int lp) /* total abc duration tics[ip] ... tics[lp-1] */ { int i, notemark, inkord=0, knt=0, ticks=0, dur; for (i=ip; i0 && on_beat && first_beat) printf("pedometer: begin phrase %d\n",kphrase+1); */ int j; if (dur>0) { /* cumulate ticks */ tick_sum += dur; delta_ticks += dur; if (delta_ticksticks_in_beat) printf("excess ticks %d\n",delta_ticks); */ /* may give problems for notes longer than one beat... */ first_beat = last_beat = 0; while (delta_ticks>=ticks_in_beat) { delta_ticks -= ticks_in_beat; current_beat++; nbeat++; } if (current_beat+1==beats_in_phrase) { last_beat = 1; } if (current_beat>=beats_in_phrase) { kphrase++; current_beat -= beats_in_phrase; if (current_beat>0 || delta_ticks>0) printf("pedometer: end phrase %d extra beats %d ticks %d\n", kphrase,current_beat,delta_ticks); if (current_beat == 0) first_beat = 1; if (kphrase>=lphrase) { /*042.28 more serious reset and check for midi generation */ if (delta_ticks>0) printf("end of phrase list, delta_ticks %d, nbeat %d\n",delta_ticks,nbeat); kphrase = iphrase; current_beat = delta_ticks = nbeat = 0; down_beat = on_beat = first_beat = 1; up_beat = off_beat = last_beat = 0; } beats_in_phrase = phrasing[kphrase]; } /* if (current_beat>=beats_in_phrase) change kphrase */ if (current_beat&1) { up_beat = 1; down_beat = 0; } else { up_beat = 0; down_beat = 1; } if (delta_ticks==0) { on_beat = 1; off_beat = 0; } } /* else if (delta_ticks>ticks_in_beat) */ } else if (dur==0) { /* consistency check (e.g. at E_BAR) */ if (off_beat){ printf("pedometer out of synch: beat %d delta %d\n", tick_sum/ticks_in_beat+1,delta_ticks); printf("measure %d ",smeas+1); for (j=0;j2 && V_CLASS==3) printf("pedometer() initialize: ticks_in_meas %d ticks_in_beat %d quantum %d\n", ticks_in_meas,ticks_in_beat,quantum); } else { /* print state */ printf("pedometer() state: beat %d delta %d\n", tick_sum/ticks_in_beat+1,delta_ticks); printf(" down %d up %d on %d off %d current beat phrase %d\n", down_beat, up_beat, on_beat, off_beat, current_beat+1, kphrase+1); } return tick_sum/ticks_in_beat; /* completed ordinal beats 0..63 or whatever... */ } /* pedometer() */