/* Copyright (c) 2002-2004 by Stanley M. Swanson.
Distributed under the GNU Geneeral Public License, version 2 (GPL v2). */
/* globals.c for midivamp.c 035.26 */
/* midivamp.c 1-sep-2002 xml like supercommands to control repetitions, vamping */
/* 29-jan-2003: events, params, chunk changes.. (major cleanup) */
/* add command driven generation 7-May-2002 */
/* split off miditest.c 18-Feb-2001 */
/* start parsing of abc like files for pitch-tune and rhythm info */
/* midigen.c, stan swanson 7-Jan-2001 */
/* merge melody line (tune), rhythm, and dynamics to produce MIDI file */
# include
/* # include */
# include /* for time stamp on logfile */
# include
# include
# include
# define _GLOBALS_C_
# include "globals.h"
# if (0) /* mirror of real definitions in globals.h */
# define MAXOUT 80000 /* size of MIDI out buffer bout[] */
# define MXNOTE 4096 /* decoded abc stuff (melody, vamp, chords) */
# define MXHELP 17 /* command options printed with help '?'*/
# define MXMFILE 50 /* number of temporary MIDI output files */
# define MXATFILE 10 /* depth of indirect file nesting '@' */
# define MXLIST 23 /* maximum list elements +3 */
# define MAXIN 136 /* length of input buffers */
# define MXCHUNK 400 /* number of abc chunks input */
# define MXMETA 21 /* number of */
# define MXCHAR 4096 /* characters for string storage */
# define MXGC 2048 /* maximum characters in guitar chords */
# define MXACC 4096 /* accent entries for phrasing */
# define MXFRAG 4096 /* fragment storage (repeats, chord limits) */
# define MXVAR 400 /* events for program-variation */
# define MXPT 512 /* selected notes stone[], stick[]; veloc[],emphasis[] */
# endif
int Q_META=1, Q_ABC=0, Q_PHRASE=0, Q_CHORD=0, Q_VAMP=0, Q_LOOP=0, Q_EVENT=0,
Q_ACCENT=0, Q_EXPERT=0, V_CLASS=0,
Q_VERBOSE=1, Q_PLAY=1, Q_BLUR=0, Q_TESTA=0, Q_TESTB=0, EXPAND_CHORDS=0;
float H_raw_part=1.0, H_root_wt=1.0;
/* pseudo enums for abc syntactic constructs (non-notes) cf. nextnote() */
const int E_REST=128, E_KEY=-2,
E_START_CHORD=-4, E_END_CHORD=-5, E_GUITAR_CHORD = -6,
E_TIE = -7, E_BAR=-9, E_REP=-10, E_REP_1=-11, E_REP_2=-12, E_REP_last=-13;
/* for chunk[].type */
const int T_MEL=1, T_VAMP=0, T_CHORD=2,
T_ACCENT=-1, T_PHRASE=-2, T_SPECIAL=-4;
int lch=0, nline=0, chunks=0, kphr=16,nstr=0,n_meta,ntoken,n_save_chr=0,
ixgch=0, error_count=0, over_flows=0;
int qswap = 1, nout=0, quantum,npitch,nbeat, repeats=1, chordflag=0,
beat_usec, total_ticks, quarterticks, staccato;
float bpm = 120.0;
int measure, tictoc, previ, ticks_in_meas, meter_num=4, meter_denom=4, default_note=8;
int n_meas_tick, meas_tick[6], meas_tick_count[6]; /* measure length statistics */
int gen_ticks, gen_meas, gen_rep, next_event_epoch, gen_epoch;
int doremi[25], intervals[27], last_tone, tune_tonic,
tonal_center, mode_delta, key_major, central_tone;
/* for relative pitch and intervals */
int tuple_p, tuple_q, tuple_r, tuple_count, broken_rhythm; /* 020.11 */
int tonic=60, key, kromote[10], whitenote[10], barnote[10], dwell[12];
int cur_chr=0, ix_chr=0; /* global current character and index in line[] */
char line[MAXIN]; /* global character input buffer */
/* session prefix for .log, .nnn.midi files, comments for midi_info */
char session[MAXIN], commenta[MAXIN],commentb[MAXIN],title[MAXIN],
token_buf[MAXIN], *tok_start, *copyleft=NULL, made_id[16];
FILE *fout; /* global output file pointer */
FILE *fin[MXATFILE], *flog, *filin;
int at_file=0, ksession=0, kc=0, dot_sess, abc_index=0;
char bout[MAXOUT]; /* MIDI output buffer */
char *guitar_ch_1, *guitar_ch_2, *guitar_ch_3, *guitar_ch_4;
char chunkname[MXCHUNK][8], sav_strings[MXCHAR], guitar_ch[MXGC],
*tokens[MXCHUNK] = { "tune","chords"};;
int pitch[MXNOTE], tics[MXNOTE], scale[128]; /* 031.29 vel[MXNOTE] */
int epoch[MXNOTE], event[MXNOTE], efirst[MXCHUNK],elast[MXCHUNK];
/* pointers to repetition structure in current tune (: [n etc.) */
int krep, rep_mark[20];
int solo_chan, map_voice_to_chan[16]; /* 032.20 instrument mappings */
/* 031.29: a structure to handle named melodies, vamps, chord sequences and accents */
struct {char* name; int type, count, ix, lx; } chunk[MXCHUNK];
/* sanity counters for chunks, also used for defaulting */
int accent_count=0, melody_count=0, chord_count=0, vamp_count=0, phrase_count;
int last_mel= -1, last_chord= -1, last_intro= -1, last_vamp= -1;
/* 031.29 start:(stop+1) pairs for complicated chunks(count>0) */
int kfrag=0, kev, frags[MXFRAG], jot[100];
/* 031.29: params for staccato, mix volume, pan, etc. may go into voice struct */
int mix_mel=104, mix_ch=104, stac_mel=5, stac_ch=30, pan_mel=64, pan_ch=64;
int trans_mel=0, trans_ch=0; /* transpose delta in halftones */
/* a start on varation/program events for generation: */
struct { int type, rep, meas, tick, chunk, data; } events[MXVAR];
int nmeta = 18;
char *metacmd[MXMETA] = { NULL,"quit","melody","vamp","chords","accent",
"variations","loops","instrument","tempo","generate","harmony",
"repeat", "midi","param", "events","xtra","phrase", NULL,NULL };
/* pseudo enum for metacommand ID (== index postion of string) *
# if (0)
# define MC_QUIT 1
# define MC_MELODY 2
# define MC_VAMP 3
# define MC_CHORDS 4
# define MC_ACCENT 5
# define MC_VARIATION 6
# define MC_LOOP 7
# define MC_INSTRUM 8
# define MC_TEMPO 9
# define MC_GEN 10
# define MC_HARMONY 11
# define MC_REPEAT 12
# define MC_MIDI 13
# define MC_PARAM 14
# define MC_EVENT 15
# define MC_XTRA 16
# define MC_PHRASE 17
# endif
/* default velocities for vamp phrasing, 028.25, 042.27:phrase and dynamics */
int nphrase=2, kphrase=6, iphrase=6, lphrase=8; /* phrase limits and counter */
int idyn=0, kdyn=0, ldyn=0, deldown=0, delup=0, deloff=0; /* velocity contour */
int master_volume=104, volume_delta=0;
int iacc=8, lacc=24, kacc=8, macc=24; /* accent limits and counter */
int phrasing[MXACC] = { 6,8, 0,0, 0,0, 8,8, /* [0:7] are default phrase chunk */
120,1060,80,1060, 90,1060,80,1060,
100,1060,80,1060, 90,1060,80,1060 };
int n_emph, veloc[MXPT], emphasis[MXPT];
/* commands and short explanations for help */
char *help[MXHELP] = { "? help: print this list",
"# comment text to output file","% comment line: ignored",
"r rhythm (sequence of note lengths in MIDI ticks)",
"t tune (note += key base)",
"v velocity/volume for r/t sequence (add 2000 or 1000 for accent)",
" numbers are a space separated list e.g. 12 20 1 3",
" or 'for' parameters: '=' start end incr",
"i instruments (MIDI 1-128, drums 135-181)",
"a accent used for velocity + 2000, +1000",
"g [file]: generate MIDI file",
"p play [current]/n/sequence",
"k key: base notes [default 0] added to tune values",
"o order of looping [default: r l a i ]",
"l loop repetitions (lid) [1]",
"c (MIDI) code_insert: lid c1 c2 ... cn",
"d dump lists (unimplemented)"
}; /* end of help[] */
/* x_list[0] is a flag: 0: enumerated, 1: 'for' list
if enumerated, n = x_list[1] is the number of elements,
x_list[2] is current element in the enumeration
and x_list[3...n+2] are the values
if 'for', one iterates (for i=x_list[3]; i