/* 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() */