commit 0497c9a75bccf70acc36acddf260ac7101876a7d Author: Seymour Shlien Date: Sun Jul 12 12:40:01 2020 -0400 abcMIDI-2020.07.06.zip diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a2379a2 --- /dev/null +++ b/Makefile @@ -0,0 +1,174 @@ +# Generic unix/gcc Makefile for abcMIDI package +# +# +# compilation #ifdefs - you need to compile with these defined to get +# the code to compile with PCC. +# +# NOFTELL in midifile.c and genmidi.c selects a version of the file-writing +# code which doesn't use file seeking. +# +# PCCFIX in mftext.c midifile.c midi2abc.c +# comments out various things that aren't available in PCC +# +# ANSILIBS includes some ANSI header files (which gcc can live without, +# but other compilers may want). +# +# USE_INDEX causes index() to be used instead of strchr(). This is needed +# by some pre-ANSI C compilers. +# +# ASCTIME causes asctime() to be used instead of strftime() in pslib.c. +# If ANSILIBS is not set, neither routine is used. +# +# KANDR selects functions prototypes without argument prototypes. +# currently yaps will only compile in ANSI mode. +# +# +# On running make, you may get the mysterious message : +# +# ', needed by `parseabc.o'. Stop `abc.h +# +# This means you are using GNU make and this file is in DOS text format. To +# cure the problem, change this file from using PC-style end-of-line (carriage +# return and line feed) to unix style end-of-line (line feed). + +VERSION = @VERSION@ + +CC = gcc +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} + +CFLAGS = -DANSILIBS -O2 +CPPFLAGS = -DHAVE_CONFIG_H -I. +LDFLAGS = -lm + +prefix = /usr/local +exec_prefix = ${prefix} + +srcdir = . +VPATH = . +bindir = ${exec_prefix}/bin +libdir = ${exec_prefix}/lib +datadir = ${prefix}/share +docdir = ${prefix}/share/doc/abcmidi +mandir = ${prefix}/share/man/man1 + +binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch + +all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch + +OBJECTS_ABC2MIDI=parseabc.o store.o genmidi.o midifile.o queues.o parser2.o stresspat.o +abc2midi : $(OBJECTS_ABC2MIDI) + $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) -lm +$(OBJECTS_ABC2MIDI): abc.h parseabc.h config.h Makefile + +OBJECTS_ABC2ABC=parseabc.o toabc.o +abc2abc : $(OBJECTS_ABC2ABC) + $(CC) $(CFLAGS) -o abc2abc $(OBJECTS_ABC2ABC) $(LDFLAGS) +$(OBJECTS_ABC2ABC): abc.h parseabc.h config.h Makefile + +OBJECTS_MIDI2ABC=midifile.o midi2abc.o +midi2abc : $(OBJECTS_MIDI2ABC) + $(CC) $(CFLAGS) -o midi2abc $(OBJECTS_MIDI2ABC) $(LDFLAGS) +$(OBJECTS_MIDI2ABC): abc.h midifile.h config.h Makefile + +OBJECTS_MFTEXT=midifile.o mftext.o crack.o +mftext : $(OBJECTS_MFTEXT) + $(CC) $(CFLAGS) -o mftext $(OBJECTS_MFTEXT) $(LDFLAGS) +$(OBJECTS_MFTEXT): abc.h midifile.h config.h Makefile + +OBJECTS_YAPS=parseabc.o yapstree.o drawtune.o debug.o pslib.o position.o parser2.o +yaps : $(OBJECTS_YAPS) + $(CC) $(CFLAGS) -o yaps $(OBJECTS_YAPS) $(LDFLAGS) +$(OBJECTS_YAPS): abc.h midifile.h config.h Makefile + +OBJECTS_MIDICOPY=midicopy.o +midicopy : $(OBJECTS_MIDICOPY) + $(CC) $(CFLAGS) -o midicopy $(OBJECTS_MIDICOPY) $(LDFLAGS) +$(OBJECTS_MIDICOPY): abc.h midifile.h midicopy.h config.h Makefile + +OBJECTS_ABCMATCH=abcmatch.o matchsup.o parseabc.o +abcmatch : $(OBJECTS_ABCMATCH) + $(CC) $(CFLAGS) -o abcmatch $(OBJECTS_ABCMATCH) $(LDFLAGS) +$(OBJECTS_ABCMATCH): abc.h midifile.h config.h Makefile + +parseabc.o : parseabc.c abc.h parseabc.h + +parser2.o : parser2.c abc.h parseabc.h parser2.h + +toabc.o : toabc.c abc.h parseabc.h + +# could use -DNOFTELL here +genmidi.o : genmidi.c abc.h midifile.h genmidi.h + +stresspat.o : stresspat.c + +store.o : store.c abc.h parseabc.h midifile.h genmidi.h + +queues.o : queues.c genmidi.h + +# could use -DNOFTELL here +midifile.o : midifile.c midifile.h + +midi2abc.o : midi2abc.c midifile.h + +midicopy.o : midicopy.c midicopy.h + +abcmatch.o: abcmatch.c abc.h + +crack.o : crack.c + +mftext.o : mftext.c midifile.h + +# objects needed by yaps +# +yapstree.o: yapstree.c abc.h parseabc.h structs.h drawtune.h + +drawtune.o: drawtune.c structs.h sizes.h abc.h drawtune.h + +pslib.o: pslib.c drawtune.h + +position.o: position.c abc.h structs.h sizes.h + +debug.o: debug.c structs.h abc.h + +#objects for abcmatch +# +matchsup.o : matchsup.c abc.h parseabc.h parser2.h + +clean : + rm *.o ${binaries} + +install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) -m 755 ${binaries} $(DESTDIR)$(bindir) + + # install documentation + $(INSTALL) -d $(DESTDIR)${docdir} + $(INSTALL) -m 644 doc/*.txt $(DESTDIR)$(docdir) + $(INSTALL) -m 644 doc/AUTHORS $(DESTDIR)$(docdir) + $(INSTALL) -m 644 doc/CHANGES $(DESTDIR)$(docdir) + $(INSTALL) -m 644 VERSION $(DESTDIR)$(docdir) + + # install manpages + $(INSTALL) -d $(DESTDIR)${mandir} + $(INSTALL) -m 644 doc/*.1 $(DESTDIR)$(mandir) + + +uninstall: + echo "uninstalling..."; + #rm -f $(DESTDIR)$(bindir)/$(binaries) + rm -f $(DESTDIR)$(bindir)/abc2midi + rm -f $(DESTDIR)$(bindir)/abc2abc + rm -f $(DESTDIR)$(bindir)/yaps + rm -f $(DESTDIR)$(bindir)/midi2abc + rm -f $(DESTDIR)$(bindir)/mftext + rm -f $(DESTDIR)$(bindir)/abcmatch + rm -f $(DESTDIR)$(bindir)/midicopy + rm -f $(DESTDIR)$(docdir)/*.txt + rm -f $(DESTDIR)$(docdir)/AUTHORS + rm -f $(DESTDIR)$(docdir)/CHANGES + rm -f $(DESTDIR)$(docdir)/VERSION + rm -f $(DESTDIR)$(mandir)/*.1 + rmdir $(DESTDIR)$(docdir) + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..d136d99 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,174 @@ +# Generic unix/gcc Makefile for abcMIDI package +# +# +# compilation #ifdefs - you need to compile with these defined to get +# the code to compile with PCC. +# +# NOFTELL in midifile.c and genmidi.c selects a version of the file-writing +# code which doesn't use file seeking. +# +# PCCFIX in mftext.c midifile.c midi2abc.c +# comments out various things that aren't available in PCC +# +# ANSILIBS includes some ANSI header files (which gcc can live without, +# but other compilers may want). +# +# USE_INDEX causes index() to be used instead of strchr(). This is needed +# by some pre-ANSI C compilers. +# +# ASCTIME causes asctime() to be used instead of strftime() in pslib.c. +# If ANSILIBS is not set, neither routine is used. +# +# KANDR selects functions prototypes without argument prototypes. +# currently yaps will only compile in ANSI mode. +# +# +# On running make, you may get the mysterious message : +# +# ', needed by `parseabc.o'. Stop `abc.h +# +# This means you are using GNU make and this file is in DOS text format. To +# cure the problem, change this file from using PC-style end-of-line (carriage +# return and line feed) to unix style end-of-line (line feed). + +VERSION = @VERSION@ + +CC = @CC@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +CFLAGS = -DANSILIBS @CFLAGS@ +CPPFLAGS = @DEFS@ @CPPFLAGS@ -I. +LDFLAGS = @LDFLAGS@ -lm + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +srcdir = @srcdir@ +VPATH = @srcdir@ +bindir = @bindir@ +libdir = @libdir@ +datadir = @datarootdir@ +docdir = @datarootdir@/doc/abcmidi +mandir = @datarootdir@/man/man1 + +binaries=abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch + +all : abc2midi midi2abc abc2abc mftext yaps midicopy abcmatch + +OBJECTS_ABC2MIDI=parseabc.o store.o genmidi.o midifile.o queues.o parser2.o stresspat.o +abc2midi : $(OBJECTS_ABC2MIDI) + $(CC) $(CFLAGS) -o abc2midi $(OBJECTS_ABC2MIDI) $(LDFLAGS) -lm +$(OBJECTS_ABC2MIDI): abc.h parseabc.h config.h Makefile + +OBJECTS_ABC2ABC=parseabc.o toabc.o +abc2abc : $(OBJECTS_ABC2ABC) + $(CC) $(CFLAGS) -o abc2abc $(OBJECTS_ABC2ABC) $(LDFLAGS) +$(OBJECTS_ABC2ABC): abc.h parseabc.h config.h Makefile + +OBJECTS_MIDI2ABC=midifile.o midi2abc.o +midi2abc : $(OBJECTS_MIDI2ABC) + $(CC) $(CFLAGS) -o midi2abc $(OBJECTS_MIDI2ABC) $(LDFLAGS) +$(OBJECTS_MIDI2ABC): abc.h midifile.h config.h Makefile + +OBJECTS_MFTEXT=midifile.o mftext.o crack.o +mftext : $(OBJECTS_MFTEXT) + $(CC) $(CFLAGS) -o mftext $(OBJECTS_MFTEXT) $(LDFLAGS) +$(OBJECTS_MFTEXT): abc.h midifile.h config.h Makefile + +OBJECTS_YAPS=parseabc.o yapstree.o drawtune.o debug.o pslib.o position.o parser2.o +yaps : $(OBJECTS_YAPS) + $(CC) $(CFLAGS) -o yaps $(OBJECTS_YAPS) $(LDFLAGS) +$(OBJECTS_YAPS): abc.h midifile.h config.h Makefile + +OBJECTS_MIDICOPY=midicopy.o +midicopy : $(OBJECTS_MIDICOPY) + $(CC) $(CFLAGS) -o midicopy $(OBJECTS_MIDICOPY) $(LDFLAGS) +$(OBJECTS_MIDICOPY): abc.h midifile.h midicopy.h config.h Makefile + +OBJECTS_ABCMATCH=abcmatch.o matchsup.o parseabc.o +abcmatch : $(OBJECTS_ABCMATCH) + $(CC) $(CFLAGS) -o abcmatch $(OBJECTS_ABCMATCH) $(LDFLAGS) +$(OBJECTS_ABCMATCH): abc.h midifile.h config.h Makefile + +parseabc.o : parseabc.c abc.h parseabc.h + +parser2.o : parser2.c abc.h parseabc.h parser2.h + +toabc.o : toabc.c abc.h parseabc.h + +# could use -DNOFTELL here +genmidi.o : genmidi.c abc.h midifile.h genmidi.h + +stresspat.o : stresspat.c + +store.o : store.c abc.h parseabc.h midifile.h genmidi.h + +queues.o : queues.c genmidi.h + +# could use -DNOFTELL here +midifile.o : midifile.c midifile.h + +midi2abc.o : midi2abc.c midifile.h + +midicopy.o : midicopy.c midicopy.h + +abcmatch.o: abcmatch.c abc.h + +crack.o : crack.c + +mftext.o : mftext.c midifile.h + +# objects needed by yaps +# +yapstree.o: yapstree.c abc.h parseabc.h structs.h drawtune.h + +drawtune.o: drawtune.c structs.h sizes.h abc.h drawtune.h + +pslib.o: pslib.c drawtune.h + +position.o: position.c abc.h structs.h sizes.h + +debug.o: debug.c structs.h abc.h + +#objects for abcmatch +# +matchsup.o : matchsup.c abc.h parseabc.h parser2.h + +clean : + rm *.o ${binaries} + +install: abc2midi midi2abc abc2abc mftext midicopy yaps abcmatch + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) -m 755 ${binaries} $(DESTDIR)$(bindir) + + # install documentation + $(INSTALL) -d $(DESTDIR)${docdir} + $(INSTALL) -m 644 doc/*.txt $(DESTDIR)$(docdir) + $(INSTALL) -m 644 doc/AUTHORS $(DESTDIR)$(docdir) + $(INSTALL) -m 644 doc/CHANGES $(DESTDIR)$(docdir) + $(INSTALL) -m 644 VERSION $(DESTDIR)$(docdir) + + # install manpages + $(INSTALL) -d $(DESTDIR)${mandir} + $(INSTALL) -m 644 doc/*.1 $(DESTDIR)$(mandir) + + +uninstall: + echo "uninstalling..."; + #rm -f $(DESTDIR)$(bindir)/$(binaries) + rm -f $(DESTDIR)$(bindir)/abc2midi + rm -f $(DESTDIR)$(bindir)/abc2abc + rm -f $(DESTDIR)$(bindir)/yaps + rm -f $(DESTDIR)$(bindir)/midi2abc + rm -f $(DESTDIR)$(bindir)/mftext + rm -f $(DESTDIR)$(bindir)/abcmatch + rm -f $(DESTDIR)$(bindir)/midicopy + rm -f $(DESTDIR)$(docdir)/*.txt + rm -f $(DESTDIR)$(docdir)/AUTHORS + rm -f $(DESTDIR)$(docdir)/CHANGES + rm -f $(DESTDIR)$(docdir)/VERSION + rm -f $(DESTDIR)$(mandir)/*.1 + rmdir $(DESTDIR)$(docdir) + diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..d90ba63 --- /dev/null +++ b/VERSION @@ -0,0 +1,2 @@ +2020 June 30 2020 + diff --git a/abc.h b/abc.h new file mode 100644 index 0000000..72baab0 --- /dev/null +++ b/abc.h @@ -0,0 +1,146 @@ +/* abc.h - header file shared by abc2midi, abc2abc and yaps */ +/* Copyright James Allwright 2000 */ +/* may be copied under the terms of the GNU public license */ + +typedef enum { +ABC2MIDI, +ABC2ABC, +YAPS, +ABCMATCH} programname; + +/* define types of abc object */ +typedef enum { +/* types of bar sign */ +SINGLE_BAR, +DOUBLE_BAR, +DOTTED_BAR, +BAR_REP, +REP_BAR, +PLAY_ON_REP, +REP1, +REP2, +/* BAR1 = SINGLE_BAR + REP1 */ +/* REP_BAR2 = REP_BAR + REP2 */ +BAR1, +REP_BAR2, +DOUBLE_REP, +THICK_THIN, +THIN_THICK, +/* other things */ +PART, +TEMPO, +TIME, +KEY, +REST, +TUPLE, +/* CHORD replaced by CHORDON and CHORDOFF */ +NOTE, +NONOTE, +OLDTIE, +TEXT, +SLUR_ON, +SLUR_OFF, +TIE, +CLOSE_TIE, +TITLE, +CHANNEL, +TRANSPOSE, +RTRANSPOSE, +GTRANSPOSE, +GRACEON, +GRACEOFF, +SETGRACE, +SETC, +SETTRIM, +EXPAND, +GCHORD, +GCHORDON, +GCHORDOFF, +VOICE, +CHORDON, +CHORDOFF, +CHORDOFFEX, +DRUMON, +DRUMOFF, +DRONEON, +DRONEOFF, +SLUR_TIE, +TNOTE, +/* broken rhythm */ +LT, +GT, +DYNAMIC, +LINENUM, +MUSICLINE, +MUSICSTOP, +WORDLINE, +WORDSTOP, +INSTRUCTION, +NOBEAM, +CHORDNOTE, +CLEF, +PRINTLINE, +NEWPAGE, +LEFT_TEXT, +CENTRE_TEXT, +VSKIP, +COPYRIGHT, +COMPOSER, +ARPEGGIO, +SPLITVOICE, +META, +PEDAL_ON, +PEDAL_OFF, +EFFECT +} featuretype; + +/* note decorations */ +#define DECSIZE 13 +extern char decorations[]; +#define STACCATO 0 +#define TENUTO 1 +#define LOUD 2 +#define ROLL 3 +#define FERMATA 4 +#define ORNAMENT 5 +#define TRILL 6 +#define BOWUP 7 +#define BOWDOWN 8 +#define BREATH 9 +#define CODA 10 +#define UPPERMORDENT 11 +#define SEGNO 12 + +/* The vstring routines provide a simple way to handle */ +/* arbitrary length strings */ +struct vstring { +int len; +int limit; +char* st; +}; +#ifndef KANDR +/* vstring routines */ +extern void initvstring(struct vstring* s); +extern void extendvstring(struct vstring* s); +extern void addch(char ch, struct vstring* s); +extern void addtext(char* text, struct vstring* s); +extern void clearvstring(struct vstring* s); +extern void freevstring(struct vstring* s); +/* error-handling routines */ +extern void event_error(char *s); +extern void event_fatal_error(char *s); +extern void event_warning(char *s); +#else +/* vstring routines */ +extern void initvstring(); +extern void extendvstring(); +extern void addch(); +extern void addtext(); +extern void clearvstring(); +extern void freevstring(); +/* error-handling routines */ +extern void event_error(); +extern void event_fatal_error(); +extern void event_warning(); +#endif + diff --git a/abcmatch.c b/abcmatch.c new file mode 100644 index 0000000..6e419eb --- /dev/null +++ b/abcmatch.c @@ -0,0 +1,1561 @@ +/* abcmatch.c +This contains the main program and core functions of the program to +compare abc files. + +The abc file may either be a single tune or a compilation +of tunes. The program searches for specific bars in the +file and returns its positions in the file. There are +various matching criteria ranging from exact to approximate +match. The program assumes there is a file called match.abc +containing a description of the bars to be matched. Though +you can run abcmatch as a stand alone program, it was +really designed to run with a graphical user interface such +as runabc.tcl (version 1.59 or higher). + + +Limitations: +tied notes longer than 8 quarter notes are ignored. + +Road map to the code: + +Matching: + The templates derived from match.abc are stored in the + global arrays tpmidipitch, tpnotelength, tpnotes, tpbars, and + tpbarlineptr. + + If temporal quantization is selected, (i.e. qnt >0) then + the template is represented by mpitch_samples[] and msamples[]. + The temporal quantization representation is created by the + function make_bar_image (). All the bars in the template + file match.abc are converted and stored in mpitch_samples + and msamples[] when match.abc is processed. However, the bars + in the tunes compared are converted only as needed. + + match_notes() is called if there is no temporal quantization + (exact matching). + match_samples() is called if there is temporal quantization. + + difference_midipitch() is called if we are doing contour + matching on the temporal quantized images. For exact matching + (i.e. qnt == 0), when contouring is specified (con ==1) the + differencing (and possibly quantization of the contour) is + performed in the function match_notes. + + count_matched_tune_bars () is called if only want an overview + (brief ==1). + find_and_report_matching_bars() is called if we want the details + (brief !=1); +*/ + + + +#define VERSION "1.74 June 04 2020 abcmatch" +#include +#include +#include +#include "abc.h" +#include "parseabc.h" + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +#define BAR -1000 +#define RESTNOTE -2000 +#define ANY -3000 + +enum ACTION +{ + none, + cpitch_histogram, + cwpitch_histogram, + clength_histogram, + cpitch_histogram_table, + interval_pdf, + interval_pdf_table +} action; + + +int *checkmalloc (int); +extern int getarg (char *, int, char **); +void free_feature_representation (); + +/* variables shared with abcparse.c and abcstore.c */ +/* many of these variables are used in event_int which has + been moved to this file. +*/ +extern int *pitch, *num, *denom, *pitchline; +extern char **atext, **words; +extern featuretype *feature; +extern int notes; +extern int note_unit_length; +extern int time_num, time_denom; +extern int sf, mi; +extern FILE *fp; +extern int xrefno; +extern int check, nowarn, noerror, verbose, maxnotes, xmatch, dotune; +extern int maxtexts, maxwords; +extern int voicesused; + +/* midipitch: pitch in midi units of each note in the abc file. A pitch + of zero is reserved for rest notes. Bar lines are signaled with BAR. + If contour matching is used, then all the pitch differences are offsetted + by 256 to avoid the likelihood of a zero difference mistaken for a + rest. + notelength: represents the length of a note. A quarter note is 24 units + (assuming L:1/4 in abc file) and all other note sizes are proportional. + Thus a half note is 48 units, a sixteenth note is 6 units. + nnotes: the number of notes in the midipitch array. + nbars: the number of bar lines in the midipitch array. + barlineptr: indicates the index in midipitch, notelength of the start + of bar lines. +*/ + +/* data structure for input to matcher. */ +int imidipitch[2000]; /* pitch-barline midi note representation of input tune */ +int inotelength[2000]; /* notelength representation of input tune */ +int innotes; /*number of notes in imidipitch,inotelength representation */ +int inbars; /*number of bars in input tune */ +int ibarlineptr[500]; /*pointers to bar lines in imidipitch */ +int itimesig_num, itimesig_denom; +int imaxnotes = 2000; /* maximum limits of this program */ +int imaxbars = 200; +int resolution = 12; /* default to 1/8 note resolution */ +int anymode = 0; /* default to matching all bars */ +int ignore_simple = 0; /* ignore simple bars */ +int con = 0; /* default for no contour matching */ +int qnt = 0; /* pitch difference quantization flag */ +int brief = 0; /* set brief to 1 if brief mode */ +int cthresh = 3; /* minimum number of common bars to report */ +int fixednumberofnotes=0; /* for -fixed parameter */ +int fileindex = -1; +int wphist, phist, lhist; /* flags for computing pitch or length histogram */ +int pdftab; /* flag for computing pitch pdf for each tune */ +int qntflag = 0; /* flag for turning on contour quantization */ +int wpintv = 0; /* flag for computing interval pdf */ +int wpipdf = 0; /* flag for computing interval pdf for each tune*/ +int norhythm = 0; /* ignore note lengths */ +int levdist = 0; /* levenshtein distance */ + +char *templatefile; + +/* data structure for matcher (template) (usually match.abc)*/ +int tpmidipitch[1000]; /*pitch-barline representation for template */ +int tpnotelength[1000]; /*note lengths for template */ +int tpnotes; /* number of notes in template */ +int tpbars; /* number of bar lines in template */ +int tpbarlineptr[300]; /* I don't expect 300 bar lines, but lets play safe */ +int tptimesig_num, tptimesig_denom; +int tpmaxnotes = 1000; /* maximum limits of this program */ +int tpmaxbars = 300; +unsigned char tpbarstatus[300]; + +int pitch_histogram[128]; +int weighted_pitch_histogram[128]; +int length_histogram[144]; +int interval_histogram[128]; +int lastpitch; + +/* compute the midi offset for the key signature. Since + we do not have negative indices in arrays, sf2midishift[7] + corresponds to no flats/no sharps, ie. C major scale. + If sf is the number of sharps (when positive) and the number of + flats when negative, then sf2midishift[7+i] is the offset in + semitones from C. Thus G is 7, D is 2, Bb is 10 etc. +*/ +int sf2midishift[] = { 11, 6, 1, 8, 3, 10, 5, 0, 7, 2, 9, 4, 11, 6, 1, }; + + +/* when using a resolution greater than 0, time resolution + * is reduced by a certain factor. The resolution is reduced + * in the arrays ipitch_samples and mpitch_samples. We need + * more room in mpitch_samples for the template, since we + * use this template over and over. Therefore we compute it + * and store it for the entire template. On the other hand, the + * input tune is always changing, so we only store one bar at + * a time for the input tune. + */ + +int ipitch_samples[400], isamples; +int mpitch_samples[4000], msamples[160]; /* maximum number of bars 160 */ + +char titlename[48]; +char keysignature[16]; + +int tpxref = 0; /* template reference number */ +int tp_fileindex = 0; /* file sequence number for tpxref */ + + +void +make_note_representation (int *nnotes, int *nbars, int maxnotes, int maxbars, + int *timesig_num, int *timesig_denom, + int *barlineptr, int *notelength, int *midipitch) +/* converts between the feature,pitch,num,denom representation to the + midipitch,notelength,... representation. This simplification does + not preserve chords, decorations, grace notes etc. +*/ +{ + float fract; + int i; + int skip_rests, multiplier, inchord, ingrace; + int maxpitch=0; /* [SDG] 2020-06-03 */ + *nnotes = 0; + *nbars = 0; + inchord = 0; + ingrace = 0; + skip_rests = 0; + *timesig_num = time_num; + *timesig_denom = time_denom; + multiplier = (int) 24.0; + barlineptr[*nbars] = 0; + for (i = 0; i < notes; i++) + { + switch (feature[i]) + { + case NOTE: + if (inchord) + maxpitch = MAX (maxpitch, pitch[i]); + else if (ingrace) + break; + else + { + midipitch[*nnotes] = pitch[i]; + fract = (float) num[i] / (float) denom[i]; + notelength[*nnotes] = (int) (fract * multiplier + 0.01); + (*nnotes)++; + } + break; + case TNOTE: + midipitch[*nnotes] = pitch[i]; + fract = (float) num[i] / (float) denom[i]; + notelength[*nnotes] = (int) (fract * multiplier + 0.01); + (*nnotes)++; + skip_rests = 2; + break; + case REST: + if (skip_rests > 0) + { + skip_rests--; + break; + } + else /* for handling tied notes */ + { + midipitch[*nnotes] = RESTNOTE; + fract = (float) num[i] / (float) denom[i]; + notelength[*nnotes] = (int) (fract * multiplier + 0.01); + (*nnotes)++; + break; + } + case CHORDON: + inchord = 1; + maxpitch = 0; + break; + case CHORDOFF: + inchord = 0; + midipitch[*nnotes] = maxpitch; + fract = (float) num[i] / (float) denom[i]; + notelength[*nnotes] = (int) (fract * multiplier + 0.01); + (*nnotes)++; + break; + case GRACEON: + ingrace = 1; + break; + case GRACEOFF: + ingrace = 0; + break; + case DOUBLE_BAR: + case SINGLE_BAR: + case REP_BAR: + case REP_BAR2: + case BAR_REP: +/* bar lines at the beginning of the music can cause the + bar numbering to be incorrect and loss of synchrony with + runabc. If no notes were encountered and nbars = 0, + then we are at the beginning and we wish to bypass + these bar line indications. Note bar numbering starts + from 0. [SS] 2013-11-17 +*/ + if (nbars >0 && *nnotes > 0) { + midipitch[*nnotes] = BAR; + notelength[*nnotes] = BAR; + (*nnotes)++; + if (*nbars < maxbars) (*nbars)++; + else printf("abcmatch too many bars\n"); + } + barlineptr[*nbars] = *nnotes; + break; + case TIME: + *timesig_num = num[i]; + *timesig_denom = denom[i]; + if (*timesig_num == 2 && *timesig_denom ==2) { + *timesig_num = 4; + *timesig_denom = 4; + /* [SS] 2013-11-12 */ + } + break; + default: + break; + } + if (*nnotes > 2000) + { + printf ("ran out of space for midipitch for xref %d\n",xrefno); + exit (0); + } + if (*nbars > 599) + { + printf ("ran out of space for barlineptr for xref %d\n",xrefno); + exit (0); + } + } + midipitch[*nnotes + 1] = BAR; /* in case a final bar line is missing */ +/*printf("refno =%d %d notes %d bar lines %d/%d time-signature %d sharps\n" +,xrefno,(*nnotes),(*nbars),(*timesig_num),(*timesig_denom),sf);*/ +#ifdef DEBUG +printf("nbars = %d\n",*nbars); +for (i=0;i<*nbars;i++) printf("barlineptr[%d] = %d\n",i,barlineptr[i]); +i = 0; +while (i < 50) { + for (j=i;j 4) + return 2; + if (pitch > 1) + return 1; + return 0; +} + +int quantize7(int pitch) +{ +if (pitch < -4) + return -3; +if (pitch < -2) + return -2; +if (pitch < 0) + return -1; +if (pitch > 4) + return 3; +if (pitch >2) + return 2; +if (pitch >0) + return 1; +return 0; +} + + + +void +init_histograms () +{ + int i; + for (i = 0; i < 128; i++) + pitch_histogram[i] = 0; + for (i = 0; i < 128; i++) + weighted_pitch_histogram[i] = 0; + for (i = 0; i < 144; i++) + length_histogram[i] = 0; + for (i = 0; i < 128; i++) + interval_histogram[i] = 0; + lastpitch = 0; +} + + +void +compute_note_histograms () +{ + int i, index, delta; + for (i = 0; i < innotes; i++) + { + index = imidipitch[i]; + if (index < 0) + continue; /* [SS] 2013-02-26 */ + pitch_histogram[index]++; + weighted_pitch_histogram[index] += inotelength[i]; + index = inotelength[i]; + if (index > 143) + index = 143; + length_histogram[index]++; + if (lastpitch != 0) {delta = imidipitch[i] - lastpitch; + delta += 60; + if (delta > -1 && delta < 128) interval_histogram[delta]++; + } + lastpitch = imidipitch[i]; + } +} + + +void +print_length_histogram () +{ + int i; + printf ("\n\nlength histogram\n"); + for (i = 0; i < 144; i++) + if (length_histogram[i] > 0) + printf ("%d %d\n", i, length_histogram[i]); +} + + +void +print_pitch_histogram () +{ + int i; + printf ("pitch_histogram\n"); + for (i = 0; i < 128; i++) + if (pitch_histogram[i] > 0) + printf ("%d %d\n", i, pitch_histogram[i]); +} + +void +print_weighted_pitch_histogram () +{ + int i; + printf ("weighted_pitch_histogram\n"); + for (i = 0; i < 128; i++) + if (weighted_pitch_histogram[i] > 0) + printf ("%d %d\n", i, weighted_pitch_histogram[i]); +} + +void +print_interval_pdf() +{ + int i; + printf ("interval_histogram\n"); + for (i = 0; i < 128; i++) + if (interval_histogram[i] > 0) + printf ("%d %d\n", i-60, interval_histogram[i]); +} + + +void +make_and_print_pitch_pdf () +{ + float pdf[12], sum; + int i, j; + for (i = 0; i < 12; i++) + pdf[i] = 0.0; + sum = 0.0; + for (i = 1; i < 128; i++) + { + j = i % 12; + pdf[j] += (float) weighted_pitch_histogram[i]; + sum += (float) weighted_pitch_histogram[i]; + } + if (sum <= 0.000001) + sum = 1.0; + for (i = 0; i < 12; i++) + { + pdf[i] = pdf[i] / sum; + printf ("%d %5.3f\n", i, pdf[i]); + } +} + +void +make_and_print_interval_pdf () +{ + float pdf[24], sum; + int i, j; + for (i = 0; i < 24; i++) + pdf[i] = 0.0; + sum = 0.0; + for (i = 48; i < 72; i++) + { + j = i-48; + pdf[j] = (float) interval_histogram[i]; + sum += (float) interval_histogram[i]; + } + if (sum <= 0.000001) + sum = 1.0; + for (i = 0; i < 24; i++) + { + pdf[i] = pdf[i] / sum; + printf ("%d %5.3f\n", i-12, pdf[i]); + } +} + +void +difference_midipitch (int *pitch_samples, int nsamples) +{ + int i; + int lastsample, newsample; + lastsample = -1; + for (i = 0; i < nsamples; i++) + { + newsample = pitch_samples[i]; + if (newsample == RESTNOTE) + { + pitch_samples[i] = RESTNOTE; + continue; + } + + else if (lastsample == -1) + { + pitch_samples[i] = ANY; + } + else + { + pitch_samples[i] = newsample - lastsample; + if (qntflag > 0) + pitch_samples[i] = quantize7 (pitch_samples[i]); + } + lastsample = newsample; + } +} + + + +int +make_bar_image (int bar_number, int resolution, + int *barlineptr, int *notelength, int nnotes, int delta_pitch, + int *midipitch, int *pitch_samples) +{ +/* the function returns the midipitch at regular time interval + for bar %d xref %d\n,bar_number,xrefnos + (set by resolution) for a particular bar. Thus if you have + the notes CDEF in a bar (L=1/8), then integrated_length + will contain 12,24,36,48. If resolution is set to 6, then + pitch_samples will return the pitch at time units 0, 6, 12,... + mainly CCDDEEFF or 60,60,62,62,64,64,65,65 in midipitch. + The pitch is shifted by delta_pitch to account for a different + key signature in the matching template. + + input: midipitch[],notelength,resolution,delta_pitch,nnotes + bar_number + output: pitch_samples + + the function returns the number of pitch_samples i creates + +*/ + int integrated_length[50]; /* maximum of 50 notes in a bar */ +/* integrated_length is the number of time units in the bar after note i; +*/ + int offset, lastnote, lastpulse, lastsample; + int i, j, t; + offset = barlineptr[bar_number]; +/* double bar is always placed at the beginning of the tune */ + + i = 1; + integrated_length[0] = notelength[offset]; + lastnote = 0; + while (notelength[i + offset] != BAR) + { + if (notelength[i + offset] > 288) + return -1; /* don't try to handle notes longer than 2 whole */ + integrated_length[i] = + integrated_length[i - 1] + notelength[i + offset]; + lastnote = i; + i++; + if (i + offset > nnotes) + { + /* printf("make_bar_image -- running past last note for bar %d xref %d\n",bar_number,xrefno); */ + break; + } + if (i > 49) + { + printf ("make_bar_image -- bar %d has too many notes for xref %d\n", + bar_number, xrefno); + break; + } + } + lastpulse = integrated_length[lastnote]; + i = 0; + j = 0; + t = 0; + while (t < lastpulse) + { + while (t >= integrated_length[i]) + i++; + while (t < integrated_length[i]) + { + if (midipitch[i + offset] == RESTNOTE) + pitch_samples[j] = RESTNOTE; /* REST don't transpose */ + else + pitch_samples[j] = midipitch[i + offset] + delta_pitch; + j++; + t += resolution; + if (j >= 400) + { + printf + ("make_bar_image -- pitch_sample is out of space for bar %d xrefno = %d\n", + bar_number, xrefno); + break; + } + } + } + lastsample = j; + t = 0; + return lastsample; +} + +/* for debugging */ +void +print_bars (int mbar_number, int ibar_number) +{ + int i; + int ioffset, moffset; + ioffset = ibarlineptr[ibar_number]; + moffset = tpbarlineptr[mbar_number]; + i = 0; + while (tpmidipitch[i + moffset] != BAR) + { + printf ("%d %d\n", tpmidipitch[i + moffset], imidipitch[i + ioffset]); + i++; + } + printf ("\n"); +} + + + +#define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) + +int levenshtein(int *s1, int *s2, int s1len, int s2len) { + int x, y, lastdiag, olddiag; /* [SS] 2015-10-08 removed unsigned */ + int column[33]; + for (y = 1; y <= s1len; y++) + column[y] = y; + for (x = 1; x <= s2len; x++) { + column[0] = x; + for (y = 1, lastdiag = x-1; y <= s1len; y++) { + olddiag = column[y]; + column[y] = MIN3(column[y] + 1, column[y-1] + 1, lastdiag + (s1[y-1] == s2[x-1] ? 0 : 1)); + lastdiag = olddiag; + } + if (column[x] >= levdist) return levdist; + } + if (column[s1len] < levdist && s1len/(2*levdist)>= 1) return 0; + return(column[s1len]); +} + +int perfect_match (int *s1, int *s2, int s1len) { +int i; +for (i=0;i 0) { + deltapitch = quantize7 (deltapitch); + deltapitchtp = quantize7(deltapitchtp); + } + string1[notes] = 256*deltapitch + inotelength[i + ioffset]; + string2[notes] = 256*deltapitchtp + tpnotelength[i + moffset]; + if (notes < 32) notes++; + else printf("notes > 32\n"); + + /* printf("%d %d\n",deltapitch,deltapitchtp);*/ + } + else { /* first note in bar - no lastnote */ + tplastnote = tpmidipitch[i+moffset]; + lastnote = imidipitch[i+ioffset]; + } + } + else { +/* absolute matching (with transposition) */ +/*printf("%d %d\n",imidipitch[i+ioffset],tpmidipitch[i+moffset]-delta_pitch);*/ + string1[notes] = 256*imidipitch[i+ioffset] + inotelength[i + ioffset]; + string2[notes] = 256*(tpmidipitch[i+moffset] - delta_pitch) + tpnotelength[i + moffset]; + if (notes < 32) notes++; + else printf("notes > 32\n"); + } + i++; + } + if (imidipitch[i + ioffset] != BAR) + return -1; /* in case template has fewer notes */ + + if (notes < 2) + return -1; + if (levdist == 0) return perfect_match(string1,string2,notes); + else return levenshtein(string1,string2,notes,notes); +} + + + +/* absolute match - matches notes relative to key signature */ +/* this matching algorithm ignores bar lines and tries to match + a fixed number of notes set by fnotes. It is unnecessary for + the time signatures in the template and tune to match. */ + +int +fixed_match_notes (int fnotes, int mbar_number, int ibar_number, int delta_pitch) +{ + int i,j, notes; + int ioffset, moffset; + int tplastnote,lastnote; /* for contour matching */ + int deltapitch,deltapitchtp; + int string1[32],string2[32]; + ioffset = ibarlineptr[ibar_number]; + moffset = tpbarlineptr[mbar_number]; + /*printf("ioffset = %d moffset = %d\n",ioffset,moffset);*/ + i = j = 0; + notes = 0; + lastnote = 0; + tplastnote =0; + while (notes < fnotes) + { + /*printf("%d %d\n",imidipitch[j+ioffset],tpmidipitch[i+moffset]);*/ + if (imidipitch[j + ioffset] == RESTNOTE + || imidipitch[j + ioffset] == BAR) + { + j++; + continue; + } /* pass over RESTS or BARS */ + if (tpmidipitch[i + moffset] == RESTNOTE + || tpmidipitch[i + moffset] == BAR) + { + i++; + continue; + } /* pass over RESTS or BARS */ + + if (imidipitch[j + ioffset] == -1 || tpmidipitch[i + moffset] == -1) + { + printf("unexpected negative pitch at %d or %d for xref %d\n",i+ioffset,i+moffset,xrefno); + i++; + j++; + continue; + } /* unknown contour note */ + + if (norhythm == 1) { + inotelength[j + ioffset] = 0; + tpnotelength[i + moffset] = 0; + } + + if (con == 1) { +/* contour matching */ + if (tplastnote !=0) { + deltapitchtp = tpmidipitch[i+moffset] - tplastnote; + deltapitch = imidipitch[j+ioffset] - lastnote; + tplastnote = tpmidipitch[i+moffset]; + lastnote = imidipitch[j+ioffset]; + if (qntflag > 0) { + deltapitch = quantize7 (deltapitch); + deltapitchtp = quantize7(deltapitchtp); + } + string1[notes] = 256*deltapitch + inotelength[j + ioffset]; + string2[notes] = 256*deltapitchtp + tpnotelength[i + moffset]; + if (notes < 32) notes++; + else printf("notes > 32\n"); + + /* printf("deltapitch %d %d\n",deltapitch,deltapitchtp); + printf("length %d %d\n",inotelength[j + ioffset],tpnotelength[i+moffset]); + */ + if (deltapitch != deltapitchtp) + return -1; +/* match succeeded */ + /* printf("%d %d\n",deltapitch,deltapitchtp);*/ + } else { /* first note in bar - no lastnote */ + tplastnote = tpmidipitch[i+moffset]; + lastnote = imidipitch[j+ioffset]; + } + } + else { +/* absolute matching (with transposition) */ + /*printf("%d %d\n",imidipitch[j+ioffset],tpmidipitch[i+moffset]-delta_pitch); + printf("%d %d\n",inotelength[j+ioffset],tpnotelength[i+moffset]); + */ + + string1[notes] = 256*imidipitch[j+ioffset] + inotelength[j + ioffset]; + string2[notes] = 256*(tpmidipitch[i+moffset] - delta_pitch) + tpnotelength[i + moffset]; + if (notes < 32) notes++; + else printf("notes > 32\n"); + } + + i++; + j++; + } + if (notes < 2) + return -1; + /*printf("ioffset = %d moffset = %d\n",ioffset,moffset);*/ + if (levdist == 0) return perfect_match(string1,string2,notes); + else return levenshtein(string1,string2,notes,notes); +} + + + +/* for debugging */ +void +print_bar_samples (int mmsamples, int *mmpitch_samples) +{ + int i; + for (i = 0; i < mmsamples; i++) + printf ("%d %d\n", mmpitch_samples[i], ipitch_samples[i]); +} + + +int +match_samples (int mmsamples, int *mmpitch_samples) +{ + int i; + int changes; + int last_sample; + int string1[32],string2[32]; + int j; + if (mmsamples != isamples) + return -1; + changes = 0; + last_sample = ipitch_samples[0]; /* [SS] 2012-02-05 */ + j = 0; + for (i = 0; i < mmsamples; i++) + { + if (ipitch_samples[i] == -1 || mmpitch_samples[i] == -1) + continue; /* unknown contour note (ie. 1st note) */ + string1[j] = ipitch_samples[i]; + string2[j] = mmpitch_samples[i]; + j++; + if (last_sample != ipitch_samples[i]) + { + last_sample = ipitch_samples[i]; + changes++; + } + } + if (ignore_simple && changes < 3) + return -1; + if (levdist == 0) return perfect_match(string1,string2,j); + else return levenshtein(string1,string2,j,j); +} + + + +int +match_any_bars (int tpbars, int barnum, int delta_key, int nmatches) +{ +/* This function reports any bars in match template match a particular + * bar (barnum) in the tune. If a match is found then barnum is + * reported. It runs in one of two modes depending on the value + * of the variable called resolution. + + * The template is not passed as an argument but is accessed from + * the global arrays, tpmidipitch[1000] and tpnotelength[1000]. + */ + + int kmatches; + int moffset, j, dif; +/* for every bar in match sample */ + kmatches = nmatches; + moffset = 0; + if (resolution > 0) + { + isamples = make_bar_image (barnum, resolution, + ibarlineptr, inotelength, innotes, delta_key, + imidipitch,ipitch_samples); + if (isamples < 1) + return kmatches; + if (con == 1) + difference_midipitch (ipitch_samples, isamples); + for (j = 0; j < tpbars; j++) + { + + dif = match_samples (msamples[j], mpitch_samples + moffset); +#if 0 /* debugging */ + printf("bar %d\n",j); + print_bar_samples(msamples[j],mpitch_samples+moffset); + /*printf("dif = %d\n\n",dif);*/ +#endif + + + moffset += msamples[j]; + if (dif == 0) + { + if (tpxref > 0) tpbarstatus[j] = 1; + kmatches++; + if (kmatches == 1) + printf ("%d %d %d ", fileindex, xrefno, barnum); +/* subtract one from bar because first bar always seems to be 2 */ + else + printf (" %d ", barnum ); + break; + } + } + } + else /* exact match */ + { + for (j = 0; j < tpbars; j++) + { + if (fixednumberofnotes) + dif = fixed_match_notes (fixednumberofnotes,j, barnum, delta_key); + else + dif = match_notes (j, barnum, delta_key); + + + if (dif == 0) + { + if (tpxref > 0) tpbarstatus[j] = 1; + kmatches++; + if (kmatches == 1) + printf ("%d %d %d ", fileindex, xrefno, barnum); + else + printf (" %d ", barnum ); + break; + } /* dif condition */ + } /*for loop */ + } /* resolution condition */ + return kmatches; +} + + +int +match_all_bars (int tpbars, int barnum, int delta_key, int nmatches) +{ +/* This function tries to match all the bars in the match template + with the bars in the bars in the tune. All the template bars + must match in the same sequence in order to be reported. + It runs in one of two modes depending on the value of resolution. +*/ + int kmatches; + int moffset, j, dif; + int matched_bars[20]; +/* for every bar in match sample */ + kmatches = 0; + moffset = 0; + if (resolution > 0) + for (j = 0; j < tpbars; j++) + { + isamples = make_bar_image (barnum + j, resolution, + ibarlineptr, inotelength, innotes, + delta_key, imidipitch ,ipitch_samples); + if (con == 1) + difference_midipitch (ipitch_samples, isamples); + dif = match_samples (msamples[j], mpitch_samples + moffset); + moffset += msamples[j]; + if (dif != 0) + return nmatches; + matched_bars[kmatches] = barnum + j ; + kmatches++; + if (j > 15) + break; + } + else + for (j = 0; j < tpbars; j++) + { + if (fixednumberofnotes) + dif = fixed_match_notes (fixednumberofnotes,j, barnum + j, delta_key); + else + dif = match_notes (j, barnum + j, delta_key); + if (dif != 0) + return nmatches; + matched_bars[kmatches] = barnum + j ; + /*printf("matched %d\n",barnum+j-1);*/ + kmatches++; + if (j > 15) + break; + } + + if (nmatches == 0) + printf ("%d %d ", fileindex, xrefno); + for (j = 0; j < kmatches; j++) + printf ("%d ", matched_bars[j]); + return kmatches + nmatches; +} + + + +void find_and_report_matching_bars +/* top level matching function. Distinguishes between, + any, all and contour modes and calls the right functions +*/ + (int tpbars, int inbars, int transpose, int anymode, int con) +{ + int i, nmatches; + if (con == 1) + { + transpose = 0; /* not applicable here */ + } + nmatches = 0; + if (anymode == 1) /* match any bars in template */ + + for (i = 0; i < inbars; i++) + { + nmatches = match_any_bars (tpbars, i, transpose, nmatches); + } + + else + /* match all bars in template in sequence */ + for (i = 0; i < inbars - tpbars; i++) + { + nmatches = match_all_bars (tpbars, i, transpose, nmatches); + } + + if (nmatches > 0) + printf ("\n"); +} + + +int +find_first_matching_tune_bar (int mbarnumber, int inbars, int transpose) +/* given a bar number in the template, the function looks for + * the first bar in the tune which matches the template. + * Unfortunately since we are only looking for single bars, + * it may not be useful to play around with the resolution + * parameter. + */ +{ + int i, dif; + for (i = 1; i < inbars; i++) + { + dif = match_notes (mbarnumber, i, transpose); + if (dif == 0) + return i; + } + return -1; +} + + + + +int +find_first_matching_template_bar (int barnumber, int tpbars, int transpose) +/* given a bar number in the tune, the function looks for + * the first bar in the template which matches the tune bar. + */ +{ + int i, dif; + for (i = 1; i < tpbars; i++) + { + if (fixednumberofnotes) + dif = fixed_match_notes (fixednumberofnotes,i, barnumber, transpose); + else + dif = match_notes (i, barnumber, transpose); + if (dif == 0) + return i; + } + return -1; +} + +/* this function is not used */ +int +count_matched_template_bars (int tpbars, int inbars, int transpose) +{ + int i, count, bar; + count = 0; + for (i = 0; i < tpbars; i++) + { + bar = find_first_matching_tune_bar (i, inbars, transpose); + /*if (bar >= 0) printf ("bar %d matches %d\n",bar,i); */ + if (bar >= 0) + count++; + } + return count; +} + + +int +count_matched_tune_bars (int tpbars, int inbars, int transpose) +/* used only by brief mode */ +{ + int i, count, bar; + count = 0; + for (i=0;i<300;i++) tpbarstatus[i] = 0; + for (i = 0; i < inbars; i++) + { + bar = find_first_matching_template_bar (i, inbars, transpose); + /*if (bar >= 0) {printf ("bar %d matches %d\n",bar,i); + print_bars(bar,i); + } + */ + if (bar >= 0) { + count++; + tpbarstatus[bar] = 1; + } + } + return count; +} + +int count_matching_template_bars () +{ +int i; +int count; +count = 0; +for (i=0;i<300;i++) + if (tpbarstatus[i] > 0) count++; +return count; +} + +void startfile(); /* links with matchsup.c */ + +int +analyze_abc_file (char *filename) +{ + FILE *fp; + fp = fopen (filename, "rt"); + if (fp == NULL) + { + printf ("cannot open file %s\n", filename); + exit (0); + } + init_histograms (); + while (!feof (fp)) + { + fileindex++; + startfile (); + parsetune (fp); +/* printf("fileindex = %d xrefno =%d\n",fileindex,xrefno); */ +/* printf("%s\n",titlename); */ + if (notes < 10) + continue; + /*print_feature_list(); */ + make_note_representation (&innotes, &inbars, imaxnotes, imaxbars, + &itimesig_num, &itimesig_denom, ibarlineptr, + inotelength, imidipitch); + compute_note_histograms (); + if (action == cpitch_histogram_table) + { + printf ("%4d %s %s\n%s\n", xrefno, filename, keysignature, + titlename); + make_and_print_pitch_pdf (); + init_histograms (); + } + if (action == interval_pdf_table) + { + printf ("%4d %s %s\n%s\n", xrefno, filename, keysignature, + titlename); + make_and_print_interval_pdf (); + init_histograms (); + } + + } + fclose (fp); + switch (action) + { + case cpitch_histogram: + print_pitch_histogram (); + break; + case cwpitch_histogram: + print_weighted_pitch_histogram (); + break; + case clength_histogram: + print_length_histogram (); + break; + case interval_pdf: + print_interval_pdf (); + break; + default: + ; + } + return (0); +} + + +void +event_init (argc, argv, filename) +/* this routine is called first by abcparse.c */ + int argc; + char *argv[]; + char **filename; +{ + int i,j; + + xmatch = 0; + /* look for code checking option */ + if (getarg ("-c", argc, argv) != -1) + { + check = 1; + nowarn = 0; + noerror = 0; + } + else + { + check = 0; + }; + if (getarg ("-ver", argc, argv) != -1) + { + printf ("%s\n", VERSION); + exit (0); + } + /* look for verbose option */ + if (getarg ("-v", argc, argv) != -1) + { + verbose = 1; + } + else + { + verbose = 0; + }; + j = getarg ("-r", argc, argv); + if (j != -1 && argc >= j+1) /* [SS] 2015-02-22 */ + sscanf (argv[j], "%d", &resolution); + if (getarg ("-a", argc, argv) != -1) + anymode = 1; + if (getarg ("-ign", argc, argv) != -1) + ignore_simple = 1; + if (getarg ("-con", argc, argv) != -1) + con = 1; + if (getarg ("-qnt", argc, argv) != -1) + { + qntflag = 1; + con = 1; + } + if (getarg ("-norhythm",argc,argv) != -1) + {norhythm = 1; + resolution = 0; + } + + j = getarg("-lev",argc,argv); + if (j != -1) { + if (argv[j] == NULL) { + printf("'error: expecting a number specifying the maximum levenshtein distance allowed\n"); + exit(0); + } + levdist = readnumf(argv[j]); + } + + j = getarg("-tp",argc,argv); + if (j != -1) { + if (argv[j] == NULL) { + printf ("error: expecting file name and optional reference number\n"); + exit(0); + } + free(templatefile); + templatefile = addstring(argv[j]); + if (*templatefile == '-') { + printf ("error: -tp filename must not begin with a -\n"); + exit(0); + } + if (argv[j+1] != NULL && isdigit(*argv[j+1])) { + tpxref = readnumf(argv[j+1]); + } + anymode = 1; /* only mode which makes sense for a entire tune template*/ + for (i=0;i<300;i++) tpbarstatus[i] = 0; + } + + + j = getarg ("-br", argc, argv); + if (j != -1) + { + if (argv[j] == NULL) + { + printf ("error: expecting number after parameter -br\n"); + exit (0); + } + + sscanf (argv[j], "%d", &cthresh); + brief = 1; + } + + j = getarg ("-fixed", argc, argv); + if (j != -1) + { + if (argv[j] == NULL) + { + printf ("error: expecting number after parameter -fixed\n"); + exit (0); + } + + sscanf (argv[j], "%d", &fixednumberofnotes); + } + + wphist = getarg ("-wpitch_hist", argc, argv); + phist = getarg ("-pitch_hist", argc, argv); + lhist = getarg ("-length_hist", argc, argv); + pdftab = getarg ("-pitch_table", argc, argv); + wpintv = getarg ("-interval_hist",argc,argv); + wpipdf = getarg ("-interval_table",argc,argv); + + if (phist >= 0) + { + action = cpitch_histogram; + } + if (lhist >= 0) + { + action = clength_histogram; + } + if (wphist >= 0) + { + action = cwpitch_histogram; + } + if (pdftab >= 0) + { + action = cpitch_histogram_table; + } + if (wpintv >=0) + { + action = interval_pdf; + } + if (wpipdf >=0) + { + action = interval_pdf_table; + } + + if (brief == 1) + resolution = 0; /* do not compute msamples in main() */ + maxnotes = 3000; + /* allocate space for notes */ + if (fixednumberofnotes > 0) resolution = 0; + pitch = checkmalloc (maxnotes * sizeof (int)); + num = checkmalloc (maxnotes * sizeof (int)); + denom = checkmalloc (maxnotes * sizeof (int)); + pitchline = checkmalloc (maxnotes * sizeof (int)); + feature = (featuretype *) checkmalloc (maxnotes * sizeof (featuretype)); + /* and for text */ + atext = (char **) checkmalloc (maxtexts * sizeof (char *)); + words = (char **) checkmalloc (maxwords * sizeof (char *)); + if ((getarg ("-h", argc, argv) != -1) || (argc < 2)) + { + printf ("abcmatch version %s\n", VERSION); + printf ("Usage : abcmatch [-options] \n"); + printf (" [reference number] selects a tune\n"); + printf (" -c returns error and warning messages\n"); + printf (" -v selects verbose option\n"); + printf (" -r resolution for matching\n"); + printf (" -fixed fixed number of notes\n"); + printf (" -con pitch contour match\n"); + printf (" -qnt contour quantization\n"); + printf (" -lev use levenshtein distance\n"); + printf (" -ign ignore simple bars\n"); + printf (" -a report any matching bars (default all bars)\n"); + printf (" -br %%d only report number of matched bars when\n\ + above given threshold\n"); + printf (" -tp [reference number]\n"); + printf (" -ver returns version number\n"); + printf (" -pitch_hist pitch histogram\n"); + printf (" -wpitch_hist interval weighted pitch histogram\n"); + printf (" -length_hist note duration histogram\n"); + printf (" -interval_hist pitch interval histogram\n"); + printf (" -pitch_table separate pitch pdfs for each tune\n"); + printf (" -interval_table separate interval pdfs for each tune\n"); + exit (0); + } + else + { + *filename = argv[1]; + }; + /* look for user-supplied output filename */ + dotune = 0; + parseroff (); +} + + + +int +main (argc, argv) + int argc; + char *argv[]; +{ + char *filename; + int i; + int ikey, mkey; + int moffset; + int transpose; + int mseqno; + /* sequence number of template (match.abc) + * mseqno can differ from xrefnum when running count_matched_tune_bars + * because there is no guarantee the xref numbers are in + * sequence in the input file. Hopefully fileindex matches sequence + * number in script calling this executable. + */ + + int kfile, count; + int kount; + +/* initialization */ + action = none; + templatefile = addstring("match.abc"); + event_init (argc, argv, &filename); + init_abbreviations (); + + +/* get the search template from the file match.abc written + in abc format. This file is automatically generated by + runabc.tcl when you are using this search function. +*/ + + if (action != none) + analyze_abc_file (filename); + + else + { /* if not computing histograms */ + if (tpxref >0 ) xmatch = tpxref;/* get only tune with ref number xmatch*/ + parsefile (templatefile); + if (tpxref != 0 && tpxref != xrefno) { + printf("could not find X:%d in file %s\n",tpxref,filename); + exit(0); + } + mkey = sf2midishift[sf + 7]; + mseqno = xrefno; /* if -br mode, X:refno is file sequence number */ + /* xrefno was set by runabc.tcl to be file sequence number of tune */ + /*print_feature_list(); */ + make_note_representation (&tpnotes, &tpbars, tpmaxnotes, tpmaxbars, + &tptimesig_num, &tptimesig_denom, tpbarlineptr, + tpnotelength, tpmidipitch); + + /* trim off any initial bar lines + for (i = 0; i < tpbars; i++) + { + j = i; + if (tpmidipitch[tpbarlineptr[i]] != BAR) + break; + } + for (i = j; i < tpbars; i++) + tpbarlineptr[i - j] = tpbarlineptr[i]; + tpbars -= j; + */ + + moffset = 0; +/* if not exact match, i.e. resolution > 0 compute to an + sample representation of the template. +*/ + if (resolution > 0) + for (i = 0; i < tpbars; i++) + { + msamples[i] = + make_bar_image (i, resolution, + tpbarlineptr, tpnotelength, tpnotes, 0, + tpmidipitch, mpitch_samples + moffset); + if (con == 1) + difference_midipitch (mpitch_samples + moffset, msamples[i]); + moffset += msamples[i]; + if (moffset > 3900) + printf ("abcmatch: out of room in mpitch_samples\n"); + } + +/* now process the input file */ + + + xmatch = 0; /* we do not want to filter any reference numbers here */ + fp = fopen (filename, "rt"); + if (fp == NULL) + { + printf ("cannot open file %s\n", filename); + exit (0); + } + + kfile = 0; + while (!feof (fp)) + { + fileindex++; + startfile (); + parsetune (fp); + /*printf("fileindex = %d xrefno =%d\n",fileindex,xrefno); + printf("%s\n",titlename); */ + if (tpxref == xrefno) { + tp_fileindex = fileindex; + continue; + } + if (notes < 10) + continue; + ikey = sf2midishift[sf + 7]; + /*print_feature_list(); */ + if (voicesused) {/*printf("xref %d has voices\n",xrefno);*/ + continue; + } + make_note_representation (&innotes, &inbars, imaxnotes, imaxbars, + &itimesig_num, &itimesig_denom, + ibarlineptr, inotelength, imidipitch); + { + +/* ignore tunes which do not share the same time signature as the template */ + if ((itimesig_num != tptimesig_num + || itimesig_denom != tptimesig_denom) + && fixednumberofnotes == 0) + continue; + + + transpose = mkey - ikey; +/* we do not know whether to transpose up or down so we will + go in the direction with the smallest number of steps + [SS] 2013-11-12 +*/ + if (transpose > 6) transpose = transpose -12; + if (transpose < -6) transpose = transpose + 12; + + +/* brief mode is used by the grouper in runabc.tcl */ + if (brief) + { + if (mseqno == fileindex) + continue; /* don't check tune against itself */ + count = count_matched_tune_bars (tpbars, inbars, transpose); + kount = count_matching_template_bars(); + /*if (count >= cthresh) [SS] 2013-11-26 */ + if (kount >= cthresh) + { + if (kfile == 0) + printf ("%d\n", tpbars); + printf (" %d %d %d\n", fileindex, count,kount); + kfile++; + } + } + + else +/* top level matching function if not brief mode */ + find_and_report_matching_bars (tpbars, inbars, transpose, + anymode, con); + } + } + fclose (fp); + if (tpxref > 0) { + printf ("%d %d ", tp_fileindex, tpxref); + for (i = 0; i /dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: Seymour Shlien (fy733@ncf.ca) about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='abcmidi' +PACKAGE_TARNAME='abcmidi' +PACKAGE_VERSION='2011-08-03' +PACKAGE_STRING='abcmidi 2011-08-03' +PACKAGE_BUGREPORT='fy733@ncf.ca' +PACKAGE_URL='' + +ac_unique_file="abc.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +EGREP +GREP +CPP +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_debug +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures abcmidi 2011-08-03 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/abcmidi] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of abcmidi 2011-08-03:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug Enable debugging information + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to Seymour Shlien fy733@ncf.ca . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +abcmidi configure 2011-08-03 +generated by GNU Autoconf 2.67 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval "test \"\${$3+set}\"" = set; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------ ## +## Report this to Seymour Shlien fy733@ncf.ca ## +## ------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by abcmidi $as_me 2011-08-03, which was +generated by GNU Autoconf 2.67. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5 ; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_config_headers="$ac_config_headers config.h" + + +# Checks for programs. +cflags_save="$CFLAGS" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5 ; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5 ; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5 ; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5 ; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5 ; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CFLAGS="$cflags_save" + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; USE_DEBUG="$enableval" +else + USE_DEBUG="no" +fi + +if test $USE_DEBUG = yes ; then + CFLAGS="$CFLAGS -g" +else + CFLAGS="$CFLAGS -O2" +fi + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lm': + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 +$as_echo_n "checking for main in -lm... " >&6; } +if test "${ac_cv_lib_m_main+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_main=yes +else + ac_cv_lib_m_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 +$as_echo "$ac_cv_lib_m_main" >&6; } +if test "x$ac_cv_lib_m_main" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + + +# Checks for header files. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5 ; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in stdlib.h string.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = x""yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + +# Checks for library functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for error_at_line" >&5 +$as_echo_n "checking for error_at_line... " >&6; } +if test "${ac_cv_lib_error_at_line+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +error_at_line (0, 0, "", 0, "an error occurred"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_error_at_line=yes +else + ac_cv_lib_error_at_line=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_error_at_line" >&5 +$as_echo "$ac_cv_lib_error_at_line" >&6; } +if test $ac_cv_lib_error_at_line = no; then + case " $LIBOBJS " in + *" error.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS error.$ac_objext" + ;; +esac + +fi + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_func in strcasecmp strchr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by abcmidi $as_me 2011-08-03, which was +generated by GNU Autoconf 2.67. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to Seymour Shlien ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +abcmidi config.status 2011-08-03 +configured by $0, generated by GNU Autoconf 2.67, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..fde9e34 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.67]) +AC_INIT([abcmidi], [2011-08-03], [seymour.shlien@crc.ca]) +AC_CONFIG_SRCDIR([abc.h]) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +cflags_save="$CFLAGS" +AC_PROG_CC +CFLAGS="$cflags_save" + +dnl This mechanism allows one to enable debug compilations... +AC_ARG_ENABLE(debug, + [ --enable-debug Enable debugging information], + USE_DEBUG="$enableval", USE_DEBUG="no") +if test $USE_DEBUG = yes ; then + CFLAGS="$CFLAGS -g" +else + CFLAGS="$CFLAGS -O2" +fi + +AC_PROG_INSTALL + +# Checks for libraries. +# FIXME: Replace `main' with a function in `-lm': +AC_CHECK_LIB([m], [main]) + +# Checks for header files. +AC_CHECK_HEADERS([stdlib.h string.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_ERROR_AT_LINE +AC_FUNC_MALLOC +AC_CHECK_FUNCS([strcasecmp strchr]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/crack.c b/crack.c new file mode 100644 index 0000000..01e20f3 --- /dev/null +++ b/crack.c @@ -0,0 +1,114 @@ +/* + * crack - put the command line to the vice. + * + * This routine takes four arguments, the variables argc and argv from + * the program's main procedure, a list of flags to recognize, and an + * indication whether to ignore unknown flags or not. + * + * The action of crack is to read a command line laid out in the format: + * + * % command [flags]... [files]... + * + * where the flags are of the form -foption, that is, a minus, a character + * and an optional argument, butted up to the character. No space may + * appear between any flag and its option. The first command line + * argument not preceded by '-' is taken as the end of the flags and the + * beginning of file names. + * + * The flags argument to crack looks like this: "a|b|cd" for flags a b c + * and d. In this example, a and b take (optional!) options, as specified + * by the trailing colon, c and d do not. When crack scans a flag, it + * returns the flag character after setting the external character pointer + * arg_option to the option part. It also sets arg_index to the index of + * the argv variable scanned. Crack returns NULL when it has scanned the + * last flag. The value of arg_index then points at the first + * argument after the last flag, which should be the first filename, if + * any. If there are no arguments, or no more arguments after reading + * the flags, arg_index == argc; + * + * Flags may be concatenated, for instance, using the flags argument + * given above: -cd will treat c and d as + * flags. -cdaoption also works. However, tacking what you think is + * a flag after another flag that takes an option will cause the flag to + * be lost. I.e., -ac will treat c as an option, not a flag. + * + * When the ignore flag is zero, flags scanned that are not in the flags + * variable generate an error message and crack returns EOF. If ignore is + * nonzero, unknown flags are suppressed, that is, no flag is returned. + * The purpose of ignoring flags is so that more than one part of a + * program can scan the command line without having to know about the + * flags of all the other parts. For instance, where a program calculates + * a sampling rate by one flag and a value in seconds in another, it must + * search for the sampling rate first, then the time value. Two calls to + * crack() would be required, one to scan just for the flag setting sampling + * rate, another to ignore the rate flag, but to set the time value based + * on the sampling rate. + * NOTE: WHEN MAKING MORE THAN ONE CALL TO crack() IN A PROGRAM, IT + * IS NECESSARY TO RESET arg_index TO 0 FIRST. + * + * When ignoring unknown flags, if an unknown flag has an option + * associated with it, the option is also ignored. Care should be excercised + * here because it may be possible that the associated "option" is really + * more concatenated flags. These, if any, are lost. The rule is that, + * when ignoring unknown flags, the first instance of an unknown flag + * causes that flag and the rest of that argument to be discarded. For + * instance, if flags is set to "a:b:cd", and a command line: + * "-zcdaoption" is supplied, c d and a would be ignored because they come + * after z in the same argument. The point is there is no way to disambiguate + * flags from unknown options when ignoring flags, so concatenating options, + * while nice, is problematical. + * + * FIX applied : index changed to index 6/9/96 + * FIX applied : crack returns char* instead of char 22/6/98 + */ + +#include +#include + +/* define USE_INDEX if your C libraries have index() instead of strchr() */ +#ifdef USE_INDEX +#define strchr index +#endif + +int arg_index = 0; +char *arg_option; +char *pvcon = NULL; + +char* crack(argc, argv, flags, ign) + int argc; char **argv; char *flags; int ign; +{ + char *pv, *flgp, *strchr(); + while ((arg_index) < argc) + { + if (pvcon != NULL) + pv = pvcon; + else + { + if (++arg_index >= argc) return(NULL); + pv = argv[arg_index]; + if (*pv != '-') + return(NULL); + } + pv++; /* skip '-' or prev. flag */ + if (pv != NULL) + { + if ((flgp=strchr(flags,*pv)) != NULL) + { + pvcon = pv; + if (*(flgp+1) == '|') { arg_option = pv+1; pvcon = NULL; } + return(pv); + } + else + if (!ign) + { + fprintf(stderr, "%s: no such flag: %s\n", argv[0], pv); + exit(0); + } + else + pvcon = NULL; + } + pvcon = NULL; + } + return(NULL); + } + diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..05376cc --- /dev/null +++ b/debug.c @@ -0,0 +1,252 @@ +/* debug.c */ +/* part of yaps - abc to PostScript converter */ +/* print tune data structure to screen for debugging purposes only */ + +#include +#include "abc.h" +#include "structs.h" + +void showfeature(struct feature *ft) +{ + char* astring; + struct fract* afract; + struct key* akey; + struct rest* arest; + struct tuple* atuple; + struct note* anote; + struct aclef* theclef; + switch (ft->type) { + case SINGLE_BAR: printf("SINGLE_BAR\n"); + break; + case DOUBLE_BAR: printf("DOUBLE_BAR\n"); + break; + case BAR_REP: printf("BAR_REP\n"); + break; + case REP_BAR: printf("REP_BAR\n"); + break; + case REP1: printf("REP1\n"); + break; + case REP2: printf("REP2\n"); + break; + case PLAY_ON_REP: + printf("PLAY_ON_REP %s\n", (char*)ft->item); + break; + case BAR1: printf("BAR1\n"); + break; + case REP_BAR2: printf("REP_BAR2\n"); + break; + case DOUBLE_REP: printf("DOUBLE_REP\n"); + break; + case THICK_THIN: printf("THICK_THIN\n"); + break; + case THIN_THICK: printf("THIN_THICK\n"); + break; + case PART: printf("PART\n"); + astring = ft->item; + break; + case TEMPO: printf("TEMPO\n"); + break; + case TIME: + afract = ft->item; + printf("TIME %d / %d\n", afract->num, afract->denom); + break; + case KEY: printf("KEY\n"); + akey = ft->item; + break; + case REST: printf("REST\n"); + arest = ft->item; + break; + case TUPLE: printf("TUPLE\n"); + atuple = ft->item; + break; + case NOTE: + anote = ft->item; + printf("NOTE %c%c %d / %d\n", anote->accidental, anote->pitch, + anote->len.num, anote->len.denom); + if (anote->gchords != NULL) { + astring = firstitem(anote->gchords); + while (astring != NULL) { + printf("gchord: %s\n", astring); + astring = nextitem(anote->gchords); + }; + }; + if (anote->syllables != NULL) { + astring = firstitem(anote->syllables); + while (astring != NULL) { + printf("syllable: %s\n", astring); + astring = nextitem(anote->syllables); + }; + }; + printf("stemup=%d beaming=%d base =%d base_exp=%d x=%.1f left=%.1f right=%.1f\n", + anote->stemup, anote->beaming, anote->base, anote->base_exp, + ft->x, ft->xleft, ft->xright); + break; + case CHORDNOTE: + anote = ft->item; + printf("CHORDNOTE %c%c %d / %d\n", anote->accidental, anote->pitch, + anote->len.num, anote->len.denom); + printf("stemup=%d beaming=%d base =%d base_exp=%d x=%.1f left=%.1f right=%.1f\n", + anote->stemup, anote->beaming, anote->base, anote->base_exp, + ft->x, ft->xleft, ft->xright); + printf("x=%.1f\n", ft->x); + break; + case NONOTE: printf("NONOTE\n"); + break; + case OLDTIE: printf("OLDTIE\n"); + break; + case TEXT: printf("TEXT\n"); + break; + case SLUR_ON: printf("SLUR_ON\n"); + break; + case SLUR_OFF: printf("SLUR_OFF\n"); + break; + case TIE: printf("TIE\n"); + break; + case CLOSE_TIE: printf("CLOSE_TIE\n"); + break; + case TITLE: printf("TITLE\n"); + break; + case CHANNEL: printf("CHANNEL\n"); + break; + case TRANSPOSE: printf("TRANSPOSE\n"); + break; + case RTRANSPOSE: printf("RTRANSPOSE\n"); + break; + case GRACEON: printf("GRACEON\n"); + break; + case GRACEOFF: printf("GRACEOFF\n"); + break; + case SETGRACE: printf("SETGRACE\n"); + break; + case SETC: printf("SETC\n"); + break; + case GCHORD: printf("GCHORD\n"); + break; + case GCHORDON: printf("GCHORDON\n"); + break; + case GCHORDOFF: printf("GCHORDOFF\n"); + break; + case VOICE: printf("VOICE\n"); + break; + case CHORDON: printf("CHORDON\n"); + break; + case CHORDOFF: printf("CHORDOFF\n"); + break; + case SLUR_TIE: printf("SLUR_TIE\n"); + break; + case TNOTE: printf("TNOTE\n"); + break; + case LT: printf("LT\n"); + break; + case GT: printf("GT\n"); + break; + case DYNAMIC: printf("DYNAMIC\n"); + break; + case LINENUM: + printf("LINENUM %p\n", (void *)(ft->item)); /* [SDG] 2020-06-03 */ + break; + case MUSICLINE: printf("MUSICLINE\n"); + break; + case PRINTLINE: printf("PRINTLINE\n"); + break; + case MUSICSTOP: printf("MUSICSTOP\n"); + break; + case WORDLINE: printf("WORDLINE\n"); + break; + case WORDSTOP: printf("WORDSTOP\n"); + break; + case INSTRUCTION: printf("INSTRUCTION\n"); + break; + case NOBEAM: printf("NOBEAM\n"); + break; + case CLEF: printf("CLEF\n"); + theclef = ft->item; + break; + case SPLITVOICE: printf("SPLITVOICE\n"); + default: + printf("unknown type: %d\n", (int)ft->type); + break; + }; +} + + +static int showline(v) +struct voice* v; +/* draws one line of music from specified voice */ +{ + struct feature* ft; +/* struct note* anote; + struct key* akey; + char* astring; + struct fract* afract; + struct rest* arest; + struct tuple* atuple; + struct aclef* theclef; +*/ + int sharps; + struct chord* thischord; + int chordcount; + int printedline; + + if (v->place == NULL) { + return(0); + }; + chordcount = 0; + v->beamed_tuple_pending = 0; + thischord = NULL; + if (v->keysig == NULL) { + event_error("Voice has no key signature"); + } else { + sharps = v->keysig->sharps; + }; + ft = v->place; + printedline = 0; + while ((ft != NULL) && (!printedline)) { + /* printf("type = %d\n", ft->type); */ + showfeature(ft); + ft = ft->next; + }; + v->place = ft; + return(1); +} + +void showtune(struct tune* t) +/* print abc structure to the screen */ +{ + char* atitle; + int notesdone; + struct voice* thisvoice; + + notesdone = 0; + atitle = firstitem(&t->title); + while (atitle != NULL) { + printf("TITLE: %s\n", atitle); + atitle = nextitem(&t->title); + }; + if (t->composer != NULL) { + printf("COMPOSER: %s\n", t->composer); /* [SDG] 2020-06-03 */ + }; + if (t->origin != NULL) { + printf("ORIGIN: %s\n", t->origin); + }; + if (t->parts != NULL) { + printf("PARTS: %s\n", t->parts); + }; + thisvoice = firstitem(&t->voices); + while (thisvoice != NULL) { + thisvoice->place = thisvoice->first; + thisvoice = nextitem(&t->voices); + }; +/* + doneline = 1; + while(doneline) { +*/ + thisvoice = firstitem(&t->voices); + while (thisvoice != NULL) { + printf("-----------(voice %d)-------\n", thisvoice->voiceno); + showline(thisvoice); + thisvoice = nextitem(&t->voices); + }; +/* }; */ +} + diff --git a/doc/AUTHORS b/doc/AUTHORS new file mode 100644 index 0000000..b1460bd --- /dev/null +++ b/doc/AUTHORS @@ -0,0 +1,26 @@ + +This file contains additional documentation for the abcMIDI package : + +Unix Man Pages +-------------- +* abc2midi.1 man pages for abc2midi written by Christoph Dalitz. +* midi2abc.1 man page for midi2abc written by Christoph Dalitz. +* abc2abc.1 man page for abc2abc written by Anselm Lingnau. +* mftext.1 man page for mftext written by Anselm Lingnau. + +These man pages are now supported by Seymour Shlien + +If you wish to preview these man pages use groff with the -man +option. The output is normally in postscript format, but you +can override this using the -a option. For example, +groff -man -a abc2midi.1 + + +To install the man pages, copy them to appropriate directory (typically +this will be /usr/man/man1). You may also need to run mandb after +copying them across. + +Code Documentation +------------------ +* abc2midi.txt : notes on the abc2midi code written by Seymour Shlien. +* midi2abc.txt : notes on the midi2abc code written by Seymour Shlien. diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 0000000..eb2df38 --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,13748 @@ +2003 March 27: +Updated the man pages to abc2abc, abc2midi and midi2abc and created a +new man page for yaps. Minor changes to midifile.c and midifile.h +were made to minimize the number of warning error messages. Midi2abc +was upgraded to be in line with the version I use with the script +midi2abc.tcl. The syntax in mftext.c was improved to reduce the +number of compilation warnings. + + +2003 April 12 +abc2midi: for abc tunes with no guitar chords, an error +message "Command not recognized" is issued whenever a %%MIDI +chordprog or %%MIDI bassprog command is encountered. +The problem occurs mainly with runabc, which +performs only one pass through the tune and is unable to +know whether guitar chords are present before sending +%%MIDI commands. Since no MIDI program command is issued +in this situation, the error message was disabled, The +fix was made in dodeferred() in genmidi.c + +2003 April 12 +abc2midi assumes the ratio of 2:1 for long/short notes +in broken rhythms specified with angle brackets (eg. c>d), +Though this can be changed using the %%MIDI ratio command, it +is inconvenient for many users since it is necessary to edit +each tune in the abc file in order to effect this change. +A new command parameter -RS (ratio standard) changes default +ratio to 3:1 which is the standard music notation. The new +parameter still allows the %%MIDI ratio command to override +the default. The change was incorporated in event_init() +of store.c. + +2003 Apri 19 +The proposed abc standard allows non numeric identifications +for the voice field, eg. V: soprano instead of V:1. If you +are creating a midi file, each unique identification string will +mapped to a sequential numbers 1,2 etc, as if you had used numbers +originally. The change allows abcMIDI to handle a number of +new multivoiced abc files which have adopted this convention. +Only the first 20 characters of the identification +string are distinguished. Anything following the identification +string is ignored. The identification string should not end with +an equal sign =. If nonnumeric identifications are used, +abc2midi will print the mapping between the id's and the numbers. +This may be useful for catching spelling errors in the id's. +The fix was made in function parsefield in parseabc.c. The +change does not yet allow V: commands to appear before the +body of the tune. + +A number of abc files may designate a rest using x instead of +z. This means that this rest exists but should not appear +in the printed score. I have modified the parser so it shall +now interpret x as rest; however, if you are using yaps to +print the score, this rest will still remain visible. Abc2midi +will now treat x exactly like z. Abc2abc will probably +automatically convert the x's to z's whether you want it or not. +A minor change was made in parsemusic in parseabc.c. It is +necessary to modify toabc.c and yapstree.c to fix the +remaining problems. + +2003 April 27 +Guitar chords. The base note preceded by a slash in the guitar +chord may now be in lower case as well as upper case. For example, +"G/B" and "G/b" will both be treated the same way. This complies +with the proposed abc standard 1.7.6 (abc-draft.txt) and avoids +problems with some files in the Nottingham database. The fix was +made in event_handle_gchord in store.c. + +Guitar chords. When there is a change of meter, the gchord beat +does not seem to get changed. I inserted a call to setbeat() +in writetrack() in genmidi.c whenever a TIME feature is encountered. +It was also necessary to change the definition of setbeat in +store.c from static to external. + +2003 May 3 +Karoake lyrics: Improved the documentation for the functions +write_syllable and getword in genmidi.c which handle the lyrics +in the w: body line. If a bar line is placed in the lyric +line between two tied notes, for example see below, + +"C6" c> G E2- | E2 (3 c d c | "E7" B> ^G E2- | E4 | +w: All of me, | * why not take | all of me.* + ^ +write_syllable loses synchrony with the music while searching +for the next bar line in the music. The problem was fixed +by resetting waitforbar to 0 between the two calls of +write_syllable, in writetrack (genmidi.c) after TNOTE is +handled. + +I found most warning messages about mismatched +lyric syllables to music notes have to do with users +failing to notate syllables correctly when tied notes +occur. (Failure to place a * or _ (underscore) preceding +syllable of tied note. Confusing hyphen with underscore...) + + + +2003 May 4 + +abc2midi file xref: Abc2midi has the option of converting +only a particular tune in a abcfile to a midi file by specifying +the X: reference number immediately following the abc file name. +When this feature is used, warning messages such as + +Warning in line 28: T: outside tune body - possible missing X: + +The problem occurs in the function parsefield in parseabc.c. +In order to catch the reference number of the selected tune, +every line of the input file is parsed. A flag "parsing" equal +to 0 or 1 is used to turn on the parsing inside the body of +the of the music. This flag is turned in function event_refno() +in store.c by calling the function parseon() in parseabc.c. +Unfortunately all field lines (eg. T: , M:, L:, V: ...) were +unaffected by this flag and continued to be parsed. When the +T: field command is encountered, it falls through to the +default: in parsefield and it is processed by the function, +event_field in store.c. Event_field was designed to treat +the T: and R: conditions but before handling these conditions +it checks whether the control flag dotune is set. This flag +is also set by event_refno. If the flag is not set, then +event_field assumes that a T: field command was encountered +without a preceding X: reference field which is a valid +error condition. + +Since all field lines in the abc file are parsed this +introduces other problems. Any anomaly in the field lines +whether they are from the selected tune or not are reported. +For example, if a user has selected for example tune 500 +from a large abc file, errors in the field lines of other +tunes will be reported. Furthermore, in some cases the +program may crash in processing a field line of another tune. + +To address these problems, the functions parseline and +parsefield in parseabc.c were modified so that all field +lines (except for the X: field line) and all text lines are +ignored for nonselected tunes. Parseline checks whether +the flag parsing is set before calling parsemusic or +event_text. In parsefield, the condition key == 'X' +was moved from the switch control structure and +treated separately immediately when entering this function. +If parsing flag has not been set, the function returns +immediately after checking for key == 'X'. + +This introduces a new problem. If the abc file has no +X: field, the abcmidi programs does nothing +without any error indication. To handle, this situation +I introduced a the global variable parsing_started into +parseabc.c, It is initialized to 0 and set to 1 +when the function parseron() is called. Prior to the +end of the function parsefile, the parsing_started +variable is checked. If it is still 0, an error message +is returned. + +Finally, event_linebreak() is suppressed in parsefile() +whenever the variable parsing is not set. This avoids +a lot of blank line output from abc2abc whenever the +X: field is missing from the input abc file. + +This is a major change to the code, since it affects +three programs, abc2midi, yaps and abc2abc. I hope this +has not introduced new problems. + +2003 May 11 + +Many tunes have a left repeat sign (|:) missing. In most +cases it is fairly clear where to place the repeat sign +and abc2midi merely puts a warning message "Assuming repeat". +When you are processing a large group of abc tunes these +messages may be annoying. A new parameter -NAR (no assuming +repeat) will suppress this message when you are +running abc2midi. However, occasionally you get the error +message "Found unexpected :| ...". This is a more serious +problem. Due to some ambiguity, the program store.c was +unable to place a missing |: into the tune. During the +second pass, genmidi.c encounters the :| and does not know +where to begin the repeat. This is a real error since the +repeat will not occur. This error message is not suppressed. + +The instructions !trill! and !fermata! are recognized by +yaps and abc2midi and are treated in the same way as the +decorations T and H preceding a note. To do this I introduced +a new integer global array decorator_passback[] which is set +by event_handle_instruction in both yapstree.c and store.c. +The array is passed between files parseabc.c, store.c +and yapstree.c as an extern. + +2003 May 18 + +The symbol y used to denote a space in Barfly, is ignored +and no longer causes an error message. It is deleted by +abc2abc. + +2003 May 19 + +Added an option to number bars in yaps. Note the bar numbers +may not match those in abc2midi or other abc*ps programs. +Introduced global flag barnums and global integer nnbars in +yapstree.c which is set by event_init and linked to +drawtune.c. Added new -k option in event_init +in yapstree.c. In event_bar in yapstree.c passed the current +bar number instead of NULL in addfeature. In drawtune.c +introduced a new function printbarnumber which is called +in various places in the function printvoiceline. + +%%MIDI chordname accepts negative semitone shifts relative +to root. In function event_specific in store.c, replaced +readnump with readsnump. + +2003 May 22 + +Bar numbering in yaps is now in agreement with abc2midi but +may differ by one unit with abc2ps and other members of its +family. See abcguide.txt for more discussion. I moved the +position of the call to checkbar() in event_bar() (yapstree.c) +so it occurs before addfeature is called rather than after. + +The decoration field line d: (used inabcm2ps) is not parsed as +a music line but is an ignored field line. Change +was made in parseabc.c in parsefield() and parseline(). + +2003 May 31 + +Yaps crashes when it encounters text preceded by an underscore +in a guitar chord. For example +"G" AB/2B/2 "_quiet" DD| g/2g/2d/2d/2 | +here yaps crashes when the function event_handle_gchord (in +yapstree.c) encounters the text _quiet. The problem was fixed +by ensuring that, cv->instruction_pending is not NULL prior +to adding anything to this structure. + +2003 June 6 + +Yaps ignores any guitar chords placed in front of a chord if +the notes in the chord are not in descending order. For +example in the following line +|"Gm"[G2B2][Ac]|[Bd][Ac][GB]|"D"[A/2c/2][A/2c/2][Ac][Bd]| +the guitar chords Gm and D do not appear because they precede +a chords [G2B2] and [A/2c/2]. This problem also applies to +any instructions (eg. !quiet!) which immediately precede +a chord. The problem has to do with the way the gchord +and instructions are processed by yapstree.c. When they +are first encountered they are placed in temporary places, +cv->gchord_pending and cv->instructions->pending. When +the next note is encountered, the function newnote moves +them to fields associated with that note. Unfortunately, +when printvoiceline in drawtune.c processes the notes in +a chord it expects the guitar chord or instructions to be +associated with the first note encountered in the chord. +(It checks chordcount variable.) This is not always true +because the function insertnote in yapstree.c for some +reason will reorder the the notes in the chord if they +are not in descending order. + +The fix was to modify noteinsert in yapstree.c so that +if it reorders the notes in the chord, it also moves the +gchord and instructions fields to be with the first note. + + +14 June 2003 + +Yaps produces a segmentation error when it fails to +find an expected continuation line and attempts to +print a guitar chord.(eg.) + +X:1 +T:example +K:C +"C" abcd|\ + +(In this example there is no more records following the +backslash.) + +The error occurs when it tries to execute showtext in +the function notetext in the file drawtune.c. The fix was +to ensure that the pointer spacing is not NULL prior to +calling showtext. + + +21 June 2003 + +Abc2midi assumes the last %%MIDI gchord string specified +as the default for the start of the tune. In the following +tune, + +X: 1 +T: gchords +M:4/4 +L:1/4 +K:C +"C" CCCC|CCCC| +%%MIDI gchord czcz +FFFF|FFFF| +%%MIDI gchord fzzz + GGGG|GGGG| +%%MIDI gchord fcfz + CCCC|CCCC| + +the gchord string was not set for the first two bars. It was +expected that abc2midi would use the system default for 4/4 time, +i.e. fzczfzcz. Instead, the last defined gchord fzfz was assumed, +which is not expected. If the user places another %%MIDI +gchord string before the first bar or adds a redundant meter +field M:4/4 just before the first bar, everything is ok. +Abc2midi calls setbeat which calls set_gchords just after +it processes the first K: declaration in the field area. +When abc2midi writes the first track writetrack(0) containing +the melody, everything is still ok, except that the accompaniment +is not written at this point. Each time writetrack encounters +another %%MIDI gchord declaration, set_gchord changes the +gchord string. When it is time to start the accompaniment track, +the gchord string was left as the last declared string. + +The fix was to move the setbeat invocation from headerprocess() +in store.c to the beginning of writetrack in genmidi.c when +the accompaniment track is identified. I also added a short +caveate in abcguide.txt about the setting of MIDI gchord +string. + + +28 June 2003 + +The %%MIDI transpose command transposes all channels including +the drum channel. For the drum channel, the pitch component +selects the percussion instrument, so transposition is not +appropriate here. + +The fix was applied to the function save_note in the file +genmidi.c. Transposition is blocked if the drum channel +9 (counting from 0) is selected. + +29 June 2003 + +Besides the key signature, the K: field can contain many +other descriptors, such as the clef (treble, bass...), the +octave and transposition. The code for parsing the K: field +parsekey was rather convoluted and hard to understand. It +was simplified by breaking it up into several functions. +During this process, I discovered an Easter Egg (undocumented +feature) in abc2midi. It is possible to transpose an +individual voice without affecting the other voices. +The documentation to these features was improved in abcguide.txt. + + +1 July 2003 + +The single voice transpose function described above does not +work correctly in combination with the global transpose initiated +by the %%MIDI transpose (or rtranspose) function. The original +code in store.c and genmidi.c was confusing since communications +between the two files was performed by both the feature/pitch +arrays and a global variable global_transpose which was linked +to both files using an extern int declaration. Here is a +short description on how it was originally. + +Parsekey passes transpose to event_key. When a +new transpose value is obtained from event_key, the TRANSPOSE +flag is added to the feature array and the value of transpose +is put in the pitch array. In addition the global_transpose +variable (a variable linked to genmidi.c) is also set to +transpose if event_key obtains the transpose value before +getting to the body of the music. When a transpose value +is obtained from event_specific (i.e. from a %%MIDI transpose +indication) a TRANSPOSE flag is also added to the feature +array and the linked variable global_transpose is always +set to the transpose value. + +Genmidi.c processes the TRANSPOSE feature in the function +writetrack. At the start of every track, writetrack sets +the transpose variable (here not linked with store.c) to +global_transpose. When TRANSPOSE feature is encountered the variable +transpose is extracted from the pitch array. The transpose +value is added to the note pitch whenever a note is issued. The +transpose value is also stashed away by save_state in case a +REPEAT feature is encountered. In this situation, the stashed value +is recovered by restore_state. + +It would make more sense to treat transpose and +global_transpose independently. i.e. +new pitch = pitch + transpose + global_transpose. +Also it would be be a good idea not to pass global_transpose +to genmidi.c using "extern int" but setting it using a new +feature GTRANSPOSE in the feature array. + +Fix: GTRANSPOSE introduced in abc.h. global_transpose variable +and associated code eliminated from store.c. In writetrack +in store.c, another switch condition for GTRANSPOSE was +introduced. global_transpose initialized to 0. transpose initialized +to 0 in starttrack. In noteon_data and addtoQ transpose + +global_transpose are added to pitch. These changes now allow +global_transpose and transpose functions to work together and +independently. + +Basically transposition is now performed by either or both +variables 'transpose' and 'global_transpose'. The only difference +between these variables is that the transpose variable is +reinitialized to zero each time a new track is started, while +global_transpose is only initialized at the start of the tune. +These variables are set only through the feature/pitch +arrays in store.c. + +5 July 2003 + +Abcm2ps allows the voice field to contain additional +descriptor information such as the clef name. This information +may indicate a voice transposition by one octave. Abc2midi +and other abcMIDI programs currently ignore this information. + +Fix: +A new function parsevoice was introduced into parseabc. +which contains a combination of the code in both parsefield +and parsekey. New parameters were introduced to event_voice +in store.c, yapstree.c, toabc.c, parseabc.c and parseabc.h +in order to pass this information. In store.c, event_voice +will call event_octave if gotoctave is set and insert +a TRANSPOSE feature in the feature/pitch array. In toabc.c, +event_voice will also output the clef if gotclef is set. + +In the event that treble+8, treble-8, or tenor-8 is +specified, parsevoice will set octave to the appropriate +value and set gotoctave so that event_voice in store.c will also +issue an event_octave. The transpose indication in the +clef is detected in the function isclef() in parseabc.c +which now has extra parameters. + +Please note no transposition is assumed for the bass clef. +If it is desired that abc2midi transpose that voice, a +octave=-1 or -2, should be included in the K: or V: field. + + + +6 July 2003 + +Abc2midi considers the placement of a V: indication outside +the music body (in the header) as an error and ignores it. +Other applications such as abcm2ps permit V: indications to +occur music header. In such instances, the voice field +specifies information such as the clef to be used for that +voice. Several changes were needed to handle the this +convention. + +(1) In event_voice, the check "pastheader" was disabled; however, +it is important not to call checkbreak() prior to passing the +header. (2) It is necessary to create the first voicecontext +structure immediately after the parser is started rather than wait +for the first K: field (which ends the header block). +Therefore, the code + + v = newvoice(1); + head = v; + +was moved to event_refno and event_key was replaced + getvoicecontext(1); + +(3) Normally event_octave will transpose all the music voices +if it is called in the music header. This needs to be disabled +when it is called from event_voice. A new parameter, local +(as opposed to global) was introduced into event_voice to +indicate such a situation. (It was necessary to also +put this change in parseabc.c, yapstree.c, toabc.c, parseabc.h, +in addition to store.c) + + + +12 July 2003 + +Abc2midi loses synchronization between voices when a voice +change occurs in the middle of a bar. The following tune +does not get converted correctly into a MIDI file. + +X:1 +T: sample +M: 2/4 +L: 1/8 +K:G +V:1 +|:AG Bc| +V:2 +|:C2 C2| +V:1 + AG Bc|[1 +V:2 + C2 C2|[1 +V:1 + CDEF:|[2 + EFG2| +V:2 + D2 D2:|[2 + G4| + +The problem occurs when writetrack (in genmidi) is processing the +second repeat. When it comes to the bar marked +with a [1 it attempt to skip to the bar labeled [2, however, +it failed to check for a voice change. (It is unusual to +switches voices in the middle of a bar.) Instead it another [1 +and outputs numerous error messages. + +The problem was fixed by checking for a voice change and searching +for the continuation of the current active voice using the +findvoice function. + + + +Yaps terminates prematurely if a tune does not contain a +M: indication in the header. Yaps reports that there is no +M: field but when it attempts to set it to the default 4/4 +in startbody(), no voice structure has been created. +To fix this problem lines of code, setvoice(1) and +startbody() were interchanged in event_true_key() in yapstree.c + + +13 July 2003 + +Yaps bar alignment fails in multivoiced files containing +tuples (eg. triplets). For example, + +X: 1 +T: yaps trips on triplets +M: 2/4 +L: 1/8 +K: G +V:1 +C4|C4|(3BBB (3BBB|C4|C4| +V:2 +F4|F4|F4|F4|F4| + +The bars for the second line do line up after the triplets. + +The function advance() in position.c does not set the +notelengths in the case of triplets. As a result, +spaceline() in position.c has the incorrect temporal position +of the notes when it tries to place the notes on the staff. + +Fix: a new variable tuplenotes was introduced in the struct +note (struct.h). This variable is set in event_note, in yapstree.c +and contains the sequence number of the tuple note (descending). +In event that advance() detects a tuple note (based on this +variable), the temporal length is adjusted by multiplying it +by the tuplefactor. (A new function mulfract was introduced +for this purpose.). The notes and bars are lined up now, +but more work is probably needed to get more pleasing spacing. + + +19 July 2003 + +Abc2midi fails to set key signature sharps or flats pattern in +multivoiced tunes with voice indications in the header. +For example in the following tune, + +X: 1 +T: G minor scale +M: 2/4 +L: 1/8 +V:2 +K: Bb +V:2 +GABc|defg| + +the notes B and e are not flattened in the output MIDI file. +This is a new bug I introduced in July 5, 2003 when I extended +the abcMIDI package to handle voice field indications in the +header block. For each voice there is a separate voicecontext +structure which contains its own basemap for sharpening or +flattening selected notes. See store.c code. (This permits +the option of a voice to have its own key signature which is +different from the other voices.) There is also a global +voicecontext structure used for applying the key signature to +all voices if they are not indicated separately. The global +key signature is copied to the voicecontext of a separate voice +at the time that the voicecontext structure is created. +Unfortunately, if the voicecontext structure is created prior +to setting the overall key signature with the first K: indicator, +then the basemap for that voice is set for C major or A minor. + +Fix: a new flag, keyset was introduced in the voicecontext +structure. This flag indicates whether the key signature was +known at the time when the voicecontext structure was +allocated by newvoice(). Whenever getvoicecontext() switches +voices context, it now checks keyset to determine whether +it is necessary to copy the basemap and related variables +from the global voicecontext structure. + +I: octave=n has been disabled in abc2midi. +Since an octave shift can be indicated in either the +K: or V: field, it is no longer necessary to use the +info field for setting the octave range. I have disabled +this feature to discourage using the info field for +setting the octave range. + + +20 July 2003 + +The hidden rest (x) was introduced in abcMIDI in April 19 +2003. Abc2midi treated it as a regular rest but abc2abc +automatically converted it into a regular rest z. The +new functionality to transpose separate voices that was +introduced in abc2midi now makes abc2abc even more useful. +I have upgraded abc2abc so it now preserves the hidden +rests in the abc files. Yaps continues to not distinguish +the two types of rests (like abc2midi). + +Fix: introduced an extra variable in event_rest in +parseabc.c, store.c, yapstree.c, toabc.c and parseabc.h. +In toabc.c event_rest emits an x instead of a z if +a hidden rest is detected. + + +16 August 2003 + + +Abc2midi: The drum accompaniment is started or stopped using the +instruction command !drum! and !nodrum!. The !drum! and +!nodrum! commands are not part of the abc standard so +other applications such as abc2ps and related clones do +not understand this instruction. The programs either ignore +or it or return a warning. + +I have introduced an alternate method of starting and stopping +the drum track using the MIDI indications. + +%%MIDI drumon +and +%%MIDI drumoff + +This is similar to the method of starting and stopping gchords. +(%%MIDI gchordon and %%MIDI gchordoff). I feel this is the +preferred method and the older method will probably be +deprecated. Fortunately, I am the only one using drum +accompaniment (eg. isra.abc) so all of this has little impact. + +August 22 2003 + +Midi2abc creates a abc file with a blank title. It is +more useful to place the name of the input midi file in the +title. + +Midi2abc puts a blank line in the abc file in the +event that a newline character \n is embedded in the +meta_text. A blank line signifies the end of a tune, so +the remaining part of the abc file is not processed. +The function remove_carriage_return was updated so it +now checks for both \r and \n. + +August 31 2003 + +Reorganized and improved documentation of midi2abc.c + +Many MIDI files have multiple tempo indications. In fact +some MIDI files change the tempo at every beat. Midi2abc +assumes the last tempo indication; however, in some MIDI +files the tempo slows down at the end. When the resulting +abc file is converted back to a MIDI file it plays much +slower than the original. I have modified midi2abc so +that it now assumes the first tempo indication and +ignores all following indications. + +September 8 2003 + +Midi2abc identifies drum tracks (channel 10) but it needs +to issue a %%MIDI channel 10 to that voice so that abc2midi +will know to assign that voice channel 10. Printtrack was +modified to test for a drum track. + +Added two new parameters, -bpl and -bps to control the +formatting of the output abc file. These parameters +control the number of bars printed per line, and the number +of bars to be associated with a music staff. The -obpl +(one bar per line) parameter is deprecated. + + +September 13 2003 + +Midi2abc by default does not use the PPQN information in the +MIDI header to determines the note length in MIDI pulses. +Furthermore it ignores any time signature information in +the MIDI file that may be present. Most MIDI files do +contain valid information so midi2abc produces the best +output when run time options -xl and -xm are included. +Midi2abc was modified to make these run time options the default +and the unnecessary flags -xl and -xm are now removed. +To allow the user to force midi2abc to estimate xunits +(MIDI pulses per standard unit note length) from the note +duration statistics, a new option -gu was now introduced. +Since this is a major change in how midi2abc runs, the +version number was bumped up to 2.6. + +September 14 2003 + +Contrary to the documentation, the anacrusis is not specified +in beats but in abc half unit lengths where a unit length is +given in the L: field in the header. For example if +L:1/8 and M: 4/4, an anacrusis of 1 beat is specified as 4 (i.e. +four 1/16 units). This is due to the way the quantized +music is represented in midi2abc. Midi2abc does not allow notes +shorter than than 1/2 an L: unit. Therefore if the unit length is +L: 1/8, the shortest note that can be produced by abc2midi +is a sixteenth note. Note lengths are stored internally in +midi2abc as numerator/denominator where the denominator is +always 2. So a sixteenth note is quantized to a numerator +value of 1. Therefore midi2abc has difficulty representing +very short notes that are encountered in trills or drum +rolls. In such situations you should use the -s option +for short notes to get an approximation. + +This also explains why printtrack, findana and guessana want +the barsize to be measured in half abc unit lengths (barsize +is doubled in the calling sequence for these functions.) + +I have corrected the readme.txt and the midi2abc.1 man file. + +September 21 2003 + +Laura Michaels contributed patches to store.c, genmidi.c +and abc.h to handle the Copyright extended information field +(see abc2-draft) and to improve the production of Karaoke +MIDI files. Laura Michaels also provided makefiles for +other compilers such as Ming and Watfor. More details follow. + +The proposed standard introduces a new field using the +syntax + +%%abc-copyright (c) Copyright John Smith 2003 + +Abc2midi now inserts this in the MIDI file in the form of a +metatext copyright tag. Changes were made to the event_specific +function in store.c to process the copyright information. + +Karaoke file applications such as Winamp, VanBasco;s Karaoke +player, and WinKaraoke (on Windows) have difficulty extracting +the composer and copyright information fields and confuse them +with the Karaoke text. The function karaokestarttrack in genmidi.c +was modified to handle additional @T information lines for +composer and copyright information after the title line in the +first MIDI track. In the Karaoke track (track 3), this +information was also added in the form of @I fields. Also +other abc information fields such as H: and A: were suppressed +in the Karaoke track by setting texton to 0 in printtrack. + +The 98 character limit for text lines handled by event_field +in store.c was changed to 255 (see default case in switch (k)). + + + +September 28 2003 + +For multivoiced abc files there is a need to be able to apply +a fermata to a rest. For example, consider this file. + +X: 1 +T: fermata applied to rest +M: 2/4 +L: 1/8 +K: G +[V:1] CDEF|GAF!fermata!G|C2 C2| +[V:2] EFGA|Bcd!fermata!z|C2 C2| +[V:1] CDEF|GAF!fermata!G|C2 C2| +[V:2] EFGA|Bcd!fermata!G|C2 C2| + +If the fermata is not applied to the rest, there is a loss +of synchronization between the two voices. + +The function event_rest was modified to get the array decorators +from one of its passed parameters. In store.c event_rest would +double the length of the rest (including hidden rests) if +decorators[FERMATA] is set. In parseabc.c it was necessary to +to update the decorators array for the case 'z' and 'x', prior +to passing it to event_rest. Changes were also required in +yapstree.c and toabc.c even though event_rest does not use the +decorators array in these files. The declarations for event_rest +in parseabc.h also needed to be changed. + +September 29 2003 + +A new problem with setbeat (store.c) was discovered. For the +file + +X:1 +T: time sig +M: 2/4 +L: 1/8 +K: G +"C" G2 G2| G2 G2| +[M:3/4] G2 G2 G2|G2 G2 G2| + + +The gchord output was not correct for the first two bars. +This was caused by several problems in the code. (1) Setbeat +calls set_gchord to set the gchord_seq, gchord_len, g_num, +and g_denom used by dogchords. The values for g_num and g_denom +were incorrect because they were computed from mtime_num +and mtime_denom which were set by set_meter. The values +of mtime_num and mtime_denom were the last values in the +previous tracks processed so if there was a change of meter +in the tune they would not reflect the initial value. +(2) Setbeat chooses the appropriate gchord string on the basis +of the time signature stored in the time_num and time_denom +array. It is therefore necessary that these values remain +current to the current context during the writetrack pass. +Therefore set_meter was modified to update time_num and +time_denom whenever it is called. + +Set_meter is called in several places. It was called in +starttrack with the global parameters time_num and time_denom. +Unfortunately these parameters are affected by the event_timesig +which is called during the parsing stage. Therefore their +values reflect the last time signature encountered during +the parsing stage. It is necessary to cache the initial settings +of the time signature set in the header block. New variables +header_time_num and header_time_denom are defined in store.c +and passed to genmidi.c as externals. + +In writetrack, for the accompaniment track it was necessary +to call set_meter() with the header time signatures just prior +to setbeat(). Set_meter is also called by write_meter in genmidi.c. +Write_meter is called whenever a TIME feature (for time signature) +is encountered. Fortunately, the correct time signature stored in +the num[] and denom[] arrays are used. Setbeat is called shortly +after in printtrack. + + +October 13 2003 + +Though most MIDI files indicate a time signature few also +indicate a key signature. Though midi2abc reports any key +signature it finds in the MIDI file, it does not use it but +insists on determining it by scanning all notes and choosing +the key signature that minimizes the number of accidentals. +This works fine if there are no key changes in the music. +If the MIDI file does indeed indicate key signatures and +key changes then midi2abc should use this information in +creating the abc file. + +In a similar vein, for some MIDI files there may be more +than one meter change. Midi2abc uses the first time signature +that is indicated in the MIDI file. If it encounters other +time signature indications later, it reports it but it still +uses the initial time signature to transcribe the file. +Again it would be desirable if midi2abc would act on this +information. + +Looking at midi2abc.c, it was noticed that the function findkey() +is always invoked except when the key signature is passed in +one of the run time parameters. If a key signature or time +signature metatext command is encountered, a time stamped +text message is added to the tlistx structure associated +with that track. These text messages are sent to the +abc file at the appropriate time using the handletext function +which is invoked by printtrack; however, no adjustment is +made for any key or meter change. Further the barsize +is assumed to be fixed. The barsize is a local variable +in the main program and it is passed to printtrack as +one of its parameters. The barsize controls the placement +of bar lines in the output abc file. + + +Numerous changes were needed to fix these problems. +(1) A new global flag, gotkeysig was introduced to the code. +It is initialized to zero but set to 1 whenever a key signature +metatext command is encountered. (2) A new variable 'type' was +added to the tlistx structure. If tlistx.text contains the +key signature, tlistx.type is set to 1. If tlistx.text contains +the time signature, tlistx.type is set to 2. For everything +else, tlistx.type is set to 0. (3) The 'type' variable was +added to the addtext() function and in the many places where +it was invoked. (4) In the function txt_keysig(), the verbose +message sent to the tlistx structure was replaced with just +the sf and mi (number of sharps/flats and major/minor flag). +(5) In the function txt_timesig(), The verbose message was +replaced with just the time signature nn/denom. (6) Major +additions were made to the function handletext() which now +does more than just print text at the appropriate place. +If the text string is a key signature or time signature as +indicated by the type variable, then the key signature or +time signature parameters are extracted. If it is a key signature, +setupkey(sf) is called which does all the work of printing +the K: field and setting up the tables for suppressing +the accidentals. If it is a time signature, a M: %d/%d %d +command is printed (time signature and pulses per quarter note). +(7) The barsize variable was turned into a global variable +like asig and bsig. (8) The function txt_timesig() was +broken into two functions, txt_timesig and setup_timesig(). +The new function setup_timesig() updates the global variables, +asig, bsig and barsize. If unitlen was never set, it is +also set as well as xunit. Because the notes are quantized +in a separate pass, we must use a fixed xunit and unitlen +for the entire file. Setup_timesig() is also called during +the printtrack pass whenever handletext() detects a meter +change. (9) Printtrack uses the barnotes counter to decide +when to place a bar line. It is set to barsize at the +beginning of each bar and it is decremented by each note. +When it reaches zero a new bar line is issued. (It is +done this way in order to handle anacrusis.) If barsize +changes after the start of the bar it is necessary to +correct barnotes. Printtrack keeps track of the previous +barsize (last_barsize) and uses that to fix barnotes. +(10) Added a new option -gk to force midi2abc to guess +the key signature by minimizing accidentals even though +the key signature is already indicated in the MIDI file. +Normally it will automatically guess the key signature if +no key signature is found in the file and the key signature +is not specified with the -k parameter. + +Unfortunately, this was not all the needed changes. +For multitrack MIDI files it is customary to reserve the +first track for handling global operations such as tempo, +key, meter changes, and text messages. The remaining tracks +contain the actual music. In the case of multivoiced abc +files, it is necessary to apply the meter change or key +change to each voice. Therefore for each voice, midi2abc +needs to also check the tlistx structure in track zero for +any such changes. Another handletext() call was added to +to printtrack to handle this situation. + +Abc2midi does not follow this convention exactly. For +single voice abc files with possible bass/chord or drum +accompaniment and possible Karaoke, it uses several tracks +but it does not reserve track 0 for this special purpose. +For multi voice abc files, abc2midi does use track 0 for +this special purpose and places text and metatext commands +grabbed from track one; however, because the delta times +from the missing notes were not accounted for, the delta +times for the time signature and key signatures are +not correct. (They are all zero.) Fortunately, each +track also has any key or time signature metatext commands +with the correct delta times (assuming the abc file +was notated correctly), so that information in track +zero is not needed. The simplest fix was to suppress +output of these meta commands in track 0. In writetrack +(genmidi.c) a new flag 'timekey' was introduced to suppress +MIDI commands for key/meter changes in track 0. + +The function setupkey does not work correctly after +the first call to this function. After that, the accidentals +are put in the wrong place. It was noticed that the +array key[] is initialized to zero in the function findkey() +instead of setupkey where it is actually used. Findkey() +is normally only called once if it is called. The +initialization code was moved to setupkey. + +October 25 2003 + +When the MIDI file has more than one key signature or +time signature, the first key signature or time signature +displayed in the header block reflects the last signature +that was encountered in the MIDI file rather than the +initial initial signature. This is corrected later on, +however the abc file looks strange. To fix this problem +new variables, header_asig, header_bsig, header_unitlen, +header_keysig and header_bb were introduced. When parsing +the MIDI file, they are set to the first time signature or +key signature encountered. They are printed in the header +block. + +For multitrack MIDI files, midi2abc prints out all +the textual information for track 0 immediately following +the end of the header block (first K: indication). This +unfortunately may include a whole list of key signature +or time signature meta text commands resulting in a +correct but rather confusing abc file. To avoid this +situation a new variable, trackno, was added to the +function handletext. The function handletext now suppresses +the K:, M:, and L: indications for track zero when the MIDI file +has more than one track. + +October 26 2003 + +There are still circumstances where a redundant key signature +or time signature is printed in the abc file. To avoid these +situations new variables, active_asig, active_bsig and +active_keysig were introduced. They are set to the current +status. Before printing a new signature, the present status +is checked and only changes are printed. + + +November 9 2003 + +Midi2abc frequently fails to detect triplets in the MIDI file; +even when it has been notated correctly using a music notation +program. Therefore sets of triplets may be converted into + +D3/2D-[D/2-D/2]D A3/2B-[B/2C/2-]C| + +instead of + +(3D2D2D2 (3A2B2C2| + +which is another annoyance. Midi2abc.c has a special function +called dospecial which attempts to detect broken notes (eg. +C > D) and triplets; however, it does not seem to work +consistently. The problem is that all notes are quantized +to units of 1/32 or 1/16 notes, (depending on the meter). +The length of a triplet note is 1/12 or 1/24 which does +not get quantized exactly. Thus the representation of this +sequence (calling scannotes in the debugger) appears as +follows. + +Pitch 62 chan 0 vel 127 time 160 xnum 3 playnum 3 +Pitch 62 chan 0 vel 90 time 160 xnum 2 playnum 3 +Pitch 62 chan 0 vel 90 time 160 xnum 3 playnum 3 +Pitch 69 chan 0 vel 90 time 160 xnum 3 playnum 3 +Pitch 71 chan 0 vel 90 time 160 xnum 2 playnum 3 +Pitch 60 chan 0 vel 90 time 160 xnum 3 playnum 3 + +time is in units of midi pulses, xnum and playnum +are in quantized half units where xunit = 120 midi pulses. +The time and xnum are the inter-onset time of the note (length +between onset of this note and the next note). Playnum +is the quantized duration of the note (from midi on to +midi off). All of these variables are computed +by the function quantize() in midi2abc. Note that +160 is not divided even by the half unit = 60. Playnum +is rounded up but xnum compensates for the fact +that it may have been too long in the previous note. + +The code in the function dospecial is far from transparent. +It looks ahead one or two notes to determine whether +this note and the following notes should be treated +differently (either as broken or triplets) and uses +the return character or featurecount array to signal +to printtrack how to handle these notes. One of the +tests in dospecial is the line just before the +broken rhythm tests is (reformatted for clarity) + if ((v2 < pnum) || (v2 > 1 + pnum) || + (pnum == 0) || (v1+v2 > *barnotes + )) { + return(' '); + +where v1,v2 refer to the xnum values of this note and the +next note and playnum is the playnum value of the next note. +v2 happened to be less than pnum due to the adjustment +discussed above, so the program returns from this function +without testing for broken notes or triplets. I commented +out /* (v2 default_length is placed in +num, denom storage. CHORDOFFEX is a new feature type added +to abc.h for handling this situation. Genmidi.c treats +CHORDOFF and CHORDOFFEX the same way. + +A new function fix_enclosed_note_lengths was introduced to +readjust the note lengths of all the notes in the chord in +the event that it is set outside the enclosing brackets +(i.e. CHORDOFFEX). + +The function tiefix now keeps track of the chord start ([) +in the variable chord_start. When it encounters a CHORDOFFEX, +it calls fix_enclosed_note_lengths. + + +November 07 2004: -chord extension continued + +yaps: + +Unlike abc2midi, yaps only performs one pass through the +abc file while preparing a very detailed layout of the music +in a complex data tune data structure. You can view part +of this structure by running yaps with the -d parameter. +This data structure is passed to printtune() in drawtune.c. + +A new function fix_enclosed_note_lengths was created in the +file yapstree.c to adjust the note durations. This function +is called by event_chordoff when the parser encounters +the end of a chord (']'). The new function does nothing +if ] is not followed by a note length. Otherwise it corrects +cv->barcount in order to avoid warnings regarding the +number of beats in the bar. It replaces the note duration +of each note in the chord with the new note duration. +The function count_dots is called to replace the note +duration representation. (There still seems to be a +problem here.) + +abc2abc: + +Minimal changes in toabc.c were made. The function event_chordoff +was modified to output the note length information following +the chord if any and to correct the bar count. + + +November 20 2004 + +The fix for handling chord extensions in yaps did not work +properly and would frequently place tails on notes which +should not have tails. It was discovered that chords have +their own structure for indicating their PostScript representation +and their tail is drawn by a function called drawchordtail. +The yapstree.c function event_chordoff was modified to also +update the chord structure when the chord extension occurs. + +Introduced a new folder called programming in the doc subdirectory +and moved abc2midi.txt, midi2abc.txt and coding.txt into this +folder. The folder contains some program implementation details. +The file yaps.txt was renamed to yapshelp.txt. A new file +yaps.txt describing the implementation of yaps was prepared. + + + +November 28 2004 + +Abc2midi new feature: all notes in a chord are started at the +same instant. Inserting a short delay between the start of the notes +in the chord would provide more control over the timbre. However to +ensure that the music is not lengthened, it is necessary to ensure +that all the notes end at the same time. + +Implementation of this feature was not easy due to the way the +notes are handled are converted to MIDI commands in genmidi.c +and the complexity of the queues.c code. MIDI note on commands +are sent by a long chain of function calls starting with the +function call to noteon(). Noteon() determines the velocity +of the note from the beatstring and current context and then +calls noteon_data(). Noteon_data() calls midi_noteon() and +updates the tracklen. Midi_noteon() calls mf_write_midi_event +which finally records the MIDI command. + +The MIDI command to stop playing the note is sent to a queue +by the function addtoQ which is defined in the queue.c file. +Finally if this note is not inside a chord, or if a end of chord +feature has been encountered, the notes in the queue all processed +by calling the function delay(). Delay() converts the note duration +in MIDI tick units and calls the function timestep() which +is defined in queues.c. + +The global variable delta_time indicates the time delay in +MIDI tick units to execute the MIDI command. All MIDI command +specify times relative to the time of the last command. Functions +in genmidi.c generally reset delta_time to zero after sending +a MIDI command. Otherwise, delta_time is adjusted by timestep() +in queues.c. + +In order to control the delay intervals between notes in a chord, +new global variables notecount, notedelay and totalnotedelay were +introduced into genmidi.c. If notecount is greater than 1, delta_time +is changed to notedelay and totalnotedelay is incremented by this +amount. It is necessary to shorten the shifted notes by totalnotedelay +so that they end at the same time. The new length is passed to addtoQ +in queues.c. At the end of the chord, notecount and totalnotedelay +are reset to zero. + +December 4 2004: + +(Continued from November 28 2004.) Unfortunately addtoQ does not +know that the shortened notes have been shifted. When correcting +the delay of the cached note in the structure, addtoQ now takes +into account that the new note was shifted with respect to the +previous note by notedelay which is also passed as a global variable. +Finally, it was also necessary to adjust delta_time in timestep() +by totalnotedelay. More comments were added to the code addtoQ +and timestep in queues.c. + +The notedelay variable is set to 10 MIDI units as a default. (There +are 480 MIDI units in one quarter note beat.) A new MIDI command +%%MIDI chordattack n, was introduced in dodeferred() (genmidi.c) +to allow the user to fine tune this variable. I do not recommend +making this variable larger than the smallest note in the tune, +(eg. 30 units if there are 1/16 note chords.) The abcguide.txt +and abc2midi.1 documentation was updated. Thanks go to Hudson +Lacerda for suggesting this improvement. + + +Midi2abc outputs MIDI metatext commands as abc comments. In +some cases they can be interpreted as pseudo comments causing +undesirable actions by other software. For example, in the +following the title MIDI program 17 is converted to metatext +in the MIDI file. When midi2abc converts the MIDI file back +to an abc file the text can be interpreted as a %%MIDI command. + +X:1 +T:MIDI program 17 +C:Hudson Lacerda +M:12/8 +L:1/8 +Q:1/4=120 +K:C +%MIDI +C,^C,D,^D,E,F,^F,G,^G,A,^A,B, | +C^CD^DEF^FG^GA^AB | +c^cd^def^fg^ga^ab | +c'^c'd'^d'e'f'^f'g'^g'a'^a'b' | + + +-- output from midi2abc -- + +X: 1 +T: from (null) +M: 12/8 +L: 1/8 +Q:1/4=120 +K:C % 0 sharps +%%MIDI program 17 +%%MIDI +C,^C,D, ^D,E,F, ^F,G,^G, A,^A,B,| \ +=C^C=D ^DE=F ^F=G^G =A^AB| \ +=c^c=d ^de=f ^f=g^g =a^ab| \ +=c'^c'=d' ^d'e'=f' ^f'=g'^g' =a'^a'b'| + +As suggested by Hudson Lacerda, the fix is to add a space +before the metatext. The sprintf statement near the +end of the function txt_metatxt() was modified. + +Midi2abc should place the input file name in the title +line instead of null. This has been changed. + + +December 09 2004 + +Abc2midi new feature: introduced %%MIDI randomchordattack n. +The delay between notes in a chord will vary randomly between +0 and n-1 MIDI units. It is recommended that n is not longer +than the shortest chord. (If the shortest chord consisting +of two notes is a 1/16 note then n should be not greater than +480/4 = 120. If there are three notes in the chord n should +be less than 480/8 since the delays add up.) + +December 12 2004 - also see June 13 2005 + +New feature: chord extension applied to tied chords. + +In order for abc2midi to handle the syntax [CEG]3-[CEG]2 or +something similar, it was necessary to make more changes +in the code store.c. The code dotie() was not easy to +figure out. To avoid working with this code, abc2midi +patches up the feature,num,denom arrays so that it +appears the same as if the old syntax [C3-E3-G3-][C2E2G2] +was used instead. New functions, insertfeature() and +removefeature() were written to insert or remove a feature +in the middle of the arrays. The dotie() function was +modified to also detect the CHORDOFFEX feature and +treat it the same way as a CHORDOFF. The function +fix_enclosed_note_lengths was modified to also catch +the TNOTE feature and treat as a NOTE feature. A +new function patchup_chordtie was introduced. The +function stuffs a TIE feature after each note in the +chord and returns the position of the first TIE. +Many changes were made to the tiefix function(). +Another local variable, chord_end was added. Chord_start +and chord_end keep track of the feature index positions +of the last chord scanned. If a TIE feature is immediately +preceded by a CHORDOFF or CHORDOFFEX feature, then +that tie is stripped off and new ties are stuffed +into the chord using the function patch_chordtie. +Tiefix then backups into this chord so it can run +dotie on all the internal ties. + +December 17 2004 + +Finished debugging chord tie feature. Tiefix no +longer runs fix_enclosed_note_length when it +backs up into the chord. + + +Abc2midi: +Limin Wang discovered and D.J. Bernstein reported +two unprotected buffer overflows in store.c. This +allows an attacker to gain control of the computer +through a malicious abc file in an email message or +from a web page that is fed into abc2midi. This +applies to all versions of abc2midi. + +The buffers are now protected. + +Yaps, midi2abc: minor changes to reduce likelihood +of buffer overflow. + + +December 18 2004 + +Abc2midi new feature: +Abc2midi recognizes the !f!, !pp!, etc indications +and adjusts the audio level in the output MIDI file accordingly. +Unfortunately this may get in the way for multivoiced abc files +where the indications are placed in one voice but not the others. +When the file is typeset by abcm2ps the output looks fine, but +one of the voices is inaudible in the MIDI file. An example, +is shown below. + +X: 1 +T:ff_pp_1_1 +C:ff_pp_1_1: the second voice is covered by the first one +C:but the score could be interpreted as they both have to +C:be played with the same intensity +M:4/4 +L:1/4 +Q:1/4=100 +%%MIDI transpose -12 +%%staves (1 2) +V: 1 clef=treble +V: 2 clef=treble +%V: 3 clef=treble +% +K:C +%%measurenb 0 +% +[V: 1] G A c e | e c A G | A G A G | +[V: 2] !ppp!C E E E | G E E E | F E D C | + +Things get more complicated when 2 or 3 voices share one stave +(eg. classical guitar notation). It is not desirable to have +to many "p"s printed over and under the stave. Abc2midi +does not understand !crescendo! and !diminuendo! notation. +A simple but not a perfect solution, is to introduce a new +option in abc2midi which will tell abc2midi to ignore all +dynamic indications. + +Fix: thanks to Michele for the code and suggestion. A new +option -NFNP (no f no p) was introduced in store.c. Abcguide.txt +and abcmidi.1 documentation was also updated. + + + +Abc2midi: Wrong tempo when L: missing in a multivoiced file. +Abc2midi should assume a L:1/8 when the meter is 3/4 or larger +and L:1/16 otherwise in the event that the default length of +a note is not specified.. This works correctly for most abc +files but fails in the following example. (The tune is +played at the wrong tempo.) + +X: 1 +T: no L +M: 3/4 +L: 1/8 +Q: 80 +V:1 clef=treble +V:2 clef=treble +K: G +V: 1 +abcdf2|gabcG2| +V: 2 +ABCDF2|ABCDF2| + +Analysis: abc2midi checks for missing L: in the function +headerprocess() when it reaches the start of the tune body +(the first K: field). If the note length, global.default_length, +was not set at this point then it is set to 8 or 16. When a new +voice is created by event_voice, it assumes a note length +specified by global.default_length. In the above example, +an event_voice is called prior to the start of the body +so global.default_length is still undefined. The default_length +for the voice remains undefined and abc2midi runs unpredictably. + +Fix: headerprocess now sets default_length to global.default_length +for any voices that have already been created. + + +January 1 2005 + +Abcmidi: does not handle a tie broken by a voice switch. +In the following example, + +X:1 +T: tie +M: 2/4 +L: 1/4 +K: G +V:1 +AB-| +V:2 +cd| +V:1 +Bc| +V:2 +G2| + +the tie joining B is interrupted by a voice change. Abc2midi fails +to join the notes. Fix: the functions tiefix and dotie now check +for a voice change and do not attempt to tie notes belonging to +different voices. + + + +Abcmidi: abcmidi fails to assign the channel to correct program +(musical instrument) for the first note in a multivoiced abc +file. In the following example: + +X:1 +T: MIDI program +M: 2/4 +L: 1/4 +V: S clef=treble name="Soprano" +V: A clef=treble name="Alto" +%%MIDI program 1 60 +%%MIDI program 2 60 +K: G +V: S +G A|B C|G A|F G| +V: A +z2|G A|F G|G A| + +The first note G is played on the piano instead of +the French Horn as indicated by the command %%MIDI program 1 60 + + +Analysis: the MIDI indications are inserted into the track +number associated with the voice. In this example, voice A is +mapped into track 2 and all the program indications are put +into track 2. The midi player processes the tracks sequentially +and does not see the program change in time to affect the first +note in voice S so it is played on the default instrument, +acoustic grand (piano). The simplest fix is to ensure all +the MIDI indications go into the first voice as shown here. + +X:1 +T: MIDI program +M: 2/4 +L: 1/4 +V: S clef=treble name="Soprano" +V: A clef=treble name="Alto" +V: S +%%MIDI program 1 60 +%%MIDI program 2 60 +K: G +V: S +G A|B C|G A|F G| +V: A +z2|G A|F G|G A| + +Alternatively you can place the %%MIDI program indication +in the voice that it affects. (The channel number is no +longer needed then.) See below. + + +X:1 +T: MIDI program +M: 2/4 +L: 1/4 +V: S clef=treble name="Soprano" +V: A clef=treble name="Alto" +V: S +K: G +V: S +%%MIDI program 60 +G A|B C|G A|F G| +V: A +%%MIDI program 60 +z2|G A|F G|G A| + + +I shall update abcguide.txt regarding this issue. + + +January 8 2005 + +Another exploitable error in store.c was found by Anselm Lingnau +which causes a buffer overflow for %%abc-copyright. A fix using +the snprintf routine was suggested. The snprintf routine is a +recent addition to the C compiler; for those running older +compilers you will need to download a portable GPL implementation +of snprintf() from http://www.ijs.si/software/snprintf in order +to compile and link abc2midi. (In case the web site changes, +search for snprintf portable implementation.) If you are running an +old or nonstandard operating system for which there is little +likelihood of a buffer overflow exploit taking over your computer +and it is too cumbersome to include snprintf, then you can define +NO_SNPRINTF (in store.c) and it will use sprintf. + +Michele has added an additional correction to the broken tie +fix I made on January 1 2004. In order to handle the following +example which includes a chord in voice 2. + +X:1 +T: tie +M: 2/4 +L: 1/4 +K: G +% +V:1 +AB-| +V:2 +[dA]c| +V:1 +Bc| +V:2 +GG| + +it is necessary to add +if(localvoiceno != voiceno) break; +after case CHORDOFFEX: +in the function dotie. + + +January 9 2005 + +Abc2midi: new decorations !arpeggio! and !breath! +are introduced. When the !arpeggio! instruction precedes a +chord, the notedelay time is temporarily set to three times +its normal value. For the time being, the !breath! instruction +is treated exactly the same as a staccato marking. (i.e. +the length of the note is halved and followed by a +rest of the same value.) + +Implementation: a new decoration BREATH was added and a +new feature ARPEGGIO was added in abc.h. In store.c, +additional code was added to event_handle_instruction to +handle the !arpeggio! and !breath! commands. In event_note, +both STACCATO and BREATH decorator flags are checked and +treated the same way. + +New global variables staticnotedelay and staticchordattack +were added and linked to notedelay and chordattack in several +places. In writetrack, genmidi.c, a separate +case statement in the main switch statement was introduced +for ARPEGGIO. It changes the values of notedelay and noteattack +to 3 times its nominal value. (They are restored back to +their nominal values after a CHORDOFF or CHORDOFFEX feature.) + +Jan 22 2005 + +Abc2midi: a missing break statement caused abc2midi to crash +when encountering !arpeggio!. Added a tune demonstrating +the !arpeggio! instruction to demo.abc. + +Midi2abc: normally midi2abc groups the notes forming a beat +together so that abc*2ps produces a pretty output. For some +raw abc output, (eg.) +B3/2z4^dz/2e3/2z3/2| +it is easier to edit it if there is a space between every note (eg.) +B3/2 z4 ^d z/2 e3/2 z3/2| +A new option -nogr has been added to midi2abc. If it is included +as one of the run time options, then a space is inserted between +all notes that are not in triplets. Changes were made to printchord +and printtrack in midi2abc.c. (Search for nogr to see changes.) + + +February 03 2005 + +Abc2abc: introduced a new run time parameter -usekey. This +is a generalization of the -nokeys -nokeyf transformation +which converts the music representation to the key of C +inserting any accidentals to preserve the original key +signature. Now you can force abc2abc to represent the +music in any key signature. The -usekey parameter is followed +by a number specifying the number of sharps (positive +number) or number of flats (negative number) in the +desired key signature. + +Implementation in toabc.c: if usekey parameter is set to a +nonzero value, the nokey parameter is set so that event_note2 +is used to process the note. Setup_sharp_flats adjusts the +arrays flatsym and sharpsym to match the desired key signature. +The function printpitch prints the notes using these two +arrays. + + +February 04 2005 + +Abc2midi: It has been proposed that a new option be introduced +that would propagate dynamic indications (pp, ff, etc) from +voice 1 to all other voices so that they need only be declared +once in voice 1. This would provide another solution to the problem +discussed in December 18 2004 resulting in the introduction +of the -NFNP option. Introduction of this feature is deferred +for the time being but here is a description of what is involved +in implementing such a feature. + +When parseabc.c sees an instruction eg. !ff!, it calls +event_instruction (in parser2.c) which calls split_string +which calls event_handle_instruction (in store.c). +Event_handle_instruction interprets the instruction and +calls event_specific with a MIDI beat x x x x command. +Event_specific passes the string to textfeature which +adds an entry DYNAMIC to the feature array and a pointer +to the string in the pitch array. Note the feature array +is used to handle all the voices, and the list of voice +features are separated by VOICE entries. The problem is +that it is impossible to propagate the DYNAMIC instructions +to the other voices because the other voices may not exist +(in the case the voices are specified serially in the abc file). +The function writetrack in genmidi.c separates the specific +voice from the feature array and creates a separate MIDI +track for each voice. + +To address this problem, we would leave the code in store.c +and parseabc.c however we would need to change writetrack +in genmidi. Writetrack would now have to keep track of the +beat number when processing a voice. When a DYNAMIC feature +is encountered in voice 1, the beat number where this has +occurred would be stored in an array, along with a pointer +to the dynamic indication string. For all other voices, +the DYNAMIC feature would be ignored but instead the +beat number would be compared with the beat number where +the dynamic indication occurred and dodeferred would be +called when the beat number equals or exceeds the numbers +cached away for voice 1. + +Worked on this project is deferred for the present time. + +February 05 2005 + +Abc2midi tie bug: + +For the file +X:1 +T: tie bug +M: 2/4 +L: 1/8 +K: G +[FA]-[FA] FA| + +abc2midi fails to tie the F# note. + +Fix: +replaced the line 737 (in removefeature) in store.c +pitchline[i] = pitch[i+1]; +with +pitchline[i] = pitchline[i+1]; + + +February 12 2005 (also see June 13 2005) + +Michele reports the following bug in the function dotie +in store.c. For the following tune, + +% +X: 1 +T: Tie bug +M:C +L:1/4 +K:D +[V: 1] | f/e/g/f/-f2 | +[V: 2] | d3/2 d/-d2 | + +abc2midi returns the message +Error in line 7 : Could not find note to be tied. + +The message is wrong, since abc2midi handles both +ties correctly. + +Michele added the conditional break statements + if(localvoiceno != voiceno) break; +after case TIE: and after case CHORDON: + +which seems to fix the problem. + +Analysis: The function dotie is a real birds nest of +code. Here is a description of how it works. +Dotie is called by tiefix when a TIE feature is +encountered. It has two parameters, j the index +in the feature array where TIE was encountered and +xinchord, a flag indicating whether the TIE is +enclosed in a chord (eg [A-B] A). The reason for the +complexity of the code is because the function dotie +is controlled by three semaphores tietodo, done, +and tied_denom. To start, dotie searches backwards +for the note preceding the tie, and calls its address +(in the feature space) tienote. It changes +feature[tienote] from NOTE to TNOTE. It changes +feature[j] from TIE to REST and sets the rest length +to that of tienote (so they are both the same). +Finally it sets the semaphores +done = 0; tied_num = num[tienote]; tietodo = 1; +which controls the stopping conditions of the following +while loop that searches for the following note to be +tied to tienote. Now the fun begins. To simplify things +assume we do not have chords. The loop begins with the +variable place set to j, the original position of the TIE +now converted to a rest. So the first feature in the loop +is guaranteed to be a REST. case REST: subtracts +the length of the rest from tied_num so it is back to zero. +Now the semaphores are +done = 0; tietodo = 1; tied_num = 0; +The loop variable place is incremented and now feature[place] +probably points to a NOTE. Case NOTE: since tietodo is not +zero the function compares the pitches (pitchline) of +place and tienote. If they are equal, the tienote length +is increased by the place note, the tied_num semaphore +is also increased by the place note. Feature[place] is changed +from a NOTE to a REST and to make things more confusing, +if we are not in a chord the length of tied_num is now +decremented by the place note so that it is back to zero. +Finally the tietodo variable is also set to zero indicating +that we have finally joined the two notes in the tie. The +semaphores are now: +done = 0; tietodo = 0; tied_num = 0; +Unfortunately the while loop does not stop here and this +is the reason for the spurious error message described above. +In order for the while loop to stop, the variable done must +be set to a nonzero value. This usually happens when the +next NOTE or REST is found. In the above example, the +next note is found in a different voice. + +The remedy is probably to end the while loop when tietodo is +zero. However, since the code is working fine now I am +rather reluctant to try it in case another bug surfaces. + + +Feb 13 2005 + +Abcmidi /abcm2ps incompatibility problem for decorations +applied to chords. It is perfectly normal to apply a +fermata or a staccatto to a chord, eg H[C2E2G2] or +.[CEG]; in fact abcm2ps prefers that you do it this way +rather than [.C.E.G]. Abc2midi handles both notations +correctly but it sends the following warning message if you use +the former convention. + +Warning in line 6 : decorations applied to chord + +Nevertheless, abc2midi sends the chord decoration to each +note in the chord and everything works fine provided you +don't attempt to apply roll, trill or ornamentation +to a chord. In the later case you receive an error message +and the decoration is not applied. It is therefore preferable +that parseabc does not produce this warning when abc2midi +is running. + +Fix: it is convenient if parseabc.c knows which program +is running (i.e. abc2midi, abc2abc or yaps). A new typedef +programname which distinguishes ABC2MIDI, YAPS, and ABC2MIDI +was added to abc.h. A programname variable called "program" +was added as a global variable to store.c, yapstree.c and +toabc.c and set to proper value. The program variable is +linked to parseabc.c as an extern global. This variable +is used to fine tune parseabc.c. + +Unfortunately not everything is well with yaps and abc2abc. +Like abc2midi, the chord decoration is applied to every +note in the chord. In the case of yaps, this does not produce +an aesthetically pleasing result. Since yaps is not the +preferred postscript converter and I am also not very +knowledgeable of its internals, yaps shall remain as it +is and the warnings serve a useful purpose. In the case +of abc2abc, it is not desirable that it automatically +converts H[A2C2E2] to [HA2HC2HE2] or something similar. +A few more changes are necessary. + +It was necessary to introduce a new parameter (chorddecorators) +into the function event_chordon. This entailed making changes to +parseabc.h, parseabc.c, store.c, yapstree.c and toabc.c. +In store.c and yapstree.c the new parameter is not used; +however, in toabc.c extra code was added to event_chordon +to print out any decorations applied to the chord. In parseabc.c +the decorators were not inherited from the chorddecorators +when parseabc.c was linked to toabc.c. + +Unfortunately event_chordon is also called by the function +event_chord which handles the obsolete form of chords ++CEG+. For store.c, yapstree.c and toabc.c, I introduced +a global array dummydecorators[DECSIZE] which is initialized +to zero's in event_init. This array is used in event_chord. + +February 14 2005 + +Abc2abc prints garbage in the V: field (reported by Hudson Lacerda). +Given a normal file : + +X:1 +T: abc2abc V: bug +M: 4/4 +L: 1/8 +K: C +V: 1 +CDE FGABC| def gab c'2| +V: 2 +C8|C8| + +abc2abc outputs + +X: 1 +T:abc2abc V: bug +M:4/4 +L:1/8 +K:C +V:1 name=(LI +CDE FGABC| def gab c'2| +V:2 name=(LI +C8|C8| + +Analysis: the local variable gotname in the function +parsevoice in parseabc is never initialized to zero. +The problem was fixed by adding +gotname = 0; + + +February 21 2005 + +Microtone note capability has been introduced into abc2midi. +A _/ means lower the pitch of the following note by a half a semitone. +A ^/ means raise the pitch of the following note by a half a semitone. +The microtone notation does not propagate across a measure but +applies to only the immediate note. For chords in the same channel +(voice), the microtone will apply to both notes no matter +how it has been notated. For example [C_/E] is the same as +[_/C_/E]. + +Following the convention in abcm2ps, (see features.txt in abcm2ps +distribution), _3/4C will depress C by 3/4 of a semitone. It is +assumed that the pitch range of the MIDI synthesizer pitch wheel +is + or - two semitones in compliance with the General MIDI +specifications. The maximum permissible pitchbend is therefore +2 semitones. + +Implementation: added a new function ismicrotone() called by +parsenote() in parseabc.c. I also introduced functions +event_microtone() and event_normal_tone() in store.c, yapstree.c +and toabc.c. There has been no change to the operation of yaps +or abc2abc. + + +February 26 2005 + +Finished microtone implementation and added microtone +documentation in abcguide.txt. + + +March 12 2005 + +Abc2midi: There is a loss of synchrony in multivoiced files +when a fermata is applied to notes of unequal lengths. For +example: + +X:1 +T: Fermata +M:2/4 +L:1/4 +K: G +V:1 +cdef|B2 Hc2|gabc| +V:2 +efga|DHe3|gabc| + +the fermata is applied to c2 and e3 for voices 1 and 2. The fermata +doubles the length of the notes c2 and e3 and there is a loss of synchrony +between the voices in the next bar. + +Solution: I introduced new MIDI commands which control how the +fermata is applied. +%%MIDI fermatafixed +The fermata adds a unit lengths to the note so HC2 is played C3. +%%MIDI fermataproportional +(default) the unit length is doubled so HC2 is played C4. + +Implementation: added new global flag fermata_fixed and modified +event_specific to set this flag. Modified FERMATA treatment +in event_note and event_rest. + + + +March 18 2005 + +Microtones in abc2midi. It is not clear whether the microtone +notation should be treated as an accidental or a decoration. +The abc2midi software treats it as a decoration. Thus in the +following: + +X:1 +T:micro +Q:60 +K:C +=C ^/C ^C _/D D _/D ^C ^/C =C + +the second to last note ^/C is played as ^^/C since the +accidental in the previous note propagates across the measure. +If you want =^/C you must specify it in this manner. +If ^/ and _/ satisfy the rules of accidentals then, +they would be interpreted the same way as double sharps and +double flats. Thus if you wrote ^^F E ^F G: the first note +would be played as G and the third note would be played as +F#. (You would not write ^^F E ^=F G.) It is not clear from +the abc standard, the meaning of the following: +[K: G] ^/F D E G| +Is the first note a F natural raised a quarter tone, +or is it a F# (as indicated by the key signature) raised +by a quarter tone? Presently abc2midi treats it as the +latter. + +To treat the notation as accidentals would mean that the +quarter tones would propagate across a measure like sharps +and flats. This would require introducing more code into +abc2midi. (Further there would be other issues relating +to transposition in abc2abc.) + +March 19 2005 + +abc2midi optional guitar chord syntax. The function +event_handle_gchord in store.c was modified to ignore +the parentheses in the guitar chord. (eg. "(C)" CDEF etc. ) +The optional guitar chord is played. + + +March 25 2005 + +abc2midi: note tied to two notes. In the following sample +the tied note is not played correctly in the repeat. + +X:1 +T: note tied to two notes +M: 2/4 +L: 1/8 +K:G +%%MIDI program 73 +|:G2D2|ABCD-|[1 D4 :|[2 D2 G2| + +Unfortunately this is a difficult problem to fix. Store.c +creates a feature/pitch/num/denom arrays which tells writetrack +in genmidi.c how to create the MIDI file. Repeat actions are encoded +into the feature array using the instructions BAR_REP, REP_BAR, +PLAY_ON_REP, etc, which instruct writetrack to backtrack +in the feature array and repeat certain sections. In other words +the repeats are not expanded until writetrack creates the MIDI +track. Tied notes are handled by the function dotie in store.c +that determines which notes are tied and combines the tied notes into +one note instruction in the feature array. In the above example, the +tied note D-D4 in the first repeat and D-D2 in the second repeat +have different durations. Dotie can only assign the D tied note +one duration so it will be wrong in one of the repeats. To +make things worse the code in dotie is unmanageable (see +comments February 12 2005). + +To fix the problem the joining of ties, it would need to be +done at the time that the repeats are expanded in writetrack +rather than in a separate pass performed by dotie in store.c. +The handling of ties is messy because they can also be embedded in +chords; they cross barlines introducing problems with accidentals +in music notation; interleaving of voices breaks up ties; we want +abc2midi to gracefully handle tie syntax errors provide useful +error message. Multiple repeats (eg |...|[1...|[2,3...|[4... :|) +introduce another headache. + +One way of avoiding this problem is to notate the above sample +differently as shown below. + +X:1 +T: better way of handling tied notes in repeats +M: 2/4 +L: 1/8 +K:G +%%MIDI program 73 +|:G2D2|[1 ABCD-| D4 :|[2 ABCD-| D2 G2| + +There is now five bars instead of four, but it avoids the above +problem. + + + +Abc2midi: an alternative method for embedding %%MIDI commands. + +The syntax for placing %%MIDI instructions in the abc file +requires that each command occupies a separate line in the +abc file. This makes the resulting file look messy when +you want to do drumon, drumoff, gchordon, gchordoff, in the +middle of a line. The problem gets worse when the abc file +also has lyrics included using the w: field command. + +It has been suggested that there should be an option +to place MIDI instructions in the information field: +eg.[I: MIDI drumon]. Abc2midi does have provision +to parse inline I: fields using the function event_info. +However, the code expects the field satisfy a specific +syntax of the form [I: key1 = value1 key2 = value2 etc.] +Thus you specify as many keys as you wish in the +I: field. + +So far I have modified the function event_info_key in +store.c so that it will now forward any info field commands +of the form [I:MIDI = stuff] to the function event_specific +which handles all %%MIDI commands. Thus you can now do +the following. + +X:1 +T: event info used for MIDI +M:4/4 +L:1/4 +K:G +[I: MIDI = program 70] DDEE|[I:MIDI=program 42] GEFG| + +instead of + +X:1 +T: event info used for MIDI +M:4/4 +L:1/4 +K:G +%%MIDI program 70 +DDEE|\ +%%MIDI program 42 +GEFG| + +Any %%MIDI command described in abcguide.txt may be embedded +in the I: field; however the '=' is very important. Otherwise +abc2midi will assume this field is just for the user's +interest and just ignore it. Here is another example: + +X:1 +T: event info used for MIDI +M:4/4 +L:1/4 +K:G +[I: oboe MIDI = program 69 MIDI = gchord fzcz MIDI = chordprog 1] BAG2|\ +"G" EC GG|[I:MIDI= bassprog 100] DDDD|[I: MIDI =gchord ffffffff] G4| + + + +March 28 2005 + +Acciaccatura grace note notation. Abcm2ps compatibility feature. +Abc2mps accepts the notation {/b}a where the slash before the +b tells it to display the grace note b as an acciaccatura. +Parseabc.c does not understand this notation and returns an +error message "Unrecognized character /". + +Fix: parseabc.c was modified to keep track whether it is inside +a grace sequence using a new global variable ingrace. When +the function parsemusic encounters a / that is not a note length +indicator, it will call event_acciaccatura if ingrace flag is +set. This function does nothing in abc2midi and yaps but it +prints the / character in abc2abc. + + +April 02 2005 + +Abc2midi does not handle microtones properly in multivoiced +files. For example in, + +X:3 +T:Miudezas +C:Hudson Lacerda +M:none +Q:1/8=132 "ca." +L:1/8 +K:none clef=treble +V:1 name="Clarineta em Sib" +{=B}_/G {=B}^g | {=B}^F {_/e}=B {_/e}^/c' |\ +{_/e}_/G {_/e}_/d' {=a}_/e | + +the first note B (grace note) was affected by the microtone which was +intended to be applied on the second note G. + +Analysis: Multivoiced files (i.e. using V:1, V:2 etc.) place a +header track (track 0) in the MIDI file where global DYNAMIC +features such as %%MIDI program may be defined for all other +voices.Since the microtone uses the %%MIDI pitchbend, it +is also treated as a DYNAMIC feature. As a result the header +track contains many pitchbends but no notes. This unfortunately +handles all other notes in channel 0 in a random fashion. + +Fix: a new parameter, noteson, was introduced into the function +dodeferred which handles all DYNAMIC features. Noteson is +also a local variable controlled by writetrack to specify whether +NOTE features are to be processed by writetrack. This flag +is now also used by dodeferred to determine whether pitchbend +MIDI commands are to be inserted. + + +April 07 2005 + +Introduced a new feature to midi2abc. Midi2abc.exe -mftext +will now produce a mftext output of a specified input MIDI file. +It was preferable to build mftext into midi2abc since I +changed the output format; also runabc already links to too +many executables and I would not like to keep track of version +numbers for another program. + +April 09 2005 + +I have modified toabc.c (abc2abc) so that it will no longer +transpose voices assigned to the drum channel (%%MIDI channel 10). +Implementation: added a new entry, drumchan, in the voicetype +structure which indicates whether this voice is to played +on drums. Also added a new global, drumchan which is linked +to voice.drumchan for the currently active voice. The event_specific +function has been extended to catch %%MIDI channel 10 and +update drumchan. The function setvoice() initializes voice[].drumchan +to 0 when a new voice is created. The functions event_note1 and +event_note2 now check the drumchan flag before transposing the note. + +April 10 2005 + +Abc2abc - abcm2ps compatibility issue. Abc2abc does not recognize +the sname= "...". Fix: introduced new function parsesname in parseabc.c +added new parameters to event_voice in parseabc.c, store.c, +yapstree.c and toabc.c. (See September 26 2004 in this file +for more details.) + +April 15 2005 + +Midi2abc: fixed problem causing midi2abc to crash when the +MIDI command indicating the time signature is missing from the file. + + +April 22 2005 + +Abc2midi: pitchbend inside a tied note. In the following +example, the third note is held too long. + +X:1 +T: bends +M: 2/4 +L: 1/8 +K: G +%%MIDI program 60 +G4|G4|G2-_/G2|G4| + +Fix: in function dodeferred() (genmidi.c) for command == pitchbend, added + tracklen = tracklen + delta_time; + delta_time = 0L; +after write_event(pitch_wheel, chan, data, 2); + +Also listen to the example 11 in demo.abc. + + +April 23 2005 + +Abcmidi: introduced two more MIDI commands. +%%MIDI portamento n +turns on the portamento controller on the current channel and +sets it to n. n is a 7 bit number which specifies the rate +slides the pitch between two notes. (Unless you are composing +20 th century classical music, you may not wish to use this +feature. Avoid slides between large pitch intervals.) + +%%MIDI noportamento +turns off the portamento controller on the current channel. + + +April 24 2005 + +Integration of abcmatch into abcmidi package. The main() function +in parseabc.c was moved into store.c, yapstree.c, and +toabc.c .The function parsetune was placed in parseabc.c. +All makefiles were updated. (I cannot verify all of them; +report any corrections to me.) The files abcstore.c and abcparse.c +are no longer needed; delete them if they are lying around. + +April 29 2005 + +Cleaned up all the compilation errors that occur in +Microsoft Visual C version 6.0. + + + +May 03 2005 + +Abc2midi abcm2ps compatability feature: +add new %%MIDI command + +%%MIDI beatmod n +where n is a positive or negative integer. + +The command will increment (decrement) the loudness of the +on beat, off beat and other notes by the amount n. + +Introduced new instructions: + !<(! or !<)! or !crescendo(! or !crescendo)! which act like +%%MIDI beatmod 15 +Also + !>(! or !>)! or !diminuendo(! or !diminuendo)! act like +%%MIDI beatmod -15 + +Thus a pair of !<(! and !<)! does two loudness increments. One +at the beginning of the crescendo and one at the end of the +crescendo. This is not a gradual change but it is better than doing +nothing. + +If the default beatmod value (15 or -15) is not ideal, you can +change it using +%%MIDI deltaloudness n +where n is a positive number. + + +Sample test file below: + +X: 1 +T: crescendo +M: 2/4 +L: 1/8 +K: G +%%MIDI deltaloudness 20 +!mf!cdef|edcB| +!<(! cdef|!<)! edcB|AAAA| +!>(! cdef|!>)! edcB|AAA| +!crescendo(! cdef |!crescendo)!|edcB|AAA| +!diminuendo(! cdef |!diminuendo)!|edcB|AAA| + +Implementation: updated dodeferred in genmidi.c, added global +velocitychange in store.c and new code in event_specific and +event_handle_instructions. + +abcguide.txt and abc2midi.1 documentation were updated. + + + +May 06 2005 + +It has been suggested that some abc2midi options could be global +when they are used outside of a tune. For example: + +%%MIDI chordname +%%MIDI ratio +%%MIDI beat +%%MIDI program + +It is rather difficult to add this feature since the handling of +these options is not centralized but spread out in the store.c +and genmidi.c code. Some of these options apply to specific voices +which do not get instantiated until the voice is defined in the +tune. This makes the full implementation rather formidable. + +I have introduced new code event_specific_in_header in store.c +that attempts to handle some of the MIDI directives. Many of +the MIDI directives send information to the feature[] array +which does not exist prior to parsing the tune. I have not +attempted to handle those directives. Presently, the only +MIDI commands that will be recognized outside the tune are + +%%MIDI C +%%MIDI nobarlines +%%MIDI barlines +%%MIDI fermatafixed +%%MIDI fermataproportional +%%MIDI ratio +%%MIDI chordname +%%MIDI deltaloudness + +All other MIDI commands outside the tune are ignored and will +produce the warning "cannot handle this MIDI directive here". + +The following is a sample test file. + +%MIDI C 48 +%%MIDI nobarlines +%%MIDI ratio 5 1 +%%MIDI chordname ugly 1 2 3 4 +X: 1 +T: test global settings +M: 2/4 +L: 1/8 +K: C +"G"CDEF|"Gugly" D>EF>C|^ABDA|AAC2| + + +May 08 2005 + +Abc2midi: voice splitting. +In some pieces of music a voice splits in two or more voices only +in some measures. The new abc standard (and abcm2ps) provides +a syntax for splitting a voice in a bar using the & symbol. +When placed within a measure, it splits the current voice and +attributes the notes that follow to the second voice. + +Voice splits are handled by creating separate voices which +are in turn converted into separate MIDI tracks. + +To implement this feature, new variables were introduced into +the voice structure defined in store.c +int nbars; /* counts number of bars processed in voice */ +int tosplitno /* points to new voice to handle split */ +int fromsplitno /* points to voice initiating the split */ +Both tosplitno and fromsplitno are intialized to -1 implying +that a split voice does not yet exit. +In an event of a split, tosplitno points to the new voice to go to. +If it is -1, a a new voice needs to be created, and fromsplitno +in the new voice is set to the voice from which initiated the split. + +In order not to confuse the new voice number with a voice number +generated by a V: field, the split voice numbers start from 32. + +Global variables in store.c were introduced. +int numsplits; /* keeps track of the number of split voices generated */ +int splitdepth; /* keeps track of the number of splits in a bar */ + +A new function event_split_voice in store.c is called by parsemusic +in parseabc.c when a '&' is encountered in a music line. + +A new function resync_split_voice adds bars of rests into the +split voice so that bar is in the right position. + +A new function complete_all_split_voices ensures all split +voices are the right length in order to avoid annoying messages +like: + +Warning in line 7 : Track 2 is 3840 units long not 4800 + +A new function recurse_back_to_original_voice is called to +recover from a split when a new bar line is encountered (see +event_bar). + +Sample test file: + +X: 1 +T: testing voice split +M: 2/4 +L: 1/8 +K: G +A4| G4 & e2g2|BGEE|CAEE & d2f2|F2G2| + + +May 12 2005 + +Wrote a new function dumpfeat(n1,n2) in genmidi.c which +prints out the contents of the feature,pitch,num,denom array +between n1 and n2. The function is usually called in the +debugger after stopping at a breakpoint in finishfile. + + +May 13 2005 + +Abc2midi split voices: Problems occur when the music contains +repeats. It is necessary to transfer the repeats to the split +voice. The function event_bar checks for any repeat symbols. +There are two cases. If we are already in a split voice then +(eg. abcd & defg :|) +we have to propagate the repeat back to the original voice +while recursing back. If we are not in a split voice but +we know that this voice does link to split voices, then we +(eg abcd & defg |abcd :|) need to propagate the repeats +downwards to the all the split voices. + +The function event_playonrep is also called by the parser +and needs to check for split voices. + +May 14 2005 + +Now there is still another problem: the parser might encounter +a repeat symbol before it knows that this voice splits. We must +find a way of getting those repeat codes into the newly created +split voice. Solution: a new function start_new_voice_and_sync is +called when a split voice is first created. It scans +the parent voice copying rests and various types of barlines +and repeat codes into the feature array of the newly created voice. +If it encounters a %%MIDI program, that is also copied. This way +the new voice also inherits the same music instrument as its parent. + +If you wish to change the instrument of the split voice, you +can do it this way. +C2 EF & [I:MIDI= program 10] F2 D2| +The new instrument will apply to all following bars of the +split voice. + +Abc2abc was made split voice compliant. + + + +May 19 2005 + +Midicopy: will now return the playing time of the extracted segment. +This only works when a segment is extracted using any combination +of the -from and -to runtime parameters. Otherwise it returns 0.0. +The program makes adjustments for any tempo changes that may occur +inside this segment. + +May 21 2005 + +Corrected a bug in midi2abc. It was returning the time in seconds +instead of beats when running with the -mftext option. + +May 22 2005 + +Midicopy: for some reason the meta command mf_write_tempo (which +originated from midifile.c) alway writes delta_time 0. As a result +all tempo meta commands are at the wrong time. When this was changed, +tempo changes seem to be handled better. + +Midicopy now caches all tempo changes in a array of structures +called tempo_array. This is used to update the current_tempo +when other tracks (not containing tempo commands) are processed. +The correct tempo is needed in order to get an accurate estimate +of the playing time of the output file. A new function +update_current_tempo is called each time Mf_currtime is updated. + + +May 28 - 31 2005 +June 04-06 2005 + +Midi2abc often produces a mess for piano music sequenced into a +single track. There are many chords played by the left hand and +the right hand usually has a different rhythm. Midi2abc tries +to place all notes sounding at the same time into a single chord. +To handle notes of different durations, some notes are tied to +the next chord and others are not. The resulting output looks +something like this. + + +X: 1 +T: Scarlatti, sonata 1 +%***Missing time signature meta command in MIDI file +M: 4/4 +L: 1/8 +Q:1/4=120 +% Last note suggests Phrygian mode tune +K:F % 1 flats +% (C) John Sankey 1998 +z/2d/2 (3efga/2-[a/2A/2] _d/2A/2[=d/2-D/2][d/2-E/2]\ + [d/2-F/2]d/2-[d/2-G/2][d/2-A/2]| \ +[d/2A,/2][e/2-_D/2][e/2A,/2][f/2=D/2-] [d/2D/2]z/2[g/2E/2-][e/2E/2]\ + [a/2F/2-][f/2F/2][e/2G/2-][d/2G/2] [_dA]z/2[a/2-A/2-]| \ +[a/2A/2][b/2A/2-][b/2a/2A/2] +etc... + + +Converting it to PostScript file produces something very difficult +to read. Ideally the notes played by the different hands should +be separated into two tracks. Chords should avoid internal tied noted. + +The abc standard contains the provision for splitting the notes +in a single bar into separate voices. This should provide a means +of simplifying the output. + +A new runtime parameter -splitbars was introduced, producing +an output similar to below. + +X: 1 +T: Scarlatti, sonata 1 +%***Missing time signature meta command in MIDI file +M: 4/4 +L: 1/8 +Q:1/4=120 +% Last note suggests Phrygian mode tune +K:F % 1 flats +% (C) John Sankey 1998 +z/2d/2 (3efga zd3- & \ +z3A/2_d/2 A/2=D/2 (3EFGA/2A,/2 &\ +d/2efgazd/2 z2| \ +(3ef/2d/2z/2Ea/2f/2Gz2z/2 (3b/2a/2b/2 &\ +EF GA A,_D/2A,/2 =Dz/2g/2& \ +z3e f/2d/2z/2Ea/2f/2G/2-| +b/2a/2b/2 etc.... + + +Implementation: +Separating the parts is complicated and incorporating these algorithms +into midi2abc.c was even more difficult. The anote structure was +extended to contain two new values. Posnum stores the position +of the start of the note in xunit units. Splitnum assigns the +note to one of several split voices. New functions label_split_voices +and label_split scan the entire track and separate all the notes +into separate parts when necessary. A note is assigned to an +existing part if it follows the previous note or forms a chord +matching the length of the previous note. Otherwise, label_split_voices +searches for another active part satisfying this criterion. +If there is no active part available, the note is put into a new +part. Bar lines are ignored at this stage. Once all the notes +are labeled into separate parts, the xnum value associated with +the notes are updated so they indicate the number of units to +the next note in the same part. + +A new version of printtrack called printtrack_with_splits was +created from the printtrack code. In order to use as much of +the original printtrack code, it make multiple passes through +the same bar whenever the bar contains notes from different +parts. In each pass a single part active in this bar is processed +and printed. + +The code is barely working and is still experimental. +It will probably not produce correct results for complicated MIDI files. +Fortunately most MIDI files have proper chords and do +not require this feature. + + +June 04 2005 + +A problem with abcmatch.c causes it to return a bad xref number +after processing the last tune in the file. This causes +runabc.tcl to report an error similar to +Error: can't read "tuneid(84)" :no such element in array. +when running extras/grouper. The problem is that the notes variable +in abcmatch.c does not get initialized to zero if parsetune() +fails because it encounters an eof. To fix the problem, +the function startfile() in matchsup.c is made global instead +of static and it is called prior to calling parsetune() in +abcmatch.c. + +June 10 2005 + +Midi2abc -splitbars: fixed segmentation error which occurs +for tracks not containing any notes. + + +June 13 2005 + +Abc2midi: "Time mismatch at tie" error when chord length +declared outside of chord. + + +X:1 +T: multiple tie +M: 2/4 +L: 1/8 +K:C +[CE]/2-[CE]/2-[CE]|[CE]/2-[CE]/2-[CE]| +K: G +[C-E-]/2[CE]/2 [F2D2] [FD]| +[C/2-E/2-][C/2E/2] [F2D2] [FD] | + +Abc2midi does not tie notes correctly in the above example. +The chord extensions in November 4 2004 and December 12 2004 +do not work correctly in combination. The problem occurs +in the function dotie in the lines + case CHORDOFF: + case CHORDOFFEX: + if(localvoiceno != voiceno) break; + inchord = 0; + /* subtract time from tied time */ + addfract(&tied_num, &tied_denom, -num[place], denom[place]); + break; +after addfract subtracts num/denom from tied_num/tied_denom, tied_num +should be zero. However, tied_num/tied_denom was not yet adjusted +by fix_enclosed_note_length, so tied_num/tied_denom is not equal +to num[place]/denom[place]. Since dotie finds tied_num to be +non-zero in code + /* tie in note */ + if (tied_num != 0) { + event_error("Time mismatch at tie"); + }; +it thinks that the notes inside the chord have unequal lengths +and reports the time mismatch error. Furthermore, fix_enclosed_note_length +is eventually called after the notes were tied making a further +mess. + +Fix: Instead of calling fix_enclosed_note_length in a separate +pass during tiefix, fix_enclosed_note_length is called during +the parsing stage whenever a CHORDOFFEX feature is added (see +event_chordoff). The variable nochordfix is now redundant and +removed from the code. This guarantees that dotie sees the +correct note lengths inside the chord. + +June 14 2005 + +Abc2midi: chord ties. In the following example, + +X:1 +T: multiple ties +M: 2/4 +L: 1/8 +K:C +[CE]/2-[CE]/2-[CE]-|[CE]/2-[CE]/2-[CE]| + +The E notes are not joined. + +Fix: the function call patchup_chordtie was moved from +tiefix to event_tie. + +In addtoQ (queues.c) a check for negative delay caused +by apeggiate code + + Q[*ptr].delay = Q[*ptr].delay - wait -notedelay; + if (Q[*ptr].delay < 0) Q[*ptr].delay = 0; + +was added. + + +June 17 2005 + +Midi2abc: fixed bug in -splitbars causing program to go +into an endless loop and various other bugs. + + +June 25 2005 + +Midicopy: added line void WriteVarLen() in function mf_write_tempo +to be compatible with the new gcc compiler. + +June 25 2005 + +Abc2midi: tieing repeated notes inside chords. Abc2midi returns +a "Time mismatch at tie" error message for the following file. + +X: 1 +T: tie +M: 2/4 +L: 1/8 +K: C +[CC]-[CC]-[CC]z| + +Analysis. The line is converted to +[C-C-][C-C-][CC]z| and the function dotie attempts +to tie C to the next note it sees which is the next C +inside the same chord. This changes the length of the +note in the chord leading to the above error message. +Fix: a new variable samechord is introduced. When it is +set to 1 it signifies that we are in the same chord where +the tie mark - was placed, we do not link the tienote to +any notes in that same chord. The flag samechord is cleared +whenever we leave the chord (CHORDOFF or CHORDOFFEX). +It is set again whenever a tie mark occurs inside a chord +is encountered. + +Please note: a tie only connects one note. +Therefore C-[CC] will tie C to only the first +C in the chord. + +June 26 2005 + +Abc2midi does not correctly handle more than one bar split. +In the following example, + +X: 1 +T: testing voice split +M: 2/4 +L: 1/8 +K: G +%%MIDI program 24 +A4 & c4 |G2F2 & BBDD & E,,4| + +E,,4 is played in the first bar coincident with A4 instead +of the second bar. + +Analysis: various bugs caused abc2midi to fail with more than +one split. locate_voice() must use voice indexno rather than +voiceno. start_new_voice_and_sync must pass the voice +indexno rather than voiceno to locate_voice(). + + +June 27 2005 + +Midi2abc: changed name of parameter -usesplits to -splitbars. +Added new parameter -splitvoices which eliminates non homophonic +chords (ie. polyphonic) by splitting entire voices. Implementation: +added new function printtrack_split_voice to midi2abc. + +June 28-30 2005 + +Midi2abc: fixed numerous bugs in printtrack_split_voice() +and printtrack_with_splits(). + +July 02 2005 + +Abcmatch: upgraded the handling of chords and ties to be +compatible with abc2midi. + +July 09 2005 + +Abcmatch: added an option to ignore simple bars. + +Midi2abc: withdrew -Midigram option and replaced it with -midigram. +Note onset and offset time are now printed in MIDI time units rather +than quarter notes units. + +July 14 2005 + +Abc2midi: voice split causes infinite loop when play on repeat +(eg [1 or [2) specified. For the following file + + +X:1 +T:reproduce the bug in a smaller file +C:H. C. L. Smith +L:1/4 +M:1/4 +K:C +D|:C|[1F:|[2F|E&C|| + +abc2midi emits the following error message in an endless loop. + +Error in line 8 : Bad variant list : reproduce the bug in a smaller file +Warning in line 8 : Bar 2 has 2 units instead of 1 +Error in line 8 : Bad variant list : reproduce the bug in a smaller file +Warning in line 8 : Bar 2 has 2 units instead of 1 +Error in line 8 :.... + +Analysis: when writing the voice split in bar E & C||, the function +inlist (in genmidi.c) fails to get the repeat on repeat number (eg [2)) +which was set for top level voice but not for the split voice. + +Fix: the problem was traced to the function start_new_voice_and_sync +in store.c. It copies the repeat BAR feature (SINGLE_BAR, DOUBLE_BAR, +etc..) to the split voice but for the PLAY_ON_REP feature it must +also copy the pointer to the part number stored in denom[]. Now +both feature[j] and denom[j] are both copied for all bar type features. + +July 15 2005 + +The above file exposes yet another problem leading to a loss of +synchronization between the voices. The first indication that there is +still something else wrong are the messages. +Warning in line 8 : Bar 2 has 2 units instead of 1 +Warning in line 8 : Bar 3 has 3 units instead of 1 in repeat +Warning in line 8 : Track 2 is 4320 units long not 2880 + +When playing the output MIDI file, the note C in the split +is played two bars late extending track 2. + +Analysis: +A play on repeat symbol is always preceded by a bar or repeat bar +(ie. | or :|). The function start_new_voice_and_sync treats the play +on repeat symbol as another bar line and inserts a rest to complete +the bar when in fact, it should just insert a PLAY_ON_REP. +Since this bar is played twice, the C note comes two bars late. +Treating PLAY_ON_REP as a separate case fixed the problem. + +July 17 2005 +Abc2midi: voice split synchronization error when not all measures +are equal in length. In the following file, the tune begins +with an incomplete measure. + +X:1 +T: anacrusis +M: 2/4 +L: 1/8 +K: F +AG|Fc Fc| d2 e2 & B2 c2| + +Analysis: start_new_voice_and_sync unfortunately assumes that +every measure contains 2 beats. Fix: the function now counts +the number of beats in each bar it processes. + + +Abc2midi: MIDI attributes inheritance. As discussed in May 14, 2005 +split voices inherit the MIDI characteristics from their ancestor. +The following file does not work as expected. + +X:1 +T:inherit 1 +M:4/4 +L:1/16 +Q:1/4 =20 +K: C +%%MIDI channel 2 +%%MIDI program 2 50 +B2G2A2B2 EDEF EGFA & z2E4 D2 C8|] + +The split voice z2E4 ... is played on the Acoustical Piano (program 0) +instead of the synthetic strings. + +However the following file works correctly. + +X:2 +T:inherit 2 +M:4/4 +L:1/16 +Q:1/4 =20 +K: C +%%MIDI program 50 +B2G2A2B2 EDEF EGFA & z2E4 D2 C8|] + + +Analysis: Each split gets its own voice and each voice gets +its own channel number unless it is changed explicitly. + +The above should be equivalent to +X:1 +T:inherit 1 +M:4/4 +L:1/16 +V:1 +%%MIDI channel 2 +%%MIDI program 2 50 +B2G2A2B2 EDEF EGFA| +V:2 +%%MIDI channel 2 +%%MIDI program 2 50 +z2E4 D2 C8 + +Unfortunately, the %%MIDI channel 2 did not propagate +to the split voice. Voice 1 was assigned channel 2 but voice 2 +still had channel 1 (writetrack automatically assigns the +first channel which is not in use). The bug was fixed by +ensuring the CHANNEL feature also propagates into the split voice. + +You may wonder why X:2 worked correctly. This is because +the MIDI program command without the channel indication applies +to whatever channel is currently active. + + +July 23 2005. + +Fixed bug causing midi2abc.exe to produce a segmentation error when +running with the -splitbars option. (Failed to save state +when doing a split voice context switch due to encountering +an end of track before an end of measure. As a result the restored +chordhead would point to the wrong place.) Added more +code around line 2480 in printtrack_with_splits in midi2abc.c. + + +August 13 2005. + +Abc2midi.exe does not handle correctly chords of the form +[CE]2 when embedded in a triplet. For example in the file, + +X:1 +T: triplet +M: 4/4 +L: 1/4 +K:C +(3C2 D2 [CE]2 | + +abc2midi produces an error messages + +Warning in line 6 : Different length notes in tuple +Warning in line 6 : Different length notes in tuple + +and the [CE] chord is the wrong length. + +Analysis: event_note processes the internal lengths +of the notes in a chord before it encounters the end +of chord marker (]) and it does not know that the +internal lengths may be adjusted externally after +the end of chord. It sees the wrong length, and +sends a warning. Event_chordoff fails to make an +adjustment for the triplet (tuple) so that the +function fix_enclosed_note_lengths sets the lengths +of the internal chord notes to the wrong length. + +Fix: event_note bypasses the tuple test (for triplets) +if the notes are inside a chord. The tuple test +was also added in event_chordoff. It adjusts the +setting of the note lengths (chord_n, chord_m) if +the chord is inside a tuple. If chord_n and chord_m +are not 1,1 then fix_enclosed_note_lengths is called. + + +August 13 2005 + +Abc2midi.exe has difficulty handling tied notes enclosed +in a slur. For example for the tune + +X:1 +T: slur 1 +M: 2/4 +L: 1/8 +K: G +(GB-B) C|(DEF) B| + +the following messages appear + +Warning in line 6 : Slur in abc taken to mean a tie +Error in line 6 : Bad tie: possibly two ties in a row +Error in line 6 : Cannot find note before tie + +Surprisingly, the output MIDI file is still correct. + +Analysis and fix: Abc2midi does almost nothing when it encounters +slurs. However, when it sees repeated notes inside a slur it +tries to tie them together. For example for (G B B), abc2midi +would try to tie the two B's together. This is the source +of the above problem. I do not think this is a very useful +feature so I have turned this feature off (in event_sluroff store.c). + +August 13 2005 + +The abc2-draft standard, +http://abc.sourceforge.net/standard/abc2-draft.html +has deprecated the !...! notation in favour of the +...+ +notation. In order to comply with the change, abc2midi, abc2abc +and yaps were modified to accept either convention. +Thus you can use +trill+, +fermata+ +pp+ etc. as well +as the deprecated notation (!trill! etc.). There is one conflict: +in the early days of abc notation chords were notated +as +CEG+ instead of [CEG]. There is probably very little +music using this old convention. If you need to handle the +old chord notation, you must now add the option -OCC to +abc2midi, abc2abc or yaps. + +Sample file: + +X:1 +T: decorations +M: 2/4 +L: 1/8 +K: G ++<(+ [CE]4 +<)+ |[CE] +trill+ DEF| +!<(! [CE]4 !<)! |[CE] !trill! DEF| + +Implementation: + +Introduced a new global, oldchordconvention into parseabc.c +which is linked externally to store.c, toabc.c and yaps.c. +If this global is unset (ie. 0), then parsemusic in parseabc.c +treats + and ! in the same manner. + + +August 17 2005 + +Added new run time parameters to midicopy -fromsec and +-tosec allowing you to select a section in terms of time +in seconds. + + +September 13 2005 + +Midicopy using the -fromsec option to select the start of the +output MIDI file causes the music to be delayed by the +the same amount of seconds. + +Analysis, the first note on (or note off) of the track has +a delta_time equal to the time of the first note in the +selected section of the original file. TiMidity has no problem +since it ignores this delay. Other MIDI players are less +compliant. + +This is a hard bug to fix properly when the tempo varies +across the MIDI file. For such files, it is recommended that +you use the -from and -to parameters and express the times +in MIDI tick (pulse) units. The program now computes +the right delay using the first tempo specification in the +MIDI file. + +I noticed that when midicopy truncates the beginning of +a file, a track may begin with a MIDI off command of a note +that has not been turned on. I don't think this causes +a problem. + + + +September 19 2005 + +Incorporated changes suggested by Mikhail Teterin into parseabc.c +and store.c to modernize the C code. This includes the replacing +of the functions casecmp(s1,s2) and stringcmp(s1,s2) with functions +built into the C compiler. If this causes any problems with +your compiler please notify me as soon as possible. Other +changes were added to make the code more efficient and eliminate +some warning messages. + + + +September 19 - October 8 2005 + +Abc2midi: another bug related to split chords was found. In the +following example + +X:1 +T: split test file +M: 2/4 +L: 1/8 +Q: 50 +K: D +CD |EF AB & CD FG| G2 | BD D2 & GB B2| + +The zero th and second bar are only one beat long. The fix described +on June 17 th handles the zero'th bar correctly but it does not +address the second bar since a different function resync_split_voice +is called to maintain synchrony. This function assumes all bars are +a fixed length as specified in the time signature. + +This was a difficult bug to fix since it required major changes +to the code. A new function sync_voice replaces the code for +start_new_voice_and_sync and resync_split_voice. A test file used +to debug these changes, split.abc, is included in the programming directory. +Hopefully, I will not need to return to this file many times. + + +October 8 2005 + +Abc2midi, yaps, abc2abc : extraneous warning "Slur within slur". +For the following example, + +X:1 +T: 2 slurs +M: 2/4 +L: 1/8 +K: C +V: 1 +C2 (C2 |\ +V: 2 +(A2 G2) |\ +V:1 +D2) E2| +V:2 +G4| + +we get the warning +Warning in line 9 : Slur within slur. + +Analysis, there are two overlapping slurs, but they are in +separate voices so this should be no problem. Parseabc.c +merely keeps a count of the number of open slurs with the +variable slur and does not note that they are associated +with specific voices. + +Fix: the warning message has been moved to store.c. + + + +October 9 2005 + +Abc2midi: grace notes are not applied correctly to a chord. +In the following example, + +X:1 +T: grace/chord +M:2/4 +L:1/8 +K:G +V:1 +D4|{c'}[g3b3] c|z2 G2| +V:2 +F4|G3 e|z2 D2| + +The length of the host chord [g3b3] is not adjusted correctly. +This results in a loss of synchronization between voice 1 and 2. +Analysis: several bugs related to host chords were fixed in +my new function applygrace_new() in store.c. The original code, +applygrace_orig was also fixed. + +October 10 2005 + +Updated makefiles/unix.mak. Cleaned up some of the -Wall warning +messages. + + +November 6 2005 + +New abc2midi feature for supporting drum tracks. Notes played on +MIDI channel 10 (counting from 1), are interpreted by the General +MIDI instrument as one of 47 percussion instruments (see abcguide.txt +for list). Unfortunately, notating the music in this manner is +rather awkward if you wish to convert it to common music notation +using abcm2ps. Usually, only a few percussion instruments are +used. To allow for better drum notation, you can alter the mapping +between notes and percussion instruments using the new +%%MIDI drummap command. For example for the tune: + +X:1 +T: illustrating drummap command +M: 4/4 +L: 1/8 +K: none +%%MIDI channel 10 +%%MIDI drummap E 36 +%%MIDI drummap G 38 +%%MIDI drummap _e 42 +|: E2 GE zE z2 & z_e z_e z_e z_e :| + +would be played on the percussion instruments +bass drum (36) +acoustic snare (38) +and closed hi-hat (42). + +Implementation: added new function parse_drummap() genmidi.c +which handles the %%MIDI drummap command. parse_drummap() +is called from the function dodeferred(). + +November 6 2005 + +Abc2midi: split voice does not propagate the octave shift +command. eg. + +X:15 +T: splits with octave=1 +M: 4/4 +L: 1/4 +K: G octave=1 +G A B C & E F G A| + +The notes E F G A are played an octave lower than intended. + +Fix: the v->octaveshift variable is passed to the +split voice in the function event_split. + + +December 08 2005 + +Abc2midi: the drummap feature illustrated on November 06 2005 +produces an improper MIDI file. eg. + +X:1 +T:unfinished +M:2/4 +L:1/16 +K:F +V:1 +%%MIDI channel 10 +%%MIDI drummap ^^g 72 % Long Whistle +%%MIDI drummap _a 58 % Vibraslap +^^gz _a2-_a4 |] + +midi2abc.exe unfinished1.mid -mftext + +Header format=1 ntrks=2 division=480 +Track 1 contains 40 bytes + 0.00 Metatext tempo = 120.00 bpm + 0.00 Metatext key signature F (-1/0) + 0.00 Metatext time signature=2/4 + 0.00 Metatext (Seqnce/Track Name) unfinished +Track 2 contains 35 bytes + 0.00 Metatext (Seqnce/Track Name) unfinished + 0.00 Note on 10 c5 105 + 0.25 Note off 10 a5 0 + 0.50 Note on 10 a#3 80 + 2.00 Note off 10 g#5 0 + +The note on's have the translated pitches but the +note off's have the original pitches. As a result +none of the MIDI note on's are properly terminated. + +For percussion instruments, this may not be noticeable +since a decay is already built in. However, some midi +players may complain. + +Fix: the function midi_noteoff in genmidi.c now checks for +for channel 10. + + +December 09 2005 + +Abcmidi: transposition should not be applied to the music +in channel 10. In the following example + +X:1 +T: drum transpose +M: 2/4 +L: 1/8 +K: G transpose=-3 +V:1 +FAFA|EFG2| +V:2 +%%MIDI channel 10 +%%MIDI drummap g 72 % Long Whistle +%%MIDI drummap a 58 % Vibraslap +agag|agag| + +The transpose=-3 changes percussion instruments. +Fix: a test for channel 10 is made before the call to noteon_data() +in the function noteon() in genmidi.c. Also in writetrack, a similar +test was applied before addtoQ in two places (NOTE: and TNOTE:). + + +December 17 2005 + +Abc2midi new feature: certain instruments such as an organ have +no greatly emphasized beat notes and sound unnatural when the beat +algorithm accents the down and off beats. To turn this feature use +%%MIDI nobeataccents +To turn it back on +%%MIDI beataccents +By default beat accents are turned on for any new tune. +Thanks to Mike Scott for contributing the code to genmidi.c + +Implementation: a new variable beataccents which acts as a +flag was introduced. + + +January 7 2006 + +I have started looking into the problem of adding the +split voice feature into yaps. In order for yaps to +handle split voices, it was necessary to introduce a new +feature code SPLITVOICE into abc.h. This had minor impact +on the debugging code for genmidi.c and matchsup.c. +Event_split_voice in yapstree.c now needs to insert a +SPLITVOICE feature. To avoid "unknown type" message +originating from sizevoice (in drawtune.c) it was necessary +to add a case statement for SPLITVOICE even though it does +nothing. To assist in debugging, the code in the showline +function was split into a new function showfeature in +debug.c. + +The real work is done in the function advance(..) in +the file position.c (see additions in programming/yaps.txt). +In order to allow spacemultiline to process all the notes +playing at the same time, major changes are necessary. We +want advance() to check a measure for splitvoices, and if +found process all the notes in the bar in the order that +they would be played. This means extending the voice +structure defined in structs.h so that it maintains +status information for v->tuplefactor, v->inchord, +v->place,v->time for all splitvoices and telling +advance() to handle the splitvoices in parallel. +This work is beyond me at the present time and +no further work was done. + +January 13 2006 + +abc2midi fails to tie note correctly in chord with +an augmented unison interval. In the following example + + +X:1 +T:A) Matching non-perfect primes +M:C +L:1/2 +K:C +[=D^D-] [=D^D] z +[=D-^D] [^D=D] z + +the D- tie and ^D- are done improperly. + +Analysis: In order to tie notes across bar lines where the +accidental is assumed, (e.g. A_B-|BD), the function dotie +performs the tie based on the pitch line (in the staff) rather +than the actual pitch. Unfortunately there are cases where we +run into trouble such as above. + +Partial Fix: dotie() has a new flag called newbar, which is set to +1 whenever a nonprocessed tie is followed by barline. The +pitchline[] test is now only activated when newbar is set. + +Unfortunately, this is not a complete fix. The same +problem reappears with this file for the second and +third lines. + + +X:1 +T:Matching non-perfect primes +M:2/4 +L:1/2 +K:C +[=D^D-]| [^D=D] | z2 | +[=D^D-]| [=D^D] | z2 | +[=D-^D]| [^D=D] | z2 | +[=D-^D]| [=D^D] | z2 | + +The feature array does not record whether accidentals +have been spelled out explicitly so further checks +cannot be done when applying ties across bar lines. +I recommend that one just changes the order of the +notes in the chord in order to get it to work. Fortunately, +this problem occurs rarely. + + +January 14 2006 + +Abc2midi fails to tie microtonal notes correctly. +In the following example: + + +X:1 +T: tied microtonal pitches +M:C +L:1/2 +K:C +C +^13/16C - ^13/16C +^13/16C ^13/16C +^13/16C - C + +The two notes on the second line are tied together, +but the first note is in C rather than ^13/16C causing +an audible pitchbend. The notes in the third line +are correct pitches but not joined. The tied notes +in the fourth line are both incorrect pitches. + +Analyses: looking at the mftext output from midi2abc +reveals the problem. + +midi2abc.exe tmp/X1.mid -mftext +Header format=0 ntrks=1 division=480 +Track 1 contains 141 bytes + 0.00 Metatext tempo = 227.00 bpm + 0.00 Metatext key signature C (0/0) + 0.00 Metatext time signature=4/4 + 0.00 Program 1 73 (Flute) + 0.00 Metatext (Seqnce/Track Name) tied microtonal... + 0.00 Note on 1 c4 127 + 2.00 Note off 1 c4 0 + 2.00 Pitchbnd 1 msb=0 lsb=90 + 2.00 Note on 1 c4 107 + 2.00 Pitchbnd 1 msb=0 lsb=64 + 4.00 Pitchbnd 1 msb=0 lsb=90 + 6.00 Note off 1 c4 0 + 6.00 Pitchbnd 1 msb=0 lsb=64 + 6.00 Pitchbnd 1 msb=0 lsb=90 + 6.00 Note on 1 c4 107 + 8.00 Note off 1 c4 0 + 8.00 Pitchbnd 1 msb=0 lsb=64 + 8.00 Pitchbnd 1 msb=0 lsb=90 + 8.00 Note on 1 c4 117 + 10.00 Note off 1 c4 0 + 10.00 Pitchbnd 1 msb=0 lsb=64 + 10.00 Pitchbnd 1 msb=0 lsb=90 + 10.00 Note on 1 c4 107 + 10.00 Pitchbnd 1 msb=0 lsb=64 + 14.00 Note off 1 c4 0 + +This is another example where the handling of tied notes +in dotie() store.c and writetrack() in genmidi.c have +gets in the way. (The code was written before microtones +was introduced into abcmidi.) The parser encircles +every microtonal note with an event_microtone and +event_normal_tone. The function dotie changes the +tied note from NOTE to TNOTE, the TIE to a REST, +and the note being tied to a REST. The function writetrack() +unfortunately applies the delay() function for the +NOTE feature but not for TNOTE. As a result, the +pitchbend is restored to normal before the note +even starts playing. + +Modernizing the tienote function (see February 12 2005 +comments) is not an option since there were too many +cases to worry about and it would probably take a +long time to get out all the bugs out. + +Fix: a small patch was added to tienote() in store.c. +It removes the DYNAMIC feature restoring the pitchbend +to normal if it finds one immediately following the +TNOTE. + + + +January 15 2006 + +The contour matching algorithm in abcmatch.c has +been changed to use pitch interval between adjacent +notes. A new run time parameter, -qnt was added +which quantizes the contour interval. Details +in abcmatch.txt. + + +January 16 2006 + +Added new feature to yaps that allows you to switch from black +to red output using !red! or +red+ instruction command. +To restore insert !black! or +black+ in the abc file. + +e.g. + +X: 356 +T:Banks of the Nile +M:4/4 +L:1/4 +K:Eb +B/2-G/2| F E F G| c B G E| F E- C C| C3 C|!red! E E G B!black!| +c2 e c/2c/2| B B E F| G3 E/2E/2| E E G B| c c e c/2c/2| B B E F| + G3 B/2G/2| F E F G| c B G E| F- E C C| C3|| + +The notes in the 6 bar are printed in red for emphasis. + +Implementation: +In structs.h added a new structure + struct dynamic {char color;}; + +In yapstree.c, added code to event_handle_instruction to detect +!red! and !black! and addfeature(DYNAMIC,psaction) where psaction +is a *dynamic struct. In drawtune.c added code to printvoiceline() +to take appropriate issue a postscript command to change the +color when it detects a DYNAMIC: feature. + +January 29 2006 + +Abc2midi: improved the microtone pitch accuracy. Replaced the +code event_microtone (in store.c) with the code contributed by +Hudson Lacerda. + +Introduced some support for single note tuning change using +the universal system exclusive messages. Added new function +in midifile.c single_note_tuning_change(). In function +dodeferred in genmidi.c added a %%MIDI snt k pitch +command where snt stands for single note tuning, k is the +MIDI pitch being retuned (a number between 0 to 127) and +pitch is a floating point number representing the new +pitch value. Sample file follows. + +X:1 +T: single note tuning +M: 2/4 +L: 1/8 +K: G +C \ +%%MIDI snt 60 61.5 +C cd| + +I have not yet updated abcguide.txt since this feature +is provisional right now. Not all MIDI devices support +this universal system exclusive message. + + +February 05 2006 + +Abc2midi.exe eliminated the warning for microtones +"divisor not a power of 2". Introduced a new copy +of readlen (readlen_nocheck which is called by +ismicrotone() and does not report this error.) + + +March 14 2006 + +Abc2abc does not recognize "middle=XXX" in the V: field +which is used by abcm2ps and silently drops it when +transposing abc files. The fix was provided by Mike +Scott who also cleaned up the parameter calling sequence +to event_voice in parseabc.c. This also involved altering +the code in store.c, yapstree.c, matchsup.c, and toabc.c. +Thank you. + +Added #include to crack.c, mftext.c, +pslib.c and queues.c which cleans up some of the +compilation warnings.(Thanks to Martin Tarenskeen.) + + +Apr 21 2006 + +(Mike Scott) The 'y' spacing character used by Barfly and +abcm2ps was being silently dropped in parseabc.c. Added +support for this (including a length specifier - is this +used by anything?) to parseabc.c and abc2abc.c; stubs in +the other modules including yaps mean they behave as before. + + +June 7 2006 + +Midicopy: new runtime parameters -frombeat and -tobeat were +introduced to copy a selection of a midi file. + +Midifile: new code was introduced to process an individual +track in a multitrack MIDI file. + + +June 25 2006 + +Abc2midi: added new feature to provide control over the +articulation of the notes. The feature %%MIDI trim x/y +introduces a gap between notes of duration x/y where x/y +is the fraction of the unit note length defined by the +L: field command. This gap is made by shortening every +note by this amount whenever it is possible. If the note +is too short, the gap is reduced. Slurs indicated by +parentheses in the music body temporarily disable this feature. + +Implementation: added a new feature SETTRIM in abc.h. +Added new globals variables trim,trim_num,trim_denom in +genmidi.c. Added additional code in writetrack to initialize +trim_num,trim_denom and to modify notes for switch conditions +NOTE:, CHORDOFF:, and CHORDOFFEX. Added new switch state +in writetrack to interpret feature SETTRIM. In store.c, added more +code in event_specific to interpret the %%MIDI trim command. + +Abcguide.txt, abc2midi.1 and demo.abc were all updated. + +Thanks to Jacques Le Normand for the suggestion. + + +July 28 2006 + +Midicopy still does not extract correctly a segment from +some MIDI files when it is specified using the -fromsec and +-tosec parameters. This occurs in multitrack MIDI files +containing numerous tempo changes. Time units measured in seconds +do not correspond between tracks. + +It was decided to completely change the method of handling +segment extraction when time is specified in seconds. It is +assumed that all tempo indications are placed in track 1 of +the MIDI file. Tempo changes in other tracks are ignored. +An initial pass is made through track 1 to extract all the +tempo changes and store them in an array. This is used to +map time in seconds to MIDI pulses or ticks. The -fromsec +and -tosec parameters are converted to pulse units using +this mapping. The program then extracts the MIDI information +falling in this time interval. + + +July 28 2006 + +Abc2midi returns the error message +"First lyrics line must come after first music line" +when processin abc files with lyrics and inline voice commands. +For example + +X:1 +T: inline voice +M:5/8 +L: 1/8 +K:G +[V:1] cdefg +w: c d e f g +[V:2] cdefg +w: c d e f g + +I have little experience with lyrics in abc files. + +The problem is caused by the fact that the inline voice command +starts up a new track which resets the variable thismline = -1. +This indicates that a new music line was not yet encountered +for this voice. If the notes cdefg were placed in a separate +line, then the variable thismline was be set to the current +line number and everything would be all right. Unfortunately, +this is not the case and the abc2 draft standard excepts this +syntax. See abc.sourceforge.net/standard/abc2-draft.html and +in particular the canzonetta.abc file on that page. +There is no easy way of detecting music information at this +point other than updating the variable thismline every +time a note is processed. Instead, I disabled the error +message by commenting the line +thismline = -1; +in genmidi.c. Hopefully, this does not cause more damage. + + +July 29 2006 + +Abc2midi: microtones (pitchbend) does not work correctly for tied +notes enclosed in a slur. For example: + +X:1 +T:bad pitchbend when tie + slur +M:4/4 +L:1/8 +K:C +"^Bad pitch bend when tie+slur" +(^1/2C- ^1/2C =C) a- a4 | + ^1/2C- ^1/2C =C a- a4 + +In the first bar, the tie does not work correctly and 3 notes are +heard instead of two. Furthermore the first note does not have +a pitchbend applied. In the second bar, the notes are played +correctly. + +Analysis: running midi2abc with the -mftext option provides +some indication of the problem. + + 0.00 Pitchbnd 1 msb=0 lsb=80 + 0.00 Note on 1 c4 105 + 0.00 Pitchbnd 1 msb=0 lsb=64 + 0.50 Pitchbnd 1 msb=0 lsb=80 + 1.00 Note off 1 c4 0 + 1.00 Pitchbnd 1 msb=0 lsb=64 + 1.00 Note on 1 c4 80 + 1.50 Note off 1 c4 0 + +The pitchbend is set prior to the note but is restored to +normal immediately after the note is started (time 0.00). +This is similar to the problem fixed on January 14 2006 +(see this file). This suggests a problem with the function +dotie(). Further analysis, revealed that the parser +places a SLUR_TIE after every NOTE feature when the notes +are enclosed inside a slur. The SLUR_TIE is not needed +by abcmidi but it is used by yaps. Unfortunately, the +function dotie() does not expect a SLUR_TIE to appear between +the TNOTE and DYNAMIC so it fails to remove the DYNAMIC +feature. + +Fix: A similar patch described in Janurary 14 2006 was +added to dotie(). + + +July 29 2006 + +Abc2midi: It is not commonly known that accidentals are not +supposed to propagate across octaves. In the follow example, + +X:1 +T: accidentals and octaves +M: 2/4 +L: 1/8 +K: G +C_EDe|C_EDe-|e2^f2|-f2g2| + +Abc2midi normally also flattens the e; however, technically +it should not be doing this. Accidentals only apply to a +specific note and should not affect the same pitch class +in other octaves. + +Fix: in store.c workmap and workmul are now doubly indexed +arrays. The second index keeps track of the octave. + + +July 30 2006 + +Abc2abc transposition always reverts to the major key signature +when it does a transposition. + +Analysis: the code in toabc.c represents the key signature +in terms of the number of sharps and flats and ignores the +mode of the original key signature when it is doing a transposition. + +Fix: (1) In parseabc.c the index to the array mode[] is +saved in the variable modeindex when a mode string is matched. +(2) in order to pass modeindex to event_key, the function +parameter minor was replaced with modeindex and the +variable minor was turned into a local variable which is +computed from modeindex. This was done in all files where +event_key is defined -- store.c, yapstree.c, matchsup.c, +and toabc.c. (In actual fact, the variable minor was only +used in store.c to set the minor flag in the MIDI file.) +(3) A new function called compute_keysignature() from +the sharps/flat representation and modeindex was added to +toabc.c. (4) event_key in toabc uses this function to +compute the correct key signature. + + +August 04 2006 + +abc2midi: The treatment of microtones and microtones with +accidentals for key signatures other than C major (or A minor) +has been changed. Prior to version 1.87, if the music +was in the key of G major, ^1/2F would be interpreted +as raising F# by a half a microtone. Now the underlying +key signature is ignored and the microtone is treated as +a pure accidental. Thus ^1/2F raised F and not F#. +Hopefully this is more intuitive. + +Thus accidentals and microtones are assumed to be +applied to the natural form of the note irrespective +of the key signature or the status of previous +notes in the measure. However, accidentals other +than microtones can still propagate to notes which +do not have accidentals. To illustrate consider +the following in the key of C major. + + _E _1/2E E __1/2E E| + +The second E is treated as E natural flattend by 1/2 +microtone because E is always assumed to be in its natural +form when preceded by any accidentals. Since the assumed +natural of the second E propagates, the third E is also +E natural and not Eb. The last note is Eb reduced by half +a semitone. The last E would be played as Eb. See +abcguide.txt for another example. + + +Implementation turned out to be easier than expected. A +new global (int microtone) was added to store.c. It is +set to 1 by event_microtone and reset to 0 by event_normal_tone. +The function pitchof(), now does not apply the active +flats or sharps (of the key signature) or accidentals when +the microtone global is set. + + +August 4 2006 + +Abcm2ps has introduced an extension of the w: field +referenced by the s: field which accepts ~ as a decoration. +Unfortunately, the parser in the abcmidi package does not +recognize this field command and attempts to treat the +line as a music line. As a result a file such as + + +X:1 +T: s +K:C + cd ef g4 | ag ab c'4 |] +s: "C"~~~ "C/E" | "Dm/F"* "G7" "C" +s: .. .. +tenuto+ | .. .. !fermata! +s: "_5"***"_6" | "_6"* "_7"*"_5" +s: "_3"***"_3" | "_3"* "_5;3"*"_3" + +produces many error messages +Error in line 6 : Single colon in bar +Error in line 6 : Malformed note : expecting a-g or A-G +Error in line 6 : *'s in middle of line ignored +Error in line 7 : Single colon in bar +Error in line 7 : Malformed note : expecting a-g or A-G +Error in line 7 : Malformed note : expecting a-g or A-G +Warning in line 7 : instruction !tenuto! ignored +Error in line 7 : Malformed note : expecting a-g or A-G +Error in line 7 : Malformed note : expecting a-g or A-G +Error in line 8 : Single colon in bar +Error in line 8 : *'s in middle of line ignored +Error in line 8 : *'s in middle of line ignored +Error in line 8 : *'s in middle of line ignored +Error in line 9 : Single colon in bar +Error in line 9 : *'s in middle of line ignored +Error in line 9 : *'s in middle of line ignored +Error in line 9 : *'s in middle of line ignored + +Similar error messages occur for other abcmidi programs, +for example yaps, abc2abc etc. + +Fix: in parseabc.c: for function +parsefield add s to the strchr string + if ((inbody) && (strchr("EIKLMPQTVdwW", key) == NULL)) { + event_error("Field not allowed in tune body"); +and also added the case in the switch statement + case 's': + break; +finally in parseline() added s to the strchr string in + if (strchr("ABCDEFGHIKLMNOPQRSTUVdwWXZ", *p) != NULL) { + q = p + 1; + + +August 05 2006 + +Note trimming introduced in June 25 2006 causes loss of +synchronization between two voices when notes are contained +in a grace sequence. +Fix: introduced a variable graceflag into writetrack() in +genmidi.c. The flag is set when GRACE feature is encountered +and restored to zero when GRACEOFF feature is encountered. +Note trimming is disabled inside a grace sequence. Also +note trimming is shutoff for short notes. +In order to separate two slurs in a row, trimming is +restored for the last note in a slur. + +August 08 2006 + +Abc2midi: split voices. In the file + +X:1 +T: also D sharp continues in next bar +K:C +M:4/4 +L:1/4 +C^DEF & C4 | CDEF | + +The D in the second bar is sharpened. +Fix: added call to function copymap() in the function +recurse_back_to_original_voice(). + +August 29 2006 + +Abc2abc: handling of rests in tuples causes an error +message. The problem does not occur in abc2midi +or yaps. For example + +X:1 +T: tuple rests +M: 2/4 +L: 1/8 +K: C +G4|(3z2A2B2|F4| + +abc2abc tuplerest.abc -t 3 +X: 1 +T:tuple rests +M:2/4 +L:1/8 +K:C +G4| +%Error : Rest not allowed in tuple + (3z2A2B2 +%Error : Bar 1 is 7/12 not 2/4 +|F4 +%Error : Bar 2 is 1/3 not 2/4 +| + + +Fix: in the function event_rest in toabc.c, the +error message was removed and the beat counter +code was modified to consider tuples. + + +September 09 2006 + +abc2abc: voice numbers not processed correctly. In the +following example: + +X:1 +T:voices +M: 2/4 +L:1/8 +K:G +V:1 +ABCD|abcd| +V:1I +ABCD|abcd| + +V:1I was changed to V:1 producing an incorrect abc file. +Analysis: the parsevoice() in parseabc decides whether the +voice number is a number or a label based on the first character. +Since the first character of 1I is a number it treats it as +a number and ignores the I. This problem also persists for +abc2midi and yaps. +Fix: created a new function isnumberp(s) which determines +whether the string s is a positive integer number and +returns 0 for no and 1 for yes; replaced the original test +with this function. + +September 11 2006 + +Abc2midi: handling of trilled notes for broken rhythms is not +correct. In the following example, + +X:1 +T: trill +M: 2/4 +L: 1/8 +K:C +%%MIDI ratio 3 1 +TE>G TF3/A/| + +the length of notes E and G are not adjusted for broken rhythm +and remain as equal values. +Analysis: the handling of broken rhythms is fairly complicated +in the file store.c. The location of E and G are maintained by +variables v->thisstart, v->thisend and v->laststart, v->lastend +by the functions marknotestart, marknoteend and marknote. (This +also allows the handling of chords too.) When a > or < is encountered +a number of flags (brokenpending, brokentype, brokenmult) are set +by the function event_broken. The function marknotend checks +these flags and calls brokenadjust to adjust the lengths of E and +G using the stored variables v->thisstart, v->thisend etc. Trilling +is handled by the function dotrill() which expands note E +into a sequence of notes whose length depends upon the length +of E and the tempo. In this example, the expansion is done +prior to encountering the broken rhythm indicator >. After +G is encountered, the lengths of the notes are adjusted for +broken rhythm. Unfortunately, there is a bug in dotrill, and +marknotestart was called for the last note in the trill sequence +rather than the first note. The problem was fixed by changing +this code. Note that in the above example, the number of notes +in the trilled E and the trilled F are different. This is +because E is not effectively expanded until after it was +trilled. There is no easy fix to this problem other than +avoiding mixing notations for broken rhythms. + +trilled F are different. +than the first note + + +September 22 2006 + +Midicopy.c: to avoid problems with some systems, the byte val +for the runtime string +-replace trk,loc,val +is read as an integer (%d) instead of a char (%c). + + +September 22 2006 + +Abc2abc, abc2midi etc. does not recognize "clef=G". +In the following example, + + +X:1 +T: clef problem +M: 2/4 +L: 1/8 +K: Am clef=G +"Am"ABCD|ABCD| + +The following message appears: +%Warning : cannot recognize clef indication +K:Am clef=G + +Fix: added checks for clef=g or clef=G in the function +isclef() in parseabc.c + + +September 23 2006 + +Abc2abc removes blank lines from abc files. (These +blank lines are usually to encircle comments between +tunes in a multitune file. + +Analysis: whenever parseline() (in parseabc.c) detects +a blank line, it calls event_blankline(). In abc2abc, +event_blankline() only emits a blank line if the flag +newbreaks is set. Unfortunately, this parameter is used +for another purpose (i.e. reformating an abc file with +new linebreaks every X bars using the -n X runtime parameter). +This has nothing to do with handling already existing +blank lines. Since event_blankline is called only when +there is a blank line, it appears that the condition on +the flag newbreaks should not be present. + +Fix: the condition statement was removed. A blank line will +always be issued. Note that event_blankline also closes +the tune and parser for that tune as usual. + + + +September 25 2006 + +Abc2midi: some users have complained about the unnecessary +warnings and error messages issued by abc2midi. For example +standard music practice does not require a leading repeat +mark |: to be placed at the beginning of the sheet music and +it is commonly left out in many abc transcriptions. Abc2midi +typically warns the user that it has been left out but does +the correct thing. Furthermore, the placement of a fermata sign +will likely cause a message that a bar has too many beats. +Too placate the users, + +I have introduced a new runtime parameter -quiet which will +suppress all these messages. + +Note abc2midi parses the abc file in two passes and may not +always handle assumed repeats correctly. For example if the +tune begins with an anacrusis, abc2midi does not attempt +to figure out whether the |: should be placed before or +after the anacrusis. (This depends upon the placement of the +end repeat.) In multipart files, abc2midi fails to place +a starting repeat sign. + +In the case of multivoiced files, loss of synchronization between +voices can occur because of user mistakes or because abc2midi made +the wrong assumption. (For example, search for the word fermata +in this file.) + +Though attempts have been made to standardize the abc music notation +language, it is a living language and various variants are introduced +now and then. Abc files that have been notated many years ago are +not updated to correct for the various problems that are introduced by +these new features. There is a variety of software to process abc files, +but many of the developers have moved to other things and fail to +maintain their software. Though these messages are an inconvenience +to users they are useful in diagnosing problems when the MIDI file +does not sound correctly. + + +September 26 2006 + +Abc2midi: now supports linear temperament scale using code contributed +by Magnus Jonsson. New %%MIDI commands are introduced to change the +temperament. + +%%MIDI temperamentlinear octave_cents fifth_cents + +where the variables specify the size of an octave and size +of a perfect fifth in cents where one cent is 1/100 of +a semitone or 1/1200 of an octave. + +%%MIDI temperamentlinear 1200.0 700.0 + +produces the equal tempered scale. + +%%MIDI temperamentlinear 1200.5 698 + +produces a slightly stretched octaves and narrowed fifths. +Quoting the Help for the program Scala +http://www.xs4all.nl/~huygensf/scala/ + +A linear temperament is a cycle or chain of one particular interval, +called the generator or formal fifth. Whenever by doing so a pitch +originates that is outside the range of one formal octave (interval of +equivalence), it is "wrapped" back inside by subtracting the formal +octave value. Examples of this kind of scale are the Pythagorean scale +generated by a pure fifth, and regular meantone scales. + +Implementation: +store.c : + added new globals temperament, octave_size, fifth_size + which are set by %%MIDI temperamentlinear. Created a new function + pitchof_b() which is similar to function pitchof() but also returns + a pointer pitchbend. Pitchof_b() would eventually replace all calls + to pitchof(). The function pitchof_b() applies the linear temperament + scale if the global variable temperament is set. It updates the + pointer pitchbend unless it was already set by a microtone. + + To store the pitchbend value of every note a new array bentpitch + was added to the other arrays (pitch, num, denom, feature). + The function event_note transfers the pitchbend value to bentpitch, + so it can be used by writetrack() in the second pass (in genmidi). + + Other functions that had to be updated were doroll, dotrill, + makecut, and doornament. + +genmidi.c : + Added global array current_pitchbend[], which maintains the + current pitchbend for each channel. It is initialized to 8192 + (neutral value) by starttrack. The pitchbend value is now + transferred to the function midi_noteon(). It will issue + a pitchwheel command anytime a new pitchbend value occurs + for the specific channel. Other functions like noteon_data() + and save_note() also carry the parameter pitchbend. + + +Limitations: linear temperament is not applied to guitar gchords. + + +October 3 2006 + +Abc2midi: in order that microtones are applied correctly to +in voice chords such as [CEG], it is necessary that each note +in the chord be played on a separate MIDI channel. A new MIDI +command "makechordchannels n" has been introduced for allocating +MIDI channels specifically for the handling of chords. The +value of n specifies the number of channels to be allocated. +It should be one less the maximum number of notes in the chord. +Note that since you have only 16 channels in a MIDI file and +once the channel has been allocated it is unavailable for +any other use. You need to do a separate allocation for each +voice containing such chords. + +Implementation: +In genmidi.c, introduced a global array chordchannels[] which +is used to store the channel numbers for handling chords. +chordchannel[0] is the channel number normally used for +handling notes for that voice. Introduced a global integer +nchordchannels storing the number of channels in chordchannels[]. +Created a new function makechordchannels() for assigning +these channels to chordchannels[]. Makechordchannels also +sets the channels program (musical instrument) to the current program +for the voice. (If you need to know the channel numbers that +have been assigned, run abc2midi with the -v option (verbosity)). +Created another branch in the function dodeferred() for handling +the MIDI command makechordchannels(). + + + +October 15 2006 + +The following file was not parsed correctly. + +X:1 +T: 2 or 3 tracks +M: 3/4 +L: 1/8 +K:G +g2| g2 fe b2| +V:2 +A2 |[B4E4] G2| + +Analysis: a bug I introduced recently resulted in the voice number (2) +not being read correctly. + +Fix: in the function parsevoice() in parseabc.c, I changed the +statement +if (isnumberp(&s)) { +to +if (isnumberp(&s) == 0) { + +apparently, this function returns 0 if the string contains a +positive number and 1 otherwise. + + +October 27 2006 + +Abc2midi: using the command %%MIDI drumon causes the error +MIDI read/write error : error: MIDI channel greater than 16 +and abc2midi fails. + +This is another bug I had introduced. Adding the pitchbend +parameter 8192 to save_note in function dodrus() in genmidi +fixes this problem. + + +October 27 2006 + +Abc2abc transpose places spurious spaces between notes +breaking up the beaming pattern. For example for, +X: 1 +T: beaming error +L: 1/8 +M: 4/4 +K: Eb +^C,,2 z2 z^C,/D,/ =E,/^F,/G,/=A,/ | B,/=A,/G,/^F,/ G,/=E,/^C,/D,/ +E,/F,/G,/A,/ B,/A,/G,/A,/ | + +abc2abc beaming.abc -t 1 produces + +X: 1 +T:beaming error +L:1/8 +M:4/4 +K:Emaj +^^C,,2 z2 z^^C,/2 D,/2 ^E,/2^^F,/2 G,/2^A,/2 | B,/2^A,/2G,/2^^F,/2 G,/2^E,/2^^C ,/2 D,/2 + E,/2 F,/2 G,/2 A,/2 B,/2 A,/2 G,/2 A,/2 | + +(note all the spaces between the notes in the second line of the body). + +Analysis: the local variable mult in event_note1() in toabc.c is +used before it is defined. + +Fix: event_note1() now sets it to zero in case it is not set elsewhere. + + + + +November 3 2006 + +Abc2midi bug: pitches are incorrect for staccato notes. eg + +X:1 +T: staccato bug +M:3/2 +L:1/2 +Q:1/4=70 +%%MIDI program 16 +%%MIDI nobeataccents +K:C +=B=c=d | .=B.=c.=d | + +The pitches of the last three notes have been affected by +a pitchbend. + +Analysis: This is a bug I recently introduced. The bentpitch[] feature +was not set to 8192 for staccato notes. + +Fix: added the following line + bentpitch[notes] = active_pitchbend; +before + addfeature(NOTE, ...); + +in event_note() in store.c. Also added it in doornament(). + + + +November 3 2006 + +Abc2midi bug: the following file causes the error message +MIDI read/write error : error: MIDI channel greater than 16 +to appear. + +X:1 +T: makechord +M:3/2 +L:1/2 +Q:1/4=70 +V:1 +%%MIDI nobeataccents +%%MIDI program 16 +%%MIDI makechordchannels 2 +V:2 +%%MIDI program 16 +%%MIDI makechordchannels 2 +V:3 +%%MIDI program 16 +%%MIDI makechordchannels 2 +K:C +% +V:1 +[c'_/e'g'] +V:2 +[c_/eg] +V:3 +[C_/EG] + + +Analysis: there was a missing parameter (bentpitch) in the function +call to noteon_data() when channel == 9. As a result the function +noteon_data() received a meaningless channel number. However, +since channel 9 is reserved for percussion, it should never have +been assigned. To fix this problem, the global variable channels[9] +was set to 1 in writetrack() (genmidi.c), so that findchannel() +will not select this channel. + + +December 9 2006 + +Abc2midi bug: the %%MIDI drone command returns an error +MIDI channel > 16. +Fix: missing parameter in function midi_noteon(), pitchbend, +was added. + + +December 12 2006 + +Abc2midi bug: split voices does not work correctly when +it is embedded in a part (eg. P:B). For example: + +X: 1 +T: bad merge +M: 4/4 +L: 1/8 +K: C +P:A +| C2 D2 E2 F2 | G2 A2 B2 c2 | +P:B +| C2 D2 E2 F2 & C,2 D,2 E,2 F,2 | G2 A2 B2 c2 | + +The split voice does not merge correctly in the +above example. + +Analysis: not all voices may be indicated in a part. As a +precaution, genmidi calls partbreak which fills in any missing +voices. Unfortunately, split voices are automatically resynced +which causes the voice to be filled in twice. +Fix: a new global array dependent_voice[] was added in +store.c and linked to genmidi.c. This array contains flags +indicating where the particular voice was a natural voice +created by a voice command (V:) or whether this is a +split voice dependent on the natural voice. The function +partbreak checks this flag and does nothing if is a +dependent voice. + + +December 21 2006 + +Voice bug (abc2midi, yaps): the fix described in September 9 2006 +caused another bug. For the following example: + +X:1 +T: noel +M: 2/4 +L: 1/4 +K: C +V: alpha +C E|D F| +V: beta +A C| G B| + +The parser fails to handle nonnumeric voice numbers. +Fix: in line 996 of parseabc.c isnumberp returns 1 +if the character string is a positive number and 0 if +it is not. The 0 was replaced with 1 as shown below. +if (isnumberp(&s) == 1) { + +December 26 2006 + +Midi2abc bug. Some music notation programs automatically place +short rests between notes and chords in order to improve the +articulation. Midi2abc is able to ignore these rests using +the -sr parameter as described in the midi2abc.1 documentation. +Unfortunately, this feature does not work correctly when rests +are placed in between chords. + +Analysis: the quantize() function decides whether to eliminate +the rest based on the difference between the inter note interval +(note->xnum) and the "on" time of the note (note->play). For +some of the chordal notes, note->xnum is zero since all the notes +in the chord start at the same time. This causes the program +to produce erroneous results. + +Fix: a new function xnum_to_next_nonchordal_note() was introduced +to look ahead past all the chordal notes and return the quantized +note interval to the next nonchordal note. The quantize function +uses this value when the -sr option is turned on. (I have +a feeling this fix may not work correctly when the notes in +the chord are not all equal length. In other words I do not +recommend using the -sr option with -splitbars or -splitvoice.) + + +January 02 2007 + +Abc2midi bug: %%MIDI trim does not work according to documentation. +The trim command is used to control the articulation of notes. +Like staccato it shortens the playing time of the note, +leaving a silent period before the next note. According to +the documentation the amount shortened should be the trim +fraction time the unit note length. It turns out that +the trim length was not adjusted for the unit note length +so that the following example did not work. + +X:1 +T: trim +M: 2/4 +L: 1/8 +K: C +%%MIDI trim 1/2 +CDEF| + +Fix: store.c was modified so that trim value set is a fraction +of the unit note length as defined by the L: field command. +Note, that if the unit note length is changed again, it is +necessary to reissue another trim command, eg. + + +X:1 +T: trim +M: 2/4 +L: 1/8 +K: C +%%MIDI trim 1/2 +CDEF| +L: 1/16 +%%MIDI trim 1/2 +CDEF CDEF CDEF CDEF| + +Otherwise the trim length will remain unchanged. + + +January 06 2007 + +Abc2midi bug: wrong bar count when %%MIDI trim command +mixed with chords. In the following example, + +X:1 +T: Bad barcount +M: 2/4 +L: 1/8 +K: C +%%MIDI trim 1/2 +AB CD |AC DF |[A2c2] DF | +[AB]2 [CD]2 | + +Abc2midi produces the following warnings: + +Warning in line 9 : Bar 2 has 7/4 units instead of 2 +Warning in line 10 : Bar 3 has 3/2 units instead of 2 + +Furthermore, this may throw off the gchord accompaniment +if it exists. + +Fix: in writetrack for case CHORDOFF: and CHORDOFFEX:, +the function addunits() is called before trim adjustment +instead of after. + + +March 15 2007 + +Abc2midi ends a MIDI track immediately after the last note. +On some MIDI synthesizers, this introduces a small artefact +at the end of the MIDI file. Fix, a short delay of 25 MIDI +pulses is inserted before the end of track. This was incorporated +in the function clearQ() in queues.c. + +Midi2abc -mftext mode was modified to report end of track meta +command. + + +December 09 2007 + +New feature in abc2midi: the program now recognizes the command + +%%propagate-accidentals not + +as described in http://abc.sourceforge.net/standard/abc2-draft.html +directive 11.3 + +This command suppresses propagation of accidentals across a bar. +The commands +%%propagate-accidentals pitch +or +%%propagate-accidentals octave + +restores propagation. Presently only octave method is used. + +For example: + +M:2/4 +L:1/8 +K:Eb +%%propagate-accidentals not +A =A A2| + +A2 is flattened since the natural sign does not propagate. + + +January 04 2008 + +Running yaps with the -E option to produce encapsulated +postscript file (.eps) causes the program to crash with +the error message +*** glibc detected *** yaps: double free or corruption (!prev): 0x08d5f390 + +Analysis: the program attempts to close the output file twice. +close_output_file was called once by printtune() (when it encountered +a blank line) and again by event_eof() when it encountered an eof. +The operating system does not set the filehandle to NULL after the +file was closed defeating the conditional test in close_output_file. + +Fix: after closing the file the file handler is set to NULL. + + +March 09 2008 + +Midi2abc: added a new option -title for providing the title +of the tune to insert in the abc file. + +June 07 2008 + +Abc2midi: introduced a warning for chords containing +unequal notes (eg. [c2e] will cause a warning to be issued). +The warning was added in writetrack in genmidi.c. In +order to get a reasonable output, the incorrect chord +will be played as [c2e2]. (The length of the first note +dominates.) + + +June 13 2008 + +Abc2midi: produces a warning "Different length notes in tuple" +when one of the notes in the tuple is a chord. eg. +X:1 +T: triplet chord +M: 2/4 +L: 1/16 +K: D +[DF]4 (3[B2d2]c2d2 | + +Analysis: the problem was traced to a bug in the function +event_chordoff in store.c which was introduced with the +chord syntax extension described in November 4 2004. +In computing the tuple adjusted note length, the function +always uses chord_n and chord_m parameters even when +they do not apply (equal to 1/1). Fix new local variables +c_m and c_n are introduced which are set to chord_n,chord_m +or num[chordstart] and denum[chordstart] depending on +whether the chord syntax extension is used or not. The +tuplet adjusted note length is computed from c_n and c_m. + +It was also necessary to change event_note so that +tuples are processed for chords too. + +June 14 2008 + +Abc2midi: ornaments (eg ~G3) does not work correctly for +default length other than 1/8 (L: 1/8). Analysis, doornament +(in store.c) assumes L:1/8 for dotted quarter notes. This was fixed. + + + +June 24 2008 + +Abc2midi: new feature. The %%MIDI drum line can sound quite +monotonous if it is repeated each bar. To circumvent this problem +a new MIDI command +%%MIDI drumbars n +where n is a small number will spread out the drum string over +n consecutive bars. By default drumbars is set to 1 maintaining +compatibility with existing abc files. You should take +care that the drumstring is evenly divisible between the +drumbar bars. Also the time signature should not change +between bars in a drumbar unit. + +Sample usage: + +X:1 +T: splitting a drum string into two bars +M: 2/4 +L: 1/8 +K: G +%%MIDI drum zdzdzdzd 39 59 50 60 +%%MIDI drumon +z4| z4| z4| z4| +%%MIDI drumbars 2 +%%MIDI drum zdzdzdzd 39 59 50 60 +z4| z4| z4| z4| + + + +Implementation: All the changes were confined to genmidi.c +Two new variables drumbars and drumbarcount are introduced. +Drumbars modifies drum_denom in set_drums. (This changes +the duration of a unit drum hit.) The function checkbar resets +the drum_ptr every drumbars using the drumbarcount variable. + +July 2 2008 + +Regarding the drumbars implementation it is necessary +to reset drumbarcount to 0 in writetrack after drumbars is +initialized back to 1. + + +July 17 2008 + +Abc2midi bug: the following sample causes abc2midi to issue +a warning + +Warning in line 9 : Bar 0 has 10 units instead of 6 in repeat + +X:1 +T: meter change +M:5/8 +L:1/8 +K:C +% +|: [M:6/8] D6 &\ +[M:6/8] E6 | +[M:4/8] F4 :| + +Analysis: the warning is issued when writetrack is processing +track 2 which is the split voice track during the repeat. The +two [M:6/8] field commands ensure that the split voice track +also sets the meter to 6/8 time. However the split voice track +was not reset to [M:4/8] unless we do it explicitly with +[M:4/8] F4 & [M:4/8] z4|. Store.c/sync_voices inserts a required +rest z4 into bar 2 of the split voice but it does not include +a time signature command which is needed to ensure that +genmidi/checkbar will process the bar correctly. + +Fix: + +Added + + case TIME: + addfeature(feature[j], pitch[j], num[j], denom[j]); /* copy feature */ + break; /* [SS] 2008-07-17 */ + +into the code of sync_voices. + + +July 17 2008 + +Abc2abc: removed the space between X: and the reference number. + + + +July 21 2008 + +Removed all static declarations in parseabc.c +In parsekey(str) initialized the local string +clefstr and modestr. + +July 21 2008 + +Abc2midi bug: key signature and accidental propagation +applied to drum channel. In the following example, + +X:1 +T: drum key +M: 4/4 +L: 1/8 +K: A +V:1 +Z|ABcd efga| +V:2 +%%MIDI channel 10 +G,, ^F,, z1 F,, E,, ^D,, z2|G,, ^F,, z1 F,, E,, ^D,, z2| + +voice 2 is assigned to the drum channel so the notes +G,, ^F reference individual drum instruments rather than +pitches. Since the key signature is A major (F#, C# and G#), +event_note automatically raises G and F one semitone +and propagates ^F across the bar. This is not desired +for the drum channel. + +Fix: in store.c, a new variable, int drumchannel was +added to struct voicecontext. It is initialized to 0. +When event_specific handles a %%MIDI channel 10, +drumchannel is set to 1. For other channels it is set +to 0. A new function barepitch() was created from +the function pitchof_b. This function does not apply +the key signature or note propagation. The function +event_note now checks whether v->drumchannel is set and calls +barepitch() instead of pitchof_b() in such circumstances. +(See Cuckoo's Nest in demo.abc for a sample.) + + +August 4 2008 + +Midi2abc: new feature. The -mftext prints the name of +the drum patch for channel 10 and noteon commands. + + +August 11 2008 + +Abc2midi bug: The following abc file cause abc2midi +to halt with a segmentation error. + +X:1 +T: trim problem +M:3/4 +L:1/4 +%%MIDI trim 1/8 +K:C +ABC|DEF| + +Analysis: the error occurs in event_specific when the function + addfeature(SETTRIM, 1, 4*a, b*v->default_length); +is called. The voice structure does not exist causing +a segmentation error when v->default_length is addressed. +(v does not exist until the body of the abc file.) +Fix: if v does not exist, addfeature(SETTRIM,...) +get the default_length from global.default_length. +Comment: event_refno creates the voice structure and +then destroys it when it calls startfile(). This does +not cause a problem but makes the code obscure. + + +August 12 2008 + +Another abc2midi trim bug: the following warnings are + +Warning in line 9 : unequal notes in chord 7/8 versus 1/1 +Warning in line 9 : unequal notes in chord 3/4 versus 1/1 + +are the produced from this file. + +X:1 +T: trim problem +M:3/4 +L:1/4 +K:C +%%MIDI trim 1/8 +%%MIDI makechordchannels 2 +CD[ABc]| + +Analysis: the problem was traced to the function writetrack in genmidi.c. +The note length is trimmed inside the switch case for NOTE:. The +length of the trimmed note is saved and trimming is reapplied to this +length for each note of the chord. This bug was probably introduced +in June 7 2008 in order to make the the first note in a chord to dominate. +Fix: new variables tnote_num and tnote_denom are introduced specifically +for note trimming. + +August 12 2008 + +Still another abc2midi trim bug. For split voices, the notes are +trimmed in only one voice. In the following example, the notes +CDE are trimmed but not EFG. + +X:1 +T: another trim problem +M:3/4 +L:1/4 +%%MIDI trim 1/8 +%%MIDI makechordchannels 2 +%%MIDI program 20 +K:C +CDE & EFG| + +Fix: another case statement SETTRIM: was added to sync_voice() in store.c +Note that %%MIDI trim command only applies to a single voice. + + +September 17 2008 + +Abc2midi bug: wrong bass note when expanding guitar chord with inversion. +The bass note should be the note after the / rather than the pitch +of the chord. Thus "C/E" should be represented by E,,x [G,E,C,] rather +than C,,x [G,E,C]. + +Fix: case 'f' in function dogchords() in genmidi.c no tests for +an inversion. If an inversion is indicated, the bass note is changed. + + +September 18 2008 + +Abc2midi new feature: added the run time option (-NCOM) to suppress +some textual comments in the output midi file. + +September 24 2008 + +Abc2midi bug: for multitune abc files, the temperament is not automatically +turned off at the start of the next tune. Fix: temperament is initialized +to zero in startfile() in store.c + +September 24 2008 +Abc2midi new behaviour: the 'strange note' in a gchord is no longer +included in the chord. (i.e. F/G is now expanded as G,, [F,A,C] instead +of G,, [G,,F,A,C]. (Suggested by H. Lacerda). Change made in +configure_gchord() in genmidi.c + + +September 28 2008 +Abc2midi bug when selecting tune from collection. When the abc2midi +is used to create a single MIDI file from an abc file containing +a collection of tune which contains %%MIDI commands, abc2midi +numerous warnings 'cannot handle this MIDI directive here' for +the non-selected tunes. For +example +abc2midi balk2.abc 237 -v +Reference X: 180 +Warning in line 9 : cannot handle this MIDI directive here +Reference X: 181 +Warning in line 34 : cannot handle this MIDI directive here +Warning in line 35 : cannot handle this MIDI directive here +Warning in line 36 : cannot handle this MIDI directive here +Warning in line 37 : cannot handle this MIDI directive here +Reference X: 182 +[snip] +This obscures real warnings from the selected tune. + +Analysis: the messages are issued by event_specific_in_header() +which was designed to process MIDI commands which appear before +the first tune (X: refno), in the file. The function is called +when dotune == 0, which is true for unselected tunes. This means +that some of the directives in the nonselected tunes (e.g. nobarlines, +fermatafixed, ...) can affect the selected tune. Furthermore, +some other MIDI directives which are not recognized by the function +cause the above warnings to occur. In the following example +(headercommands.abc), + +%%MIDI nobarlines +X:1 +T: tune 1 +M: 2/4 +K:G +%%MIDI barlines +%%MIDI program 100 + + +X:2 +T: tune 2 +M: 2/4 +K: F +etc. + +the directive %%MIDI nobarlines appearing before the first tune +is to apply to all tunes in the abc file except where specifically +overrided (in tune 1). When we run + +abc2midi headercommands 2 + +we are expecting %%MIDI nobarlines to apply to tune 2. However, +this was changed in the nonselected tune 1 and the %%MIDI program 100 +command causes the message 'cannot handle this MIDI directive here'. + +Fix: a new global variable started_parsing initialized to zero was +introduced in store.c. When event_refno is invoked, the variable +started_parsing is set to 1. The function event_specific_in_header +is called only if started_parsing is still 0. + + +February 20 2009 +Yaps bug. The -E option (for encapsulated postscript) does +not compute the boundingbox correctly if the abc file contains +note fields (N:). eg. + +X:1 +T:A test +N:A note +K:C +AB cd ef ga | \ +AB cd ef ga | \ +AB cd ef ga | \ +AB cd ef ga | +AB cd ef ga | \ +AB cd ef ga | \ +AB cd ef ga | \ +AB cd ef ga |] + +The bottom part of the last staff is cutoff. + +Analysis: the function tuneheight() in drawtune.c did not +account for space used by the note fields. + +Fix: added several lines of code to the function to scan +through the notefield list and adjust the page height. + + +March 17 2009 + +Abc2midi new feature: a new command +%%MIDI gchordbars n +was introduced that acts in the same manner as %%MIDI drumbars (see +June 14 2008). but applies to the gchord string instead. The command +spreads the gchord string over n consecutive bars. In the following +example: + +X:1 +T: gchordbars +M: 2/4 +L: 1/8 +K: C +%%MIDI gchordbars 2 +%%MIDI gchord fzczIzHz +"C" c2 "G" c2|"C" g4|"G"c4|g4| + +fzcz applies to bars 0 and 2 while IzHz applies to bars 1 and 3. +For this function to work properly, it is important that +the length of the gchord string be exactly divisible by n +where n is the number of bars that the gchord string applies to. +If gchordbars is not specified, it is assumed to be one bar. + +Implementation is similar to drumbars. New variables gchordbars +and gchordbarcount were introduced in genmidi.c + + +June 23 2009 + +Abc2midi does not attempt to fill in missing left repeats |: +in multipart and multivoiced files. New code was introduced +to solve this problem. The functions scan_for_missing_repeats(), +add_missing_repeats(), clear_voice_repeat_arrays() was added +to store.c. + + +July 22 2009 + +Abc2midi produces irrelevant error messages + %%MIDI drumon must occur after the first K: header +when extracting a particular tune in a file containing a +collection, eg. +abc2midi balk1.abc 10 + +Fix: in event_specific() in store.c now check the flag dotune. + if (strcmp(command,"drumon") == 0 && dotune) { + addfeature(DRUMON, 0, 0, 0); + etc. + +July 22 2009 + +Abc2midi produces the error message + found another |: after a |: +for the file + +X:1 +T:title +M:4/4 +L:1/4 +K:C +A2 c2 :: d2 c2 :| + +Fix: set bar_rep_found[voicenum] = 1 after inserting missing BAR_REP. + + + +September 20 2009 + +Abc2midi bug: the following file produces a faulty midi file. + +X:1 +T: bug +M: 4/4 +L: 1/4 +K: G +V:1 +%%MIDI control 7 49 +C4|\ +%%MIDI control 7 48 +C4|\ +%%MIDI control 7 47 +C4|\ +%%MIDI control 7 46 +C4| +%%MIDI control 7 45 + +Analysis: As seen below track 1 which contains only control codes is 56 beats +long while track 2 which contains the notes is only 16 notes. +The control codes in track 1 are not placed at the correct times. + + +ur@localhost abc]$ midi2abc err1.mid -mftext +Header format=1 ntrks=2 division=480 +Track 1 contains 57 bytes + 0.00 Metatext tempo = 120.00 bpm + 0.00 Metatext key signature G (1/0) + 0.00 Metatext time signature=4/4 + 0.00 Metatext (Seqnce/Track Name) bug + 0.00 CntlParm 1 Volume = 49 + 4.00 CntlParm 1 Volume = 48 + 12.00 CntlParm 1 Volume = 47 + 24.00 CntlParm 1 Volume = 46 + 40.00 CntlParm 1 Volume = 45 + 56.05 Meta event, end of track +Track 2 contains 67 bytes + 0.00 Metatext (Seqnce/Track Name) bug + 0.00 CntlParm 1 Volume = 49 + 0.00 Note on 1 c4 105 + 4.00 Note off 1 c4 0 + 4.00 CntlParm 1 Volume = 48 + 4.00 Note on 1 c4 105 + 8.00 Note off 1 c4 0 + 8.00 CntlParm 1 Volume = 47 + 8.00 Note on 1 c4 105 + 12.00 Note off 1 c4 0 + 12.00 CntlParm 1 Volume = 46 + 12.01 Note on 1 c4 105 + 16.00 Note off 1 c4 0 + 16.01 CntlParm 1 Volume = 45 + 16.06 Meta event, end of track + +Explanation: when abc2midi produces a type 2 MIDI file (multitracks), +track 1 only contains comments, time signature and control codes +while the other tracks contain the actual note-on/note-off codes +corresponding to the different voices. When abc2midi produces a +type 1 MIDI file corresponding to the bare bones abc file (no +voices or accompaniment), then there is only one track and +all note-on/note-off commands are in the same track. For +historic reasons, MIDI control codes are placed in both +track 1 and track 2 for voice 1, and the control codes for the +other voices are put into their own track. (I dare not +change this since it could cause a problem somewhere else.) +However, there appears to be a bug since the times of the +control codes seem to be incorrect. + +Fix: I reset delta_time to 0 at the end of the function +genmidi.c/dodeferred(). It seems to fix the problem. + + +October 23 2009 + +Abc2midi bug: the function dograce fails to adjust the length +of the host notes in a chord. In the following example + +X:1 +T: grace chord problem +M: 2/4 +L: 1/8 +K: C +A2 B2|{edc}[cg]2 d2| + +The chord [cg]2 is not shortened by the length of the grace +note {edc}; however if the chord is expressed as [c2g2] the +chord is shortened correctly. + +Analysis:the function applygrace_new() in store.c fails to +recognize the CHORDOFFEX feature which is used to express chords +of this type. Fix: the function now checks for that feature. + +December 12 2009 + +Abc2midi bug: dynamics (eg !pp!) deletes previous rest. +In the following example: + +X:1 +T: dynamic problem +M:4/4 +L:1/4 +K:C +|ABcd|Az3|!pp!dcBA|] + +The rest z3 is destroyed by the !pp! indication. Analysis: +this bug was introduced on September 20 2009 when +delta_time was reset to 0 in dodeferred(). Fix, a global +variable rest_pending was added to indicate that a rest +has not yet been instantiated in the MIDI file and not +to reset delta_time. The variable rest_pending is set to +zero for every NOTE, TNOTE or CHORDON feature but set +to 1 for a REST feature. +**note** this change was undone Feb 4 2010 + + +December 18 2009 + +Abc2midi bug: split voices (also known as voice overlay) works +incorrectly when there are in repeats. For example + +X:1 +T: voice overlay in repeats +M: 2/4 +L: 1/4 +K: G +|:C D &b/c/d/e/| F G:| + +used to work but now does not repeat the voice overlay. (It does not +matter whether an opening repeat |: is present.) However, if you +put a V:1 after K:G as shown here + +X:1 +T: voice overlay in repeats +M: 2/4 +L: 1/4 +K: G +V: 1 +|:C D &b/c/d/e/| F G:| + +it then works correctly. + +Analysis: this is a new bug that was introduced after the changes +on June 23 2009. The function scan_for_missing_repeats corrupts the +feature arrays. Here is the feature arrays just before calling +scan_for_missing_repeats. +0 LINENUM 2 0 0 0 +1 TITLE 0 0 0 0 +2 LINENUM 3 0 0 0 +3 LINENUM 4 0 0 0 +4 LINENUM 5 0 0 0 +5 DOUBLE_BAR 0 0 0 0 +6 LINENUM 6 0 0 0 +7 MUSICLINE 0 0 0 0 +8 BAR_REP 0 0 0 0 +9 NOTE 60 8192 1 1 +10 NOTE 62 8192 1 1 +11 SINGLE_BAR 0 0 0 0 +12 VOICE 2 0 0 0 +13 DOUBLE_BAR 0 0 0 0 +14 BAR_REP 0 0 0 0 +15 NOTE 83 8192 1 2 +16 NOTE 72 8192 1 2 +17 NOTE 74 8192 1 2 +18 NOTE 76 8192 1 2 +19 SINGLE_BAR 0 0 0 0 +20 VOICE 1 0 0 0 +21 NOTE 66 8192 1 1 +22 NOTE 67 8192 1 1 +23 REP_BAR 0 0 0 0 +24 VOICE 2 0 0 0 +25 REST 0 0 2 1 +26 REP_BAR 0 0 0 0 +27 VOICE 1 0 0 0 +28 MUSICSTOP 0 0 0 0 +29 LINENUM 7 0 0 0 +30 VOICE 2 0 0 0 +31 SINGLE_BAR 0 0 0 0 + +Here is the feature array afterwards. + +1 TITLE 0 0 0 0 +2 LINENUM 3 0 0 0 +3 LINENUM 4 0 0 0 +4 LINENUM 5 0 0 0 +5 DOUBLE_BAR 0 0 0 0 +6 LINENUM 6 0 0 0 +7 MUSICLINE 0 0 0 0 +8 BAR_REP 0 0 0 0 +9 NOTE 60 8192 1 1 +10 NOTE 62 8192 1 1 +11 SINGLE_BAR 0 0 0 0 +12 VOICE 2 0 0 0 +13 DOUBLE_BAR 0 0 0 0 +14 BAR_REP 0 0 0 0 +15 NOTE 83 8192 1 2 +16 NOTE 72 8192 1 2 +17 NOTE 74 8192 1 2 +18 NOTE 76 8192 1 2 +19 SINGLE_BAR 0 0 0 0 +20 VOICE 1 0 0 0 +21 NOTE 66 8192 1 1 +22 NOTE 67 8192 1 1 +23 BAR_REP 0 0 0 0 +24 REP_BAR 0 0 0 0 +25 VOICE 2 0 0 0 +26 REST 0 0 2 1 +27 REP_BAR 0 0 0 0 +28 VOICE 1 0 0 0 +29 MUSICSTOP 0 0 0 0 +30 LINENUM 7 0 0 0 +31 VOICE 2 0 0 0 +32 SINGLE_BAR 0 0 0 0 + +Note that feature BAR_REP was placed at 23 immediately before +REP_BAR. The problem is that the first VOICE 1 feature was found +after the first bar was processed and a split voice (VOICE 2) +was generated. scan_for_missing_repeats automatically places +a BAR_REP 3 indices past (24) the VOICE 1 (20) command which it expects +to be before the first note. This messes up the feature array. +If the abc file has a V:1 after the K: then the BAR_REP is placed +at the right place. + +Fix: Always place a VOICE 1 command after the first K: in the +abc file. In event_key (store.c) addfeature(VOICE, ...) after +getvoicecontext(1) if not inside body of abc file. (There may +be a K: indication inside another voice and we do not want +to automatically switch to VOICE 1.) ***This change was +removed on December 21 ***. + + + +December 20 2009 + +abc2midi bug: + + +X:1 +T: embedded V: command and voice overlay +%%MIDI program 2 41 +K:C +[V:1] | cde2 & egc'2 | C8 & z4 e'4 | c8 :| +[V:2] |C,D,E,2 | C,,8 | C,8 :| + +the voice overlay gets garbled but if we write +V:1 + | cde2 & egc'2 | C8 & z4 e'4 | c8 :| +V:2 + |C,D,E,2 | C,,8 | C,8 :| + +it works fine. In scan_for_missing_repeats changed + add_leftrepeat_at[num2add] = voicestart[voicenum]+3; +to + add_leftrepeat_at[num2add] = voicestart[voicenum]+2; + + +December 21 2009 + +abc2midi bug: abc2midi fails to convert the simple file + +X:1 +T: one track +M: 2/4 +L: 1/4 +K: C +CD|EF|GA|Bc| + +Fix: removed insertion of VOICE feature after the event_key. +instead event_key remembers the location to place a VOICE +feature in the variable v1index in case a event_split_voice +is encountered and voicesused is 0. + + +January 05 2010 + +abc2midi bug: loss of voice synchronization when stacatto, +chords and dynamics mixed. In the following example, + +X:1 +T:staccato and dynamics +M:4/4 +L:1/8 +K:G +V:1 +C4 G4|A4 G4| +V:2 +[.D4.G4]!p!C2C2|D4F4| + +the chord [.D4.G4] is one beat two short causing a loss of +synchronization between the two voices. However if abc2midi +is run with the option -NFNP which causes abc2midi to ignore +the dynamic indication !p!, the voices remain in synchronization. + +Analysis, the stacatto markings embedded in a chord causes +a REST feature to be embedded in the chord. +21 CHORDON 0 0 0 0 +22 REST 62 0 2 1 +23 NOTE 62 8192 1 1 +24 NOTE 67 8192 1 1 +25 CHORDOFF 0 0 2 1 +normally a stacatto places the rest after the shortened note +but for chords it is done differently. (It is rather unusual +to find stacatto markings inside a chord.) Nevertheless, the +notes are still played with the rest following. (Another +quirk of abc2midi.) +Fix: in writetrack() (genmidi.c) rest_pending is no longer +reset to 0 if the note is inside a chord. +**note** this change was undone Feb 4 2010 + + +January 06 2010 + +Abc2midi new feature: a missing Fermata in a multivoiced tune +can cause a loss of synchrony between the voices. As an aid +in detecting this problem, a new run parameter was introduced. +-NFEM will cause abc2midi to ignore all fermata markings in +the abc tune. + +Implementation: introduced a new global variable ignore_fermata +which is normally set to 0 into store.c. If it is nonzero, then +decorators[FERMATA] is ignored. + + +January 10 2010 + +Abc2midi new feature: though abc2midi should shorten the notes +preceded by a grace sequence in some circumstances it may fail +to shorten it the right amount causing the voice track to lose +synchrony with the other tracks. As an aid to detecting this +problem, a new run parameter was introduced. -NGRA will cause +abc2midi to ignore all notes in a grace sequence (enclosed +in curly brackets {}). + +Implementation: a new global variable ignore_gracenotes (normally +set to 0) was introduced in store.c. If both ignore_gracenotes +and gracenotes are nonzero, then event_note ignores the +current note. + + +January 14 2010 + +Abc2midi bug: the -NGRA option messes up the output abc file +for the following example. Track 2 is shorter than track 1. + + +X:1 +T:-NGRA option makes a mess +L:1/2 +M:2/2 +K:C +V:1 +|: {d-}[de]f|ga :| +V:2 +|: {E-}[EF]G|AB :| + +Analysis: (You should review the operation of dotie and tiefix as described +in this file at February 12 2005. Note the many other problems that +were encountered with this code.) Before calling tiefix, the feature +array looks as follows. + +(gdb) call dumpfeat(0,notes) +0 LINENUM 3 0 0 0 +1 TITLE 0 0 0 0 +2 LINENUM 4 0 0 0 +3 LINENUM 5 0 0 0 +4 LINENUM 6 0 0 0 +5 DOUBLE_BAR 0 0 0 0 +6 LINENUM 7 0 0 0 +7 VOICE 1 0 0 0 +8 LINENUM 8 0 0 0 +9 MUSICLINE 0 0 0 0 +10 BAR_REP 0 0 0 0 +11 GRACEON 0 0 0 0 +12 TIE 0 0 0 0 +13 GRACEOFF 0 0 0 0 +14 CHORDON 0 0 0 0 +15 NOTE 74 8192 2 1 +16 NOTE 76 8192 2 1 +17 CHORDOFF 0 0 2 1 +18 NOTE 77 8192 2 1 +19 SINGLE_BAR 0 0 0 0 +20 NOTE 79 8192 2 1 +21 NOTE 81 8192 2 1 +22 REP_BAR 0 0 0 0 +23 MUSICSTOP 0 0 0 0 +24 LINENUM 9 0 0 0 +25 VOICE 2 0 0 0 +26 LINENUM 10 0 0 0 +27 MUSICLINE 0 0 0 0 +28 BAR_REP 0 0 0 0 +29 GRACEON 0 0 0 0 +30 TIE 0 0 0 0 +31 GRACEOFF 0 0 0 0 +32 CHORDON 0 0 0 0 +33 NOTE 64 8192 2 1 +34 NOTE 65 8192 2 1 +35 CHORDOFF 0 0 2 1 +36 NOTE 67 8192 2 1 +37 SINGLE_BAR 0 0 0 0 +38 NOTE 69 8192 2 1 +39 NOTE 71 8192 2 1 +40 REP_BAR 0 0 0 0 +41 MUSICSTOP 0 0 0 0 +42 LINENUM 11 0 0 0 +43 SINGLE_BAR 0 0 0 0 + +Note that that there is a TIE feature enclosed in the GRACEON and GRACEOF +area but there is no NOTE or REST preceding. This is because we ran +abc2midi with -NGRA which had removed all the notes enclosed by the +grace complex. When dotie, attempts to process the TIE at 12 it fails +to find a NOTE or REST and exits; however when dotie attempts to +process the TIE as 30, it finds a NOTE in a different voice +at position 21 and all hell breaks loose a big mess. + +Fix: to prevent dotie from searching for a NOTE or REST in a previous +voice, we cause a break when feature[TIENOTE] == VOICE. + while ((tienote > 0) && (feature[tienote] != NOTE) && + (feature[tienote] != REST)) { + tienote = tienote - 1; + if (feature[tienote] == VOICE) break; /* [SS] 2010-01-15 */ + }; +to prevent a TIE from appearing in the first place in a grace +complex when -NGRA was specified we add +if (gracenotes && ignore_gracenotes) return; /* [SS] 2010-01-12 */ +in the event_tie() function. + + + +January 23 2010 + +Code clean-up to remove the numerous warnings when compiling +with the -Wall compilation flag. genmidi.c, mftext.c, midifile.c, +midifile.h, and store.c were modified. There are still a few +warnings to be checked out later. + + +February 01 2010 + +Code clean-up. Removed unused functions -- slurtotie(), applybroken(), +and delendrep() in store.c. + + + +February 01 2010 + +Abc2midi: support for multivoiced lyrics introduced. +The following tune illustrates multivoiced lyrics. + +X:1 +T:multivoiced lyrics +M:2/4 +L:1/16 +K:C +V:1 clef=treble +V:2 clef=treble +%%staves 1 2 +V:1 +C4 C4 | E4 G4 | c8 |] +w: 1 2 3 4 5 +V:2 +C4 E4 | C4 B,4 | C8 |] +w: 11 12 13 14 15 + +A warning "More than one voice with words in" appears. +Though the MIDI file plays properly, the lyrics do not appear +correctly in MIDI file players such as Melody Player. +It was necessary to some significant changes to +the way the information in the w: field is transferred to +the MIDI file in order to ensure compatibility. + + +This section describes how abc2midi treats the w: field in order to +incorporate lyric text into a karoake style MIDI file. For multivoiced +abc files, abc2midi only handles the lyrics in the first voice. There +is interest in generalizing the program so that it can handle lyrics +in multiple voices which are common in choir music. + +Parsing stage (store.c) +------------------------ + +All lyric text is copied into string array called words +char** words; +which is allocated by checkmalloc(maxwords*sizeof(char) +where maxwords is set to INITWORDS 20. + +Each time a w: field is encountered, event_words() in store.c is +invoked and places the string of text in the w: into +words[wcount] where wcount is incremented. A new feature, +WORDLINE is added to the feature array. The index wcount is +saved in the pitch[] component of the feature arrays. +If there is no continuation, of the w: command, then a +WORDSTOP feature is added to signal the end of the w: field. + +In the event that the wcount index reaches maxwords, the function +textextend() doubles the allocated space in words[] and doubles +maxwords. + +event_words() also verifies that the lyrics originate from only +one voice. + + +Creation of the MIDI file (genmidi.c) +------------------------------------- + +Genmidi records the MIDI tracks using the function writetrack() +which is called by mfwrite() in midifile.c. Mfwrite() was called +by finishfile() in store.c + +There is no one to one correspondence between voices and MIDI +tracks. Some voices may have two tracks. A voice containing +lyrics is mapped into two tracks, one for the notes and another +for the words. Two semaphores, wordson and noteson signal +writetrack whether to record only the words, only the notes or both +in the track. When writetrack scans through all the features +in the feat array for the specific voice, the NOTE: and TNOTE: +blocks inscribe the words or notes in the MIDI file depending on +the status of the wordson and noteon semaphores. +The gchord accompaniment is placed in a separate +track, gchordtrack which was set by finishfile() in store.c. The +voice containing the gchord indications is passed from store.c +to genmidi.c by means of the variable gchordvoice. The same applies +to drumtrack and dronetrack which rely on drumvoice and dronevoice +to establish the synchronization. + +The voice structures used in store.c are not passed to genmidi.c. +All the information for writing the MIDI tracks come from the +above semaphores and the feature,pitch,num,denom arrays which +were passed from store.c. Genmidi does not know whether it +is writing a split voice track (voice overlay) or a regular +voice track. They both look the same. + +Genmidi must know the number of tracks in the MIDI file since +this is recorded in the header chunk of the MIDI file. + +The current design of writetrack() assumes that if a lyrics +track exists it must be in track 2 (counting from zero). There +can be only one lyric track. + +To allow more than one lyric track (or voice containing lyrics), +to allow a track to have notes as well as words embedded requires +passing more information to genmidi. For instance we need to know +whether a particular track should record lyrics or notes, and +which voice number is the source. + +Changes: +------- + +Created a new function dump_voicecontext() in store.c which prints out +the descriptors of all the voice contexts. +Created a new structure trackstructure in store.c +struct trackstruct {enum {NOTES, WORDS, NOTEWORDS, GCHORDS, DRUMS, DRONE} tracktype; + int voicenum; + }; + +and a new array +Created struct trackstruct trackdescriptor[40]; +which will be shared with genmidi.c +Created a new function setup_trackstructure() in store.c which +modifies trackdescriptor[]. +Modified writetrack() in genmidi.c so that it can write more than +one lyric track. +Introduced an option to write lyrics in either the same track as +the notes or else in a separate track (-STFW). +Added "int hasdrums" to voice structure in store.c. +Added "int hasdrone" to voice structure in store.c +Cleaned out dronevoice, drumvoice, dronetrack, drumtrack, gchordvoice, +gchordtrack variables from store.c and genmidi.c +Removed warning "More than one voice with guitar chords in" + +One of the benefits of the new organization is that now you can +have drums and gchords in more than one voice as shown in the +following examples + + +X:1 +T: double gchords +M: 2/4 +L: 1/8 +K: C +V:1 +%%MIDI chordprog 1 +%%MIDI gchord fffff +"G" z4|z4| +V:2 +%%MIDI chordprog 90 +%%MIDI bassprog 90 +%%MIDI gchord ghii +"G" z4|z4| + + + +X:1 +T: drums in two voices +M: 2/4 +L:1/8 +K: C +V:1 +%%MIDI drum dddddddd 35 36 37 38 35 36 37 38 +%%MIDI drumon +|G4|G4| +V:2 +%%MIDI drum d2d2 40 41 +%%MIDI drumon +|C2D2|EFGA| + + + + + +February 04 2010 + +Abc2midi bug: the following tune is not converted correctly and +the drone is not heard. + +X: 129 +T: Drone Bug +M: 2/4 +L: 1/8 +K: Gdor +Q:1/4=140 +G\ +%%MIDI drone 109 67 67 50 50 +%%MIDI droneon +%%MIDI program 41 +| c2 c2 |(3cBA GB|c2 c2 |(3cBA GB | +%%MIDI program 111 +%%MIDI droneoff + +Analysis: this yet another bug introduced by the change in dodeferred +(September 20 2009). (See also December 12 2009 and Jan 05 2010). +Fix: in dodeferred replaced the lines +/********* delta_time = 0L; [SS] 2009-09-20 [SS] 2009-12-12*/ + if (!rest_pending) delta_time = 0L; /* [SS] 2009-12-12 */ + +with +if(wordson+noteson+gchordson+drumson+droneon == 0) delta_time = 0L; + +This is a better fix to the bug addressed on September 20 2009. +Removed the variable rest_pending and all references in genmidi.c + + +February 07 2010 + +Abc2midi: segmentation errors when applying abc2midi on a large +collection of tunes in an abc file. + +Analysis: two array index out of bounds problems were identified in store.c. +The variable num2add was not reset to 0 in the function scan_for_missing_repeats() +causing the array add_leftrepeat_at[100] to overrun when a large collection +of tunes is processed. (Also many spurious BAR_REP's are inserted into +the feature[] array.) A separate problem caused by insertion of BAR_REPs +is that the part_start[] array no longer points to the correct location +of the PART feature in the feature[] array. This causes fillvoice() to +induce a segmentation error because partlabel contains bad data. + +Fix: (1) reset num2add to 0 in scan_for_missing_repeats(), (2) add_missing_repeats() +also increments the addresses in part_start[] after each insert in the +feature[] array. As a precaution, fillvoice() in genmidi() reports an +error if variable partlabel is out of bounds. + +As a precaution v1index is also reset to -1 and splitdepth set to 0 in startfile(). + + +February 09 2010 + +Abc2midi bug: drum voice fails to materialize in this tune. + +X: 30 +T: Drum fails to materialize +M: 8/4 +L: 1/8 +Q: 1/4=120 +K: D octave=1 +%%MIDI program 74 +%%MIDI drum dzdzdzdzzzzzzdddd 41 43 41 43 45 45 45 45 +|:z2g2e2c2 gagfe2c2|\ +%%MIDI drumon +z2g2e2c2 gagfe2c2| +c2^d2e2ga g2^d2ccg2|\ +c2^d2e2ga g2^d2ccc2:| + +Analysis: setup_trackstructure() sets the number of tracks to +1 if there is no drumvoice, gchordvoice, karaoke, or dronevoice. +Unfortunately drumvoice was not set when %%MIDI drumon was +encountered. +Fix: drumvoice is set to v->indexno when %%MIDI drumon is found. + + + + +February 23 2010 + +Abc2midi lyric bug: abc2midi does not treat the double hyphen +in the w: line. In the following example + +X:1 +T: lyric bug +M: 5/4 +L: 1/4 +K: G +cdefg +w:one two--three four +the word four should be under the g note not f. + +Analysis: the problem occurs in the function getword() in genmidi.c. +After processing a syllable the second 'while loop' skips over +all following control codes. It should increment syllcount when +it encounters a hyphen so that another note will be skipped. + + +February 23 2010 + +Abc2abc does not copy s: and d: (symbols and decoration +lines) but instead puts a blank line. In the following example: + +X: 2 +T:Aaron's (Rarefied) Air +M:4/4 +L:1/4 +K:G +D|"G"DG "D7"FA|"G"G2 DD|G3/2A/2 Bc|\ +d3d|"C"e3/2d/2 ce|"G"d3/2c/2 Bd|"Am"cB AG|\ +s: .. .... .... .... +"D7"FG AD| + +abc2abc example.abc + + +abc2abc aaron.abc -t 2 +X:2 +T:Aaron's (Rarefied) Air +M:4/4 +L:1/4 +K:Amaj +E|"A"EA "E7"GB|"A"A2 EE|A3/2B/2 cd|\ +e3e|"D"f3/2e/2 df|"A"e3/2d/2 ce|"Bm"dc BA|\ + +"E7"GA BE| + +Fix: added event_field(key, place) to case 'd' and case 's' in +parsefield(key,field) in parseabc.c. + + + +March 27 2010 - contributed by Bas Schoutsen + +abc2midi now reads w: lines starting with hyphens, example: + +X:1 +K:C +A +w:la- +BcdA +w:---la + +X:2 +K:C +A +w:la-- +BcdA +w:---- +BcdA +w:--la + +Fix: introduced new global variable hyphenstate in genmidi.c/getword(). + + + +April 08 2010 contribution by Bas Schoutsen + +Abc2midi lyric bug: tied notes at the end of the line shifts the lyrics +one place further ahead in the following example. + + +X:1 +T: tie 2 +M:4/4 +L:1/4 +K:C +cdef-| +w:c d e x- +fgag +w:-g a g + +Fix: in genmidi.c a new global variable onemorenote +were introduced plus additional code in getword() and checksylables() +to handle the situation. + + +April 15 2010 + +Abc2midi: incompatibility with Melody Player, MidiNotate, NoteWorthy Player +and other commercial products. In the following example, + +X:1 +T:Zijn niet de tien gereinigd +C:Willem Vogel +M:C| +K:C +z4z2A2|[M:5/4]c4A2A2A2|[M:3/4]c4A2|[M:5/4]d4B2B2B2|[M:C|]e4A4|d4G4|c4B2A2|G6G2|A4E2E2|G4D4|E4F4|D8-|D8-|!fermata!D8|] + +the time signature 5/4 is placed at the beginning instead of the second +measure. + +Analysis, the MIDI meta Text event Time signaturea= 5/4 is +placed at MIDI Time = 1919 instead of MIDI Time = 1920. Apparently, when +the MIDI Player performs the division 1919/480 (where 480 is the number +of divisions per beat) the result is truncated instead of rounded. + +Fix, in set_meter(n,m) defined in genmidi.c, the last statement +was changed to + +mf_write_meta_event(delta_time, time_signature, data, 4); + +(delta_time replaces 0L.) + +**Note** this change was retracted on July 07 2010 and a +different fix was introduced. + +April 21 2010 + +Abc2midi bug: The fix described on April 15 2010 introduced a more +serious bug. In the following example + +X: 15 +T: Accompaniment starts at the wrong time +M: 2/4 +L: 1/8 +K: Am +%%MIDI program 57 +| CDEF|CDEF| CDEF|CDEF| +M:2/4 +%%MIDI drum dddz 35 48 60 +%%MIDI drumon +%%MIDI gchord fczz +%%MIDI bassvol 40 +%%MIDI chordvol 40 +|"D" dcBd |d2B2 |cBAc |B2A2 |\ + z2d2- |d2B2 |c4 |B2A2 | + +Both the drum and chordal accompaniment start 4 bars late. +If the second M:2/4 indication is left out, the accompaniment +starts at the correct time. + +Fix: in set_meter() the change +if (noteson) /* [SS] 2010-04-21 */ + mf_write_meta_event(delta_time, time_signature, data, 4); /* [SS] 2010-04-15 */ +else + mf_write_meta_event(0L, time_signature, data, 4); /* [SS] 2010-04-15 */ + +seems to fix the problem. + +**Note** this change was retracted on July 07 2010 and a +different fix was introduced. + +May 08 2010 + +Abc2midi new feature: the abc draft standard 2.0 + http://abc.sourceforge.net/standard/abc2-draft.html#K:%20-%20key +allows one to explicitly define all accidentals of a key signature +using the notation +K: exp +Thus K:DPhr ^f could also be notated as K:D exp _b _e ^f +where exp is an abbreviation for explicit. The standard states +that the notes should be in lower case; however, as a compatibility +measure with abcm2ps upper case notes are also allowed with +this feature. + +Fix: in parseabc.c (parsekey) checked for string "exp" and +set a new variable explict to 1 if the string is present. +Added the variable explict to the function event_key(..) +which is defined in store.c, toabc.c, yapstree.c, matchsup.c, and +parseabc.h. Note the applications abc2abc, yaps, abcmatch do +not support this feature presently. + + +May 20 2010 + +Abc2midi in compatibility. For the following example + + +X: 1 +T: Araber tants +R: Terkish +M: C +L: 1/8 +K: Dphr ^F +D2 "A"\ +| "D"FGA2 A2A2 | "Gm"B6 AG | "D"^FGA2 "Eb"BAGA | "D"GF3 z2D2 | + +abc2midi ignores ^F in the K: field command. The draft 2.0 standard +states that modifiers should be in lower case. Thus the K: field +should be written as +K: Dphr ^f +Since abcm2ps allows upper case modifiers too and distinguishes +them, I now allow both upper and lower case modifiers. +Fix: commented out +if (expict) in parseabc/parsekey(). +This also maintains compatibility with various Klezmer transcriptions. + + + +May 21 2010 + +Abc2midi bug: abc2midi crashes when the -c option (checking only) +is selected. eg. +abc2midi test.abc -c +Floating point exception + +Analysis: division by zero occurs when set_meter(header_time_num, +header_time_denom) because both input parameters are zero. These +parameters are not set when the c option is selected. + +Fix: in finishfile() (store.c) set header_time_num and header_time_denom +when check is set. + + if (check) { + Mf_putc = nullputc; + header_time_num = time_num; /* [SS] 2010-05-21 */ + header_time_denom = time_denom; /* [SS] 2010-05-21 */ + + + +May 24 2010 + +Abc2midi compatibility bug: the key signature +K:C^f^c +is not parsed correctly. (Such indications occur in many +Klezmer tunes.) Analysis: parsekey (in parseabc.c) expects +a space separating the key signature modifiers ^f and ^c. +Fix: readword() in parseabc.c was changed so that it splits +a string when it encounters '^' and '_' as well as '='. + + +May 26 2010 + +Abc2midi crashes with a segmentation error for file demo.abc +(included with abcMIDI package) when run on any specific tune eg. + +[seymour@localhost abc]$ abc2midi demo.abc 2 +writing MIDI file demo2.mid +Segmentation fault + +Analysis: abc2midi scans the entire demo.abc file. When it +encounters %%MIDI drumon in tune 7, it attempts to set +v->drumon = 1. The v structure has not been allocated, +so a null pointer is encountered. + +Fix: also tested the variable dotune in the following test + if (strcmp(command,"drumon") == 0 && dotune) { /* [SS] 2010-05-26 */ +in event_specific, in store.c. + + +May 31 2010 + +Abc2midi does not process K: field when key is missing but sharps +and flats are indicated explicitly. This typically occurs in some +Klezmer tunes. In the following example + +X:1 +T:explicit key +M:2/4 +L:1/8 +K:^c^d^e +CDEF|DEGA| + +abc2midi returns the messages + +Error in line 5 : First K: field must specify key signature +Warning in line 6 : Ignoring text: CDEF|DEGA| +Error in line 7 : No valid K: field found at start of tune + +and does not produce a MIDI file + +Analysis: the messages are produced when parsekey returns a zero +value for the flag gotkey. Fix: if parsekey succeeds in parsing +some information in the K: field (parse == 1), then gotkey is +set to 1 and sf is set to 0 (i.e. C scale). + + +June 26 2010 + +Abc2midi bug. Tempo command (eg Q:60) applied at the wrong place +in a multivoiced abc file containing a change in dynamics. In +the following example: + +X: 1 +T: Branles +M: 4/4 +L:1/8 +Q:1/4=110 +K:C +V:1 +CDEF GABc | CDEF !p!GA[Q:60]Bc | +V:2 +K:C +|[C,G,]4 [G,,F,]4 | [C,G,]4 [G,,F,]4 | + +the Q:60 is applied after the second note (D). + +Analysis: the !p! command resets delta_time to zero in track 1 (where +the TEMPO command is inserted) because of the line +if(wordson+noteson+gchordson+drumson+droneon == 0) delta_time = 0L; +at the conclusion of the function dodeferred (in genmidi.c). As a +result when TEMPO is encountered, delta_time only reflects the next two +notes GA after the !p!. Unfortunately, if we do not set delta_time +to 0L, then another bug comes back (September 20 2009). + +Fix: it is necessary to introduce another global delta_time_track0 +which is shared between genmidi.c and queues.c. delta_time_track0 +is updated by queues.c but is only used by the TEMPO command +in genmidi.c + + +July 1 2010 + +Abc2midi does not recognize tabs in field commands K: and V: +eg. + +X: 1 +T:Danse +M: 4/4 +L:1/8 +Q:1/4=110 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +V:1 nm=Oboe snm=Ob +V:2 nm=Basse snm=Bs +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +V:1 % Oboe +%%MIDI channel 1 +%%MIDI program 68 +K:Gm +GABc def2|edcd BcA2 | GABc def2|ec[Q:100]B[Q:90]d[Q:80] A[Q:70]F[Q:60]G2|] +V:2 % Basse +%%MIDI channel 2 +%%MIDI program 46 +K:Gm +[G,,D,]4 [G,,D,]4 |[G,,D,]4 [G,,D,]4 |[G,,D,]4 [G,,D,]4 |[G,,D,]4 +[G,,D,]4 |] +%%% + +Analyses: tabs instead of spaces occur after V:1 and V:2. Abc2midi +processes 1\tnm=Oboe as a single word etc. As a result abc2midi +identifies four voices instead of 2. + +Fix: in readword() (parseabc.c) added (*p != '\t') in the while +predicate. + + +July 07 2010 + +Abc2midi bug occurs when a rest is followed by a time signature. +In the following example: + +X:1 +T: time signature +M: 2/4 +L: 1/8 +K: C +V:1 +E2D2|[M:2/4] D2F2| +V:2 +z4|[M:2/4] f2e2| + +the rest z4 is held too long causing a loss of synchrony between the +two voices. If the following meter change is removed in the two voices, +the problem disappears. The rest is also held too long in the single +voiced tune (no V: command). + +Analysis: this bug was introduced with the April 15 - April 21 2010 +changes to write_meter() in genmidi.c (see above). Fix, I restored +write_meter() to its original state reintroducing the incompatibility +with Melody Player and several other players. + +To fix the incompatibility, delta_time was initialized to 1 instead +of 0 in writetrack() (genmidi.c). + + +July 11 2010 + +Abc2midi: new feature. Added warning "no default gchord string for this meter". +The message appears once if no gchord string could be set and a guitar chord +appears in the music. Implementation: the gchord string is set to 'x' by +default. If dogchords finds 'x' it outputs the message one time. + + +July 27 2010 + +Abc2midi: possible bug. No voice command assumed. In the following +sample: + +X:1 +T: voices +M: 2/4 +L: 1/8 +K: G +GABc|BAGF| +V:2 +FGAB|defg| + +tht V: field occurs past body; will include this body with this voice."); +1 voice command is missing after the K: G. abcm2ps understands +that there are two voices; however, abc2midi appends the second +voice to the first voice. Analysis: in order to handle named voices +parsevoice in parseabc.c assigns a sequential number starting from +1 to the first voice it encounters. This gets confused with the +body which also has the same voice number. I did not see any clean +way of fixing this problems; however, there is now a warning +in event_voice (store.c) when this potential problem occurs. + +{event_warning("First V: field occurs past body; will combine this body with this voice."); + +In order to detect this problem, it was necessary to introduce +the flag bodystarted. + + +July 29 2010 + +Abc2midi bug: in the following tune + + +X:1 +T: K: bug +M: 4/4 +L: 1/4 +K: E +V:1 +K: treble +EFGA|Bcde| + +the E major scale was not set up. Analysis: this bug was introduced +in May 31 2010. In the second K: command, parsekey (in parseabc.c) +sets sf to 0 and gotkey to 1. This forces event_key to change +the key signature to the C major scale. Fix: in order to handle +key signature mods, we introduced a new flag modnotes which is +set when it encounters a ^, _ or == in the K: command. If gotkey is +zero and modnotes is set, then explct is set to 1 so that +event_key will process the key signature modifications. + + + +August 12 2010 + +Abc2midi bug: delayed start of drum pattern for second voice. In the +following example: + +X:1 +T: drumbug +M:4/4 +L:1/1 +K:C +% +V:1 +%%MIDI drumon +%%MIDI drum d2zd 35 38 120 50 +%| +x|x| +% +V:2 +%%MIDI drumon +%%MIDI drum dzdz 67 68 100 80 +%| +x|x| + +the drum generator for the second voice begins one bar late. If you +remove the comment before the single bar in second to last line, +the second voice starts on time. + +Analysis: dodrums() in genmidi.c is called by progress_sequence in queues.c +provided the Q structure is not empty (Qhead not -1). In the case of +the first voice, the Q structure is setup by checkbar() in genmidi.c +because it was called by softcheckbar() when the DOUBLE_BAR feature +was encountered. For the second voice, no DOUBLE_BAR feature was +encountered, so the Q structure was not set up for the drum track. +If the voice starts with a single bar, checkbar() is called and +everything is properly initialized. + +Fix: added to starttrack() in genmidi.c + if (drumson) { /* [SS] 2010-08-12 */ + drum_ptr = 0; + addtoQ(0, drum_denom, -1, drum_ptr, 0); + } + +This seems to fix the problem. + + + + + +August 28 2010 + +abc2midi bug: voice splits does not work when the unit length +is not the default value 1/8. In the example + +X:1 +T: split voice bug. +K:C +L:1/2 +|:cd |1 c2 & e2 :|2 C2 & G2 |] + +The split voice was transformed with the wrong unit length. If +L: is set to 1/8 the MIDI file is correct. + +Analysis: +v->default_length has the wrong value for the split voice. + +Fix: in event_split_voice (store.c) v->default_length is transferred to +the split voice. + + + +August 31 2010 + +abc2midi bug: rests inserts after [Q:1/4=100]. In the following +example + +X:1 +T: Rallentando +M: 4/4 +L: 1/4 +Q:1/4=120 +K: C +C C C C | C C C C | C C C C | C C [Q:1/4=100]C [Q:1/4=80]C | C1 |] + +there is a large silent period inserted after the Q:1/4=100 command. +Inserting a V:1 after K: C fixes this problem. + +Analysis: this bug was introduced on June 26 2010 in effort to +fix a related problem. Unfortunately, for single track MIDI +files this caused another problem. + +Fix: if the MIDI file has only one track, the program reverts +to the old code. + + +September 28 2010 + +abc2midi bug: multiple repeats does not work correctly. In the +following example, + +X:1 +T: repeats +M: 2/4 +L: 1/8 +K: C +|:G2A2|[1,3 B2f2:|[2,4 B2c2:| + +G2A2 is played again after the last repeat. Analysis: in genmidi.c +maxrepeats was incremented to 5. Fix: limited maxrepeats to 4 or +less. (Note [1,3,5 does not work because inlist() in genmidi.c +does not check beyond two numbers.) + + +November 21 2010 + +abc2midi bug: when the path name to the abc file contains embedded periods, +eg. +"C:\Documents and Settings\midi.stadsmuur.INTERN.018\Local Settings\Temp\temp.abc" +abc2midi places the output midi file in the wrong folder +eg. +"C:\Documents and Settings\midi + +Analysis: the problem is in the code + *filename = argv[1]; + outbase = addstring(argv[1]); + for (j = 0; j< (int) strlen(outbase); j++) { + if (outbase[j] == '.') outbase[j] = '\0'; + }; + }; +in the function event_init() in store.c. + +Fix, the loop should go backwards and stop at the first period. + +outbase = addstring(argv[1]); /* [RM] 2010-11-20 */ + for (j = (int) strlen(outbase); j>0 ; j--) { + if (outbase[j] == '.') { + outbase[j] = '\0'; + break; + } + }; + +Thank you Reinier Maliepaard for identifying the bug +and proposing a solution. + + +December 07 2010 + +abc2midi: New feature: tempo indication compatibility with abc standard 2.0. +The standard allows the following syntax for the Q: command; + +X:1 +T:tempo +M:2/4 +L:1/4 +K:G +Q: "Adagio" +CD|EF| +Q: "Adagio" 1/4=40 +GA|Bc| + +Explanation: "Adagio" translates into 1/4=59. In the second Q: command, +1/4=40 overrides the default tempo for "Adagio". See abcguide.txt for +other tempo directives. Please note that the double quotes are +mandatory. + +Implementation: in store.c, translation tables temponame[] and +temporate[] were added; also the function get_tempo_from_name() +was introduced. + + + +December 10 2010 + +Abc2midi bug: abc2midi crashes if the above tempo descriptor +is not enclosed in double quotes. See example below. + + +X:1 +T:tempo causes crash +M:2/4 +L:1/4 +K:G +Q: Adagio +CD|EF| + + +Analysis: the segmentation error occurs in the new function +get_tempo_from_name(s) in store.c. The string s is empty nad +causes the program to crash when strcasecmp() is called. + +Fix: added the test + +if (s == NULL) return 0; /* [SS] 2010-12-10 */ + +in get_tempo_from_name(s). Now the program returns +Error in line 6 : malformed Q: field ignored + + +December 12 2010 + +yaps: bug. The following file crashes yaps. + +X:1 +T:yaps segmentation error +Q:1/4=60 +M:2/4 +L:1/16 +K:Bb +Q:1/4=60 +"F"F2FF AFAc |"Bb" B2 z2 B2 \ + z2 | z4 | +%%printtempo 0 + "Bb"((3_b2a2g2) f2d2 | B2BB dBdf | "F"F2FF AFAc | "Bb"B2z2 "D"A2z2 | +P:Accelerando --------------------------->---------------->----------------------- + [Q:1/4=65] "Gm"G2B2 G2B2 |[Q:1/4=70] "D"A2 D4 D2 |[Q:1/4=80] "Gm"G2B2 G2B2 |[Q:1/4=90] "D"d2z2 d4 | + +Analysis: yaps does not expect such a long label in the P: field. + +Fix: in event_parts(s), in yapstree.c, changed +char label[20] to char label[200]. + + + +January 1 2011 + +abc2midi irrelevant messages when running on a collection of tunes +in a file. (eg. "voice mapping ..." and "First V: field occurs past body..."). + +Analysis: the variable voicecode in parseabc.c was not reset to 0 when the +next tune was processed. Also the variable bodystarted in store.c +was not reset to 0 when the next tune was processed. + +Fix: in parseabc.c, call init_voicecode() after event_ref() called; +in store.c, set bodystarted to 0 in event_ref(). + + +February 21 2011 + +abc2abc : the program now attempts to transpose the key modifications +in the key signature. For example: K: Dphr^F will be transposed to +EPhr^G (for abc2abc -t 2). Explicit key modifications are also supported. +These key signatures are used a lot in Klezmer music. Unfortunately, +the algorithm does not always work correctly. Perhaps someone can help me. +All the new code is in toabc.c before the function event_key(). I +have given up in treating double sharps and double flat modifications. + + +April 14 2011 + +abc2abc bug: when using the voice extraction feature -V n, the program +still reports errors occurring in other voices causing some confusion. +In the following example, voice 1 has 5 beats instead of 4 in bar 1 +(we count from zero). + +X:1 +T: confusing error message +M: 4/4 +L: 1/4 +K: C +V:1 +ABcg|dcABE| +V:2 +Acde|feFE| + +When extracting voice 2: + +abc2abc xabc.abc -V 2 +X:1 +T:invisible note problem +M:4/4 +L:1/4 +K:C + +%Error : Bar 1 is 5/4 not 4/4 +V:2 +Acde|feFE| + +The error message applies to a problem in voice 1 even though the +program is extracting voice 2. + +Analysis, abc2abc processes the entire file but merely suppresses +all voices except the one requested. Error messages in other voices +are not suppressed. + +Fix: the flag output_on in toabc.c is used to suppress output of +the unwanted voices. The functions event_error(s) and +event_warning(s) now check both flags echeck and output_on +before printing. + + +April 14 2011 + +abc2abc bug: when extracting a particular voice, abc2abc fails to +print the part field command P:. In the following example, + + +X:1 +T: abc2abc missing part +M: 2/4 +L: 1/8 +K: G +P: Intro +V:1 +V:2 +V:3 +P:A +V:1 +V:2 +V:3 + +abc2abc pabc.abc -V 1 +X:1 +T:abc2abc missing part +M:2/4 +L:1/8 +K:G +P:Intro +V:1 +V:1 + +P:A is missing in the output, however + +abc2abc pabc.abc -V 3 +X:1 +T:abc2abc missing part +M:2/4 +L:1/8 +K:G +P:Intro +V:3 +P:A +V:3 + +P:A is present when the last voice is requested. + +Analysis: P:A is considered to be part of voice 3, so it was +suppressed when any other voice was extracted. + +Fix: the P: command should be treated as the start of a new +section so that the control flag output_on should be set to +1 whenenver this command is encountered. This occurs in the +function event_part() in toabc.c. + + +April 17 2011 + +abc2abc new feature: normally abc2abc converts all instructions +(decorations) like !ppp! to +ppp+ in order to comply with the +abc standard 2.0 which has deprecated the former convention. +A new option -noplus, causes abc2abc to use the deprecated convention +to represent all instructions and decorations. + +Implementation: a new global integer noplus was introduced in +toabc.c code. + + +April 17 2011 + +abc2abc bug: abc2abc fails to recognize clef=perc, eg. + +X:1 +T: clef= error +M: 2/4 +L: 1/8 +K: G +V:drum clef=perc +!f! CDEF| + +causes abc2abc to issue a warning + +%Warning : cannot recognize clef indication + + +Fix: added to isclef() in parseabc.c + +if (strncmp(s, "perc",1) == 0 && strict==0) { + gotclef = 1; + } /* [SS] 2011-04-17 */ + + + +April 18 2011 + +abc2abc bug: fails to transfer all voice parameters. In the +following example + + +X:1 +T: missing stafflines parameter +M: 2/4 +L: 1/8 +K: G +V:drum clef=perc stafflines=1 + CDEF| + +abc2abc fails to copy 'stafflines=1' to stdout. + +Analysis: parsevoice in parseabc.c ignores anything it does not +recognize. stafflines=1 is a parameter used by abcm2ps. + +Fix: +added to voice_params in parseabc.h + int gotother; + char other[V_STRLEN]; + +added to parsevoice(s) in parseabc.c + vparams.gotother = 0; + vparams.other[0] = '\0'; + if (!parsed) parsed = parseother()... + +introduced a new function in parseabc.c + parseother(); + +added to event_voice() in toabc.c +if( vp->gotother ) { sprintf(output, " %s", vp->other); + emit_string(output);} + +April 19 2011 + +parseother() in parseabc.c added check for break caused +by '='. + + +April 19 2011 + +Abc2midi: By popular demand the message +"missing BAR_REP for voice inserted for voice ... " +has been suppressed. The BAR_REP |: is still inserted +back when it is expected. (It could be inserted in the wrong place.) + + +April 29 2011 + +Abc2midi: Jurgen Schwietering has contributed the roll ornament for +the harp described here. + +The operation is quite simple, instead of generating a grace the ~ ornament on +harp is a roll with the same 3 notes (always) which can be quite accurately +transcribed as +~n2 := n/n/n (BTW played always with fingers 4 3 2 [a m i]) +~n3 := n/n/n2 (for dotted, execution same as previous) +It is NOT a movement done before the beat like graces. +It is very common among folk harpists. + +A new MIDI command +%%MIDI harpmode 1 +changes the ornament to harp mode. To switch back to regular mode, use +%%MIDI harpmode 0 + +Alternatively, you can specify the harp mode in the command line to +abc2midi, eg. + +abc2midi inputfile.abc -HARP + +Implementation: a new global variable harpmode was introduced which +is modified by the MIDI command or set in event_init() in store.c. +The function doornament() checks the harpmode flag and calls the +new functions makeharproll3() or makeharproll() in store.c. + +Here is a sample file to test this feature. + + +X:61 +T:The Glass of Beer +C:Reel, Trad. Irish +C:Arr. Gráinne Hambly +M:4/4 +L:1/8 +K:D +Q:1/4=130 +%%MIDI program 1 46 +%%MIDI harpmode 1 +~B3 ~B4 B| +~B2 B/B/B ~B4| +%%MIDI harpmode 0 +~B2 B/B/B ~B3 B| +~B2 B/B/B ~B4| + + +June 6 2011 + +Abc2midi bug: For the following file, + +X:1 +T:part not found +M:3/8 +L:1/16 +P:B +K:Dphr^f +%MIDI gchord fzz +P:A +"G"cdefga:| +P:B +M:2/4 +|:d4e4:| + +(Comment: a common trick in transcribing music to abc is +to temporary split it into parts so that you do not have +listen to the beginning each time you are checking it out. +The following problem occurs when you attempt to skip the +beginning.) + +abc2midi returns the error message +genmidi.c:fillvoice partlabel -55 out of range +genmidi.c:fillvoice partlabel -55 out of range +and the resulting MIDI file does not contain any music. + +Analysis: +The function findpart (in genmidi.c) looks for P:B in the +feature[24] which was its original location, unfortunately it +has been moved to feature[25] by add_missing_repeats() (store.c) +but part_start was not updated correctly. The problem is with the loop, +for (j=0;jD B,>D G>TB | GA Bc dc | GA Bc dc | +[V:2] B,>A, G,>A, B,>D | G,A, B,C DC | G,A, B,C DC | + +The problem also appears when trills are combined with grace +notes as illustrated here. + + +X:1 +L:1/8 +M:3/4 +K:Am +Q:1/4=60 +V:1 +c2 {d}TcB/c/ d>B | BA Ac e>d | +V:2 +A2{B}A^G/A/ B>G |^GE EA c>B | + + +Analysis: The trilled or rolled notes are expanded into a sequence of notes +as soon as they are detected. As a result, the grace or broken rhythm is applied +to the first note of this sequence. To fix this problem it is necessary +to expand trills and rolls after broken rhythms and grace notes are treated +rather than as soon as they are detected. + +Fix: (2012-05-29 to 2012-06-03) a new function expand_ornaments () +is called by finishfile() that converts trilled and rolled notes into +a sequence of notes. The defunct function dotrill() was split into +dotrill_setup() (called by event_note) and dotrill_output() called +by expand_ornaments(). Similarly, doroll() was split into doroll_setup() +and doroll_output(). Notes to treated by expand_ornaments() were +flagged using a new feature array called decotype[] which was checkmalloc'd +like stressvelocity, and pitchline. If the note was flagged it +is treated by either dotrill_output() or doroll_output() depending +on its type. + +The implementation was complicated by the problem, that the internal +representation of the music in the feature arrays does not preserve +the key signature information which is needed to decide whether to +ascend (descend) a tone or semitone in the trill or roll. Therefore +it was still necessary to analyze the context of the trill or roll +at the time of detection using the .._setup() functions and save +the generation parameters for .._output() in a specifically designed +struct called notestruct. These structures are generated as needed, +but a pointer array noteaddr[1000], (assuming not more than 999 +trills or rolls occur in a particular tune) is used to find the +struct. The notestruct struct thus acts as a bridge between the +setup and output functions. Treatment of microtones added another +complications and at this point I have not verified whether the +new code is correct with regard to microtones. + +There is still a synchronization problem when broken rhythms +are combined with ornaments as illustrated below. + +X:1 +T: ornament test +M: 2/4 +L: 1/8 +K: G +V:1 +D2 >~B2 |c2 G2| +V:2 +F2 >D2| e2 D2| + +Ornaments are handled in a different fashion. If harpmode is set, +then ornaments are expanded into a sequence of notes like trills +and rolls. If harpmode is not set, then a grace note is inserted +prior to the note and graceon() is called to make the final adjustments. +Furthermore if the note is dotted, then two grace notes are added. +For the present time you should avoid combining ornaments with +broken rhythms in multivoiced tunes. + + +August 08 2012 + +Abc2midi, yaps, abc2abc: The time signature C| or c| is now +interpreted as 2/2 instead of 4/4. + +Implementation: added another test in void readsig() in parseabc.c + + +October 03 2012 + +Chinese character support in lyrics was added to abc2midi by +Bow Yi Jang . Changes were restricted to +the function getword(.) in genmidi.c + + +November 03 2012 + +Abc2midi multirest bug. In the following example, + +X:1 +T: multirest problem +M: 2/4 +L: 1/8 +K: G +Z|G4|\ +M:3/4 +L:1/8 +Z|D6| + +The second multirest preceding D6 is held for two beats instead of +three and the warning +Warning in line 9 : Bar 2 has 2 units instead of 3 +appears. + +Analysis: the function event_mrest (store.c) uses the initial time +signature 2/4 stored in time_num/time_denom which does not get updated by +event_timesig() once the parser is in the body. abc2midi must keep +track of two time signatures: time_num/time_denom which is declared in +the initial field commands and mtime_num/mtime_denom which may be +updated in the middle of the body. The initial time signature, is +important for multivoiced tunes where the initial declaration is carried +to the start of all the voices. The active time signature +mtime_num/mtime_denom is only updated in the second stage in +set_meter() when genmidi is processing the feature[] array and +writing the MIDI tracks. However, the active time signature is +also needed when event_mrest is called to write multiple bars +of rests. Unfortunately, the active time signature was not maintained +during the initial parsing stage (first stage). + +Fix: the variables mtime_num and mtime_num are now also used +during the first pass and maintained in event_timesig(). event_mrest() +uses the active time signature mtime_num/mtime_denom rather than +the initial time signature time_num/time_denom. + + +November 08 2012 + +Abc2midi: multirest bug part 2. The problem with meter change and +multirests persists in multivoiced tunes. In the following example, + +X:1 +T: Multirest bug part 2 +M:C +L:1/4 +K:F +V: 1 +V: 2 +%%MIDI program 1 73 +%%MIDI program 2 40 +%%staves [{ 1 2 }] +[V: 1] F A z c| z4 | [M:3/8][L:1/8] F/>G/ FA|B/>c/ BA | G/>A/ GF|C3|] +[V: 2] A F3 | Z | [M:3/8][L:1/8] Z | G/>A/ GA | B/>c/ BA | G3|] + +The first multirest Z in voice 2 is held for 3/8 instead of of 1/4. + +Analysis: voice 1 changes mtime_num/mtime_denom to 3/8 and it +remains in that state at the start of voice 2. + +Fix: new variables int active_meter_num, active_meter_denom are +introduced into the voicecontext struct. They are used to maintain +the values of mtime_num and mtime_denom over voice switches. + + +November 15 2012 + +Abc2midi extension: abc2midi treats Xn the same way as Zn, to be +compatible with the new version of abcm2ps. Fix in parseabc.c added +case 'X': /* [SS] 2012-11-15 */ +after case 'Z': + + +November 21 2012 + +Abc2midi: verbose option provides more detail if set to 4 or 5 for +tracking segmentation errors. + + + +November 22 2012 + +The fixes for the following two problems were provided +by Philippe De Muyter. + +The input line size in parseabc.c was increased from 256 to 512 +to accommodate abc files that are automatically generated (eg midi2abc). +char inputline[512]; + + +Abc2abc truncates the voice ids when it encounters the first +invalid character without giving any warning. eg. + +X:1 +T: invalid voice +M: 2/4 +L: 1/8 +K: G +V: A_1 +abcd| +V: A_2 +DEFG| + +only one voice is detected. + +Fix: +In interpret_voicestring() in parseabc.c the following code was added +after c = readword(code,s); + +if (*c != '\0' && *c != ' ' && *c != ']') { + sprintf(msg, "invalid character `%c' in Voice ID", *c); + event_error(msg); + } + +Now abc2abc and abc2midi complain that they encountered an invalid +character. + + +November 23 2012 + +abc2midi bug: unable to trill or roll tied notes. In the following +example + +X:1 +T:trill-issue +M:2/4 +L:1/8 +K:F +V: 1 +z4|z3d| +V: 2 +%%MIDI program 1 73 +%%MIDI program 2 40 + TF2 Tc2-| c Tf2-f| + +The tied notes c2-c and f2-f do not get trilled. + +Analysis: this bug was introduced on July 03 2012 in the attempt +to fix other problems associated with trills. The function +expand_ornaments() only processes NOTE features and ignores +TNOTE features used to designate tied notes. + +Fix: The solution is to change TNOTE to a NOTE. However, +writetrack() in genmidi.c processes TNOTE features in a special way +in order that checkbar() will work when a tied note extends +over a measure. The TNOTE invokes a midi on command but a midi +off command is deduced from the following REST(s) which are +associated with the tied note. Therefore, if we change TNOTE +to a NOTE we also need to eliminate the REST(s) which are +part of the TNOTE sequence. This is done by a new function, +convert_tnote_to_note(). Unfortunately, this is not a clean fix. +Checkbar() will give a misleading message when the tied note +extends over a measure. Also, lyrics may not align correctly +with tied and trilled notes. It gets messy to make expand_ornaments() +to split up a trill across a measure. + + +November 25 2012 + +Abc2midi: the compiler on Windows PC does not initialize arrays +to zero when they are allocated. As a protection the arrays the bentpitch +and decotype are now initialized to 0 when they are allocated. +Some array pointers are now checked for valid values. + + +December 01 2012 -- submitted by Philippe de Muyter + +abc2abc truncates a line to 512 characters without warning in the +-P mode. (This is the continuation of the changes November 22 2012.) + +Analysis event_error is muted during the output so it is necessary +to simulate it with a plain printf in the function print_inputline_nolinefeed() +in the file parseabc.c. + +December 11 2012 + +abc2midi: bend note, new feature. Placing the instruction !bend! slides +the pitch of the following note up. + +For examples: + +X:1 +T: pitchbend +M: 6/8 +L: 1/8 +K: Gdor +%%MIDI program 78 whistle +%%MIDI transpose 12 +DEF G3|DEF !bend!G3| + +the second G is slid up. + + +Implementation: added a new function note_effect to queues.c which +is called by timestep(). Note effect inserts a sequence of pitch bend +events prior to sending a MIDI note off. Added a new integer member, +effect, to struct Qitem. The flag, effect, determines whether note_effect +is invoked. An additional parameter, effect, was added to the function +addtoQ which is also defined in queues.c. The function addtoQ is called +in many places in genmidi.c. In abc.h added a new feature called +EFFECT. The feature is inserted before a note when the instruction +!bend! is encountered -- see event_handle_instruction() in store.c. +In genmidi.c added a global flag, effecton, which is usually set to +zero except when the EFFECT feature is encountered. The NOTE: handler +in writetrack returns effecton in one of the addtoQ function +calls. + + +December 12 2012 + +abc2midi: bend configuration. Introduced two variables bendvelocity and +bendacceleration into note_effect. Note_effect inserts 8 MIDI pitchbends +equally spaced inside a note. The pitchbend is initialized to the neutral +value of 8192. During the loop repeated 8 times, pitchbend and +bandvelocity are incremented as follows. + +pitchbend = pitchbend + bendvelocity +bendvelocity = bendvelocity + bendacceleration. + +The pitchbend is limited between 0 and 16383 usually corresponding +to a negative and positive shift of two semitones on most General +MIDI instruments. + +The variables bendvelocity and bendacceration can be set by the +following %%MIDI command. + +%%MIDI bendvelocity n1 n2 + +where the integers n1 and n2 are the velocities and acceleration +respectively. By default, n1 and n2 are initialized to 100 and 200. + + +December 25 2012 + +Abc2midi part/trill bug. Introducing trills or ornaments in a +multipart abc file causes erratic behaviour. For example, + +X:1 +T:parts +M:2/4 +L:1/8 +P:B +K:C +P:A +CDEF|TGABc| +P:B +cBAG|FEDC| + +Part B is not played when the trill is present in part A. + +Analysis, abc2midi stores the start position of each part in +the array part_start during the parsing stage. Unfortunately, +things may move around during the later stages. The function +expand_ornaments() inserts additional notes in the feature +arrays when it does its expansion. This shifts the position +of the parts and the information in the part_start array is +no longer valid. + +Fix: created a new function fix_part_start() in store.c which +is called after expand_ornaments() in finishfile(). + + +Jan 27 2013 + +Abc2midi: the abc2midi allows but does not recommend the tempo +command to just specify a number. eg. Q:320. abc2midi automatically +assumes that this number refers to a quarter note; however, +the abc standard 2.0 specifies that it should refer to the unit length +specified by the L: command prior to the body. + +Fix: in parseabc.c changed a=1 to a=0 in the function parse_tempo(). +The existing code in tempunits() in store.c does all the rest. + +Jan 28 2013 + +Abc2midi: the above change was withdrawn since there is disagreement +between abc standard 1.7.6 and abc standard 2.0. + +February 25 2013 + +Abcmatch: introduced -wpitch_hist runtime parameter for computing +the pitch histogram weighted by the note length. Some minor clean-up +of the output. + +February 26 2013 + +Abcmatch: negative array index fixed in abcmatch.c (compute_note_histogram). +Problem is exposed on Windows operating system. + + +March 08 2013 -- patch submitted by Philippe De Muyter + +Abc2abc: the -V and -P options have been generalized so that more +than one voice can be selected using a comma separated list. + +Implementation: + +The long global variable selected_voices represents the selected +voice in a bit map. Each bit in the word corresponds to a specific +voice number. Two new functions are introduced. parse_voices_selection +parses the voices_string in the -P or -V command and converts it +into the bitmap in the selected_voices variable. must_emit_voice(n) +examines the n'th bit of the selected_voices and indicates whether +it is on or off. The other change is the replacement of the control + +- if ((selected_voice != -1) && (n != selected_voice)) { +with ++ if (!must_emit_voice(n)) { /* [PHDM] 2013-03-08 */ + + + + +March 10 2013 -- also submitted by Philippe De Muyter + +abc2abc: fix chord's tuple length calculation + +Up to now, bar length was increased at first note of chord, and +tuple status was lost at first note of last chord. When a chord +in a tuple had a length modifier, the resulting bar length +was wrong, which caused wrong error messages. + +With + X:1 + T:wrongbarlengtherror + M:4/4 + L:1/8 + K:C + z8 | z6 (3 [fd]/ [fd]3/ [fd] | z6 (3 [f/d/] [f3/d3/] [fd] | +abc2abc gave a wrong message : + %Error : Bar 1 is 13/12 not 4/4 + +Fix that, by incrementing bar length and decrementing `tuplenotes' at +chordoff time, not at first chord note. +Move also the tuple-implied length conversion in `addunits', to +avoid code duplication. +Because there are two ways to specify a chord length, + [c2e2g2] +and [ceg]2 +in the first case, we must now memorize the note length to be able +to retrieve it at chordoff time; this is done in the new +`chordfactor' variable. + +Additionnaly, as 'addunits' is only called when we know the exact length +of a note or chord, `repudiate_lastaddunits' is now useless and removed. + + + +March 14 2013 + +Abc2midi: part/repeat bug. In the following example + +X:1 +T: Part - repeat bug +Q:1/2=120 +M:2/2 +L:1/4 +K:D +%%vskip 0 +P:Intro +|: "Em"e4 || +P:A +|| "D"d4 :| + +abc2midi returns the following messages: +Error in line 12 : found another |: after a |: +Warning in line 12 : Assuming repeat +Warning in line 12 : replacing with double repeat (::) +writing MIDI file temp21.mid + +Furthermore, the e4 in the Intro is repeated and then the D4 +in part A is repeated. Since the P: are only labels here +(there is no P: command preceding K:), it was expected that +the entire the tune would be played as +|: "Em" e4 | "D" d4 :| + +Analysis: the function scan_for_missing_repeats() which was +introduced in June 23 2009 is the source of the problem. The +function assumes that the tune is actually in two parts and +inserts a |: in the beginning of part A. When fixreps() is +called it discovers that two |: occur without an +intervening :|, so it decides to replace the second |: with +a double repeat ::. (Note that fixreps() would not be called +if the parts were real and not just annotations.) + +Fix: +The useless conditional statement +if (J == PART || j == VOICE || j == BAR_REP etc. +was commented out since it does nothing. +In the following statement, an additional check parts != -1 +was added. If parts == -1, this implies that the part indications +are merely annotations and do imply a real part as abc2midi is +concerned. Therefore bar_rep_found[] and voicestart[] are not +cleared again, implying that a |: may need to be introduced at +the beginning of the part if the part ends with a :|. + + + + +March 20 2013 + +Abc2midi: invisible and visible multirest confusion with field commands. +Z and X are used both as field declarations (X: reference number +and Z: transcription source) and as multirests in the body. In unusual +cases where the multirest is followed by a repeat sign and happens +to be at the beginning of a line, it can cause confusion. For example, + + +X:1 +T: rests +M:3/4 +K:C +c6|e6|^g6|\ +X ::\ +C6|e'6|^G6|\ +Z :|\ +[CE^G]6|] + + +X:2 +T:rests +M:3/4 +K:C +c6|e6|^g6|\ +X1::\ +C6|e'6|^G6|\ +Z1:|\ +[CE^G]6|] + +are two examples which abc2midi fails to interpret correctly. parseline() +in parseabc.c attempts to treat X :: and Z :| as field commands even +though they are malformed. Abc2abc also does not produce correct output. + +Fortunately parseline issues warnings + +Warning in line 8 : whitespace in field declaration +Warning in line 8 : potentially ambiguous line +Error in line 8 : Missing Number + +and the transcriber is urged to reformat the line to avoid this problem. + +Fix: I am not sure whether I should fix this problem. In any case, +I have put a small patch in parseline() so that the above examples +are treated correctly. + + +March 21 2013 + +abcmatch: several bug fixes and a new feature -pitch_table. +Given a file containing a collection of tunes eg. Modes.abc, +abcmatch Modes.abc -pitch_table +will output the interval weighted pitch histogram for each +tune. If the output is stored in a separate file, eg. Modes.tab, +this table could be used for searching for the tune having the +closest matching pitch histogram (a feature to be introduced +in runabc). + + + +March 26 2013 + +abc2midi bug: if a chord is preceded by a Roll or Trill indication, +abc2midi fails to encode the chord in the MIDI file. + +For example: + + +X:1 +T: chordtrill +M: 4/4 +L: 1/8 +K:C +V:1 +%%MIDI program 16 +T[ceg]4 [AEc]4 :| +V:2 +%%MIDI channel 10 +GA GA GA GA :| + +A warning is issued that trills and rolls are not implemented for +chords, but [ceg]4 is not encoded in the MIDI file. + +Fix: in event_note, in store.c added the lines + + pitchline[notes] = pitch_noacc; /* [SS] 2013-03-26 */ + bentpitch[notes] = active_pitchbend; /* [SS] 2013-03-26 */ + addfeature(NOTE, pitch, num*4, denom*2*(v->default_length)); /* [SS] */ + +following the statement + event_error("Rolls and trills not supported in chords"); + + +April 10 2013 + +Abc2midi: new feature. Added a new runtime option -CSM . +This option allows one to customize the BarFly stress models by +providing an external file. + +Background: the 32 stress models are presently built-in the source +code in the file stresspat.c. This has the advantage that executables +can be distributed without an auxiliary data file containing +the models. However, the user does not have much leeway to alter +the models or add additional stress models. The -CSM feature +addresses this limitation by allowing the user to add more +models for other rhythm designators (eg lesnoto), and to alter +one or more of the existing models. There is room to add up to +16 additional models. The feature requires the user to specify +a text file which contains these models. + +Description of the external file and how it works is given +in abcguide.txt and a sample of such a file is given in the +pt folder (customstress.txt). + +Implementation: a new function read_custom_stress_file() +was introduced in the file stresspat.c. Assuming the file +conforms exactly with the expected format, the function +reads all the models provided. For each model, if the rhythm +designator and meter conflict with one of the existing standard +models, the function will update the characteristics of that model. +Otherwise the function will append the model to the current +list. + + +April 11 2013 + +Corrected a minor error in init_stresspat() (Tango) in stresspat.c. +As a convenience, I have produced default_stress.txt in the format +that read_custom_stress_file() accepts. Default_stress.txt contains +the built in models to abc2midi. You can find the file in the pt (Phil +Taylor) folder. + + +April 17 2013 + +Abcmatch: numerous bugs fixed. Introduced a new matching -norhythm. +The matching algorithm ignores the length of the notes and only +matches the sequence of pitches in a bar. The file abcmatch.txt +was updated. More internal documentation was added in abcmatch.c + + +April 20 2013 + +Abc2midi bug: combination of chords and broken rhythm. In the +following example, + +X:1 +T: broken rhythms +M: 2/4 +L: 1/8 +K: F +[DF]2 > [CE]2| + +The second chord [CE]2 begins before the end of chord [DF]2. + +Analysis: the function brokenadjust() (store.c) is called +to adjust the lengths of the notes to effect the broken rhythm. +It adjusts the notes inside the chord but fails to adjust the length +associated with the CHORD (CHORDOFFEX feature). This causes +timestep() in queues.c to be called too early, causing the +second chord to start to early. + +Fix: in the function lenmul() added another condition, + || (feature[n] == CHORDOFFEX)) /* [SS] 2013-04-20 */ + + +April 21 2013 + +Fixed: a potential memory overflow in parsing the repeat string. +In getrep() (parseabc.c) ensured the array index for playonrep_list +does not exceed 50. + + +April 24 2013 + +Suppressed warning in abc2midi. For the following example, + +X:1 +T:TEST TUPLES +M:2/2 +L:1/4 +Q:1/2=80 +K:G +[F,A,D] (3[df]/[eg]/[^e^g]/ [fa][CF] | +[F,A,D] (3[d/f/][e/g/][^e/^g/] [fa][CF] | + +abc2midi issues the following warnings. +Warning in line 7 : Different length notes in tuple for chord +Warning in line 7 : Different length notes in tuple for chord +Warning in line 7 : Different length notes in tuple for chord + +Analysis: the message is issued when closing each of the +tuple chords in the first line. The length of the note in the +tuple is stored in the variables tnote_num, tnote_denom when +the first tuple note is encountered. Unfortunately when +the chord note duration is applied (here one half), the +note length no longer matches the stored values tnote_num +and tnote_denom and a warning is sent. The output midi +file nevertheless correct. + +Fix: abc2midi stores the note length of the tuple in tnote_num, +and tnote_denom. A chordoff feature can modify the value of a tuple +note (i.e. chord) if its length is indicated outside the chord (eg. +[CE]3/2. If the modified chord length does not match the stored value +tnote_num, tnote_denom set by event_note, a warning is issued. +It is getting too complicated to keep track of a tuple note +inside and outside a chord, so I have decided to just suppress +the error message for tuples of chords. (i.e. I would have to +make extensive changes to the logic of the program to get it working +properly.) + + + +May 07 2013 + +Abcmatch: introducing -fixed runtime parameter. It allows +matching to go across a bar line. See doc/abcmatch.txt for +more information. + + +May 10 2013 + +Midicopy: bug in extracting a segment of a MIDI file. When +the segment starts in the middle of a note playing, it causes +a loss of synchronization between the tracks. + +Analysis: there was an attempt to write a negative MIDI time +increment when Mf_currcopytime exceeds Mf_currtime. + +Fix: set negative values to zero in the function WriteVarLen(value). + + + +June 06 2013 + +Abc2midi: potential segmentation error when applying stress model. +The following tune contains stray text which abc2midi assumes +to be part of the body of the tune. + +X: 157 +T: Cliffs of Moher +N: page 51 +R: jig +M: 6/8 +K: Ador +"Am"eaa bag| (4efaf "G"ged| "Am"c2A BAG| "Em"EFG ABc|\ +"Am"eaa bag| (4efaf "G"ged| "Am"cAA BAG| "Em"EFG "Am"A3 :| +"Am"efe dBA| efe dBA| "G"G2d dBA| GAB dBd|\ +"Am"efe dBA| efe dBA| "G"GAB dBG| "Em"EFG "Am"A3| +~e3 dBA|~e3 dBA|"G"~G3 dBA|GAB dBd|\ +"Am"efe dee|cee Bee|"G"EFG BAG|EDB, "Am" A,3| +This abc file is used to generate the MIDI files and pdf file for volume 2 +of the music collection used by the Ottawa Slow (Celtic) Jam. +The file is derived from +http://www.ceolas.org/pub/tunes/abc.tunes/sessionTunes.abc + +When the stray text is processed in the Barfly mode (-BF), +the array index to the variable fdursum exceeds the allocated +memory 32 which can cause a segmentation error on some +systems. + +Fix: in the function fdursum_at_segment in genmidi.c, replaced +inx0 = inx0 - nseg; +with +inx0 = inx0 % nseg; /* [SS] 2013-06-07 */ +which is executed if inx0 > nseg. + + +June 09 2013 + +Abcmatch: in -br mode the program returns both the number of matching +bars in the tune and template. + + +September 04 2013 + +Midicopy: new feature. Introduced the run time option -tempo n (beats/min). When +this option is included all tempo messages in the midi file are +replaced with the specified value. + +Implementation: in metaevent() when a tempo message is encountered, +if newtempo is greater than zero, write the newtempo value instead +of the value in the source midifile. The value of newtempo is set +by the -tempo run time option. + + +September 06 2013 + +Midicopy: new feature. Introduced the run time option -speed f (multiplier). +When this option is included all tempo messages in the midi file are +are multiplied by the factor f where f is a floating point number between +0.05 and 10.0. This speeds up or slows the music by this factor. + + +September 07 2013 + +Midicopy: new feature. Introduced the run time option -drumfocus n m +where n is the pitch code of the selected drum line and m is the velocity +value to be applied to all other drum lines. The feature, highlights +the selected drum line by attenuating all other drum lines by playing +them at level m (m varies from 0 to 127). + +Implementation: the velocities of the other drum lines are set to +m in function chanmessage() prior to sending a 'note on' message. + +September 08 2013 + +Midicopy: fixed function tick_to_seconds so it returns the correct +time when the tempo is changed by -tempo or -speed. + + +September 10 2013 + +Midi2abc, midicopy: bug fix. Midi2abc or midicopy may fail for some +midi files which use the running status. A few midi files attempt +to save a few bytes by not transmitting the status byte for a channel +message when status byte has not changed. For clarification, the +status byte contains the channel message like "note on channel 10". +The status byte is followed by one or two data bytes specifying the +particular note it applies to and the velocity value. Since +data bytes are restricted to 6 bits and status bytes always +contain a value exceeding 6 bits, it is easy to tell when a status +byte is missing. The running status, saves a few bytes when +several notes in a chord are turned on (or off) at the same time. +The bug occurred when a metatext message is inserted inside +a running status complex (eg. note on channel 10, metatext, note on +channel 10). Midi2abc and midicopy abort with the message +"unexpected byte 0x..". + +Analysis: the bug was traced to the code writetrack() in midifile.c +and also midicopy.c. It is necessary to store the last status byte +that occurred in the last channel message. Note a metatext message +is not a channel message. A new local variable, laststatus, was introduced +in the code. + + +September 15 2013 + +Midicopy: new feature. Added an option -mutenodrum [level] to mute +all channels to velocity level if the channel is not 9 (drum channel). +If level is not provided, it is set to zero. + + +Ocotober 1 2013 + +Midicopy: new feature. Added the option -setdrumloudness n m +where n is the drum number between 35 and 81 inclusive and m +is the new velocity between 0 and 127, All instances of the +selected drum are assigned the given loudness (velocity). + +October 15 2013 +Abcmatch: new feature. Added options -interval_hist and +-interval_table to analyze the pitch intervals between +adjacent notes. The program produces a histogram of the +note intervals in MIDI (semitone) units. + + +October 22 2013 +Abcmatch: new feature. Added the option to accept +a certain number of insertion, deletion, and substitution +errors using the Levenshtein distance measure. + + +October 28 2013 +Midicopy: new feature: added the option to list the tracks +to exclude from copying. eg. -xtrks 4,5 indicates to copy +all tracks except 4 and 5. + + +October 30 2013 +Abc2midi: bug fix. A key change in the middle of a tune does +not propagate to the split voice. In the following example, + + +X:1 +T:Test +L:1/4 +M:2/2 +Q:1/2=110 +K:C +V:1 +C4 | [K:Bb]B4 & B,4 | + +B,4 was not flattened. + +Analysis: the key change [K;Bb] was not propagated to the split +voice. + +Fix: in event_split_voice() in store.c, the active basemap and basemul +arrays for the voice was saved in a temporary area and transferred +to the split voice. + + +October 31 2013 + +abc2midi and yaps bug: for the following example, + +X:1 +T: :|] ending +M:C +N:Portland p.19 +R:march +K:D +|:"G" b2a2 "A"g2e2| "D"d4 d4 :|] + +abc2midi returns the error +Error in line 10 : Chord already finished +and +yaps returns the error +Error in line 7: no chord to close + +Analysis: these are extraneous error messages. Parsemusic() in +parseabc.c detects the THIN_THICK bar line |] but does not +detect it when it is preceded with ':'. +Fix: check for ']' in this case and skip over. + + +November 02 2013 + +Abc2midi: some instructions which are meaningful to abcm2ps are +meaningless to abc2midi and cause a warning. In the following +example, abc2midi cannot interpret !4! and !0!. + +X:1 +T: instructions +M: 4/4 +L: 1/8 +K: A +"E"FEF(G "A" A2) !4!!0! [A2A2]| + +Warning in line 6 : instruction !4! ignored +Warning in line 6 : instruction !0! ignored + +Analysis: event_handle_instructions(s) in store.c issues this +warning when it cannot interpret this message. + +Fix: the message is suppressed if -quiet is included in +the runtime parameters. + + + +November 2 2013 + +abc2midi indicates the wrong line number in a warning. In +the following example, + +X:1 +T: Slurs +M: 2/4 +L: 1/8 +K: F +z(GFE +|:DE) FG| +AB (3cBA:| + +abc2midi returns the message +Error in line 8 : Unexpected end of slur found + +The end of slur is actually in line 7. + +Analysis: on the second repeat, no slur was started so an end of +slur is not expected - but the line number in the error message +is wrong. The repeat :| causes writetrack (in genmidi.c) to backtrack +it restores the state variables to the condition where the opening +repeat sign |: occurs but the state variables do not include the +line number used by the warning or error message. + +Fix: expanded the functions save_state() and restore_state() so +that the line number can also be saved. + + +November 4 2013 + +abc2midi bug: A bug was detected when abc2midi is run with the Barfly +stress model (-BF 1). For the following file t.abc + +X: 1 +T: Barfly implementation bug +R: jig +M: 6/8 +L: 1/8 +K: G + |: "C"c3 "G/B"B3 | "D7/A"AGF "G"GBd :| + +abc2midi t.abc -BF 1 +the note c3 or B3 may be inaudible in some instances. + +Analysis: the local variable vel in the function noteon() may end +up being undefined. In certain cases stress_factors() called +by noteon() may not set the variable vel, in which case +we expect note_beat() to be called. Unfortunately, if vel +was initially nonzero note_beat is note called and vel +has a random value. + +Fix: initialize vel to 0 in noteon(). + + +November 04 2013 +yaps fix: On January 16 2006 an option to display the notes in +red was introduced. This code did not work well because the +other musical components were also colored red. The problem +was fixed by maintaining the color in black and temporarily +switching the color to red when a note, beam or rest is +drawn. A new variable redcolor was introduced in drawtune.c +and set by the !red! command and reset to zero by !black!. +The functions drawnote(), drawrest, and drawbeam() test this +variable and switch the color to red on a temporary basis in +order to draw the object. + + +November 12 2013 +abcmatch.c improvement. When running in absolute versus contour +mode, abcmatch frequently transposes in the wrong direction when +the key signatures differ since it does not know which direction +to go. abcmatch now transposes in the direction of minimum distance +between keys. + +For cut time C| abcmatch translates it to 4/4 rather than 2/2 +so it can find more matches. Both changes are in abcmatch.c + + +November 17 2013 +abcmatch.c. Bug fixes so the matched bars have correct bar numbers. + +November 26 2013 +abcmatch.c -br threshold applies to the number of matched bars +in template instead of matched tune. + + +December 2 2013 +abc2midi bug - split voices and repeats. The following tune +is not converted correctly. + + +X:1 +T: test split file 13 +M: 1/4 +L: 1/4 +K: G +|:G & E |1 D:|2 F & A| + + +On conversion: +writing MIDI file s11.mid +Error in line 8 : Need || |: :| or :: to mark end of variant ending +Warning in line 8 : Track 2 is 1946 units long not 2426 + +The program produces to MIDI tracks of unequal length. +Track one contains G D G D F and track two contains E z E A. +In other words track 1 plays both section one and two in the repeat +instead of just section two. + +Surprisingly if we replace |1 and |2 with |[1 and |[2 respectively, +the conversion is done correctly and there are no errors or +warnings. + +Analysis: in the first pass the feature PLAY_ON_REP belonging +to voice 1 was placed in voice 2 and two PLAY_ON_REP features +appear consecutively in voice 2 resulting in the error, +"Need || |: :| or :: ..." message. When the [1 and [2 are +used, the internal representation contained in the feature +arrays is correct. + +The problem was traced to the code in event_bar in store.c. +When the [1 and [2 is used, the PLAY_ON_REP is handled correctly +by event_playonrep() which is called directly by parsemusic in +parseabc.c. When |1 or |2 is used, parsemusic does not catch +these codes and they are handled (mishandled) by event_bar +when a split voice is present. + +Fix: event_bar() was reorganized so that bar commands are sent +to the original voice rather than the child split voices. When +the child split voices are sync'd the bar commands are copied to +the child voices. This seems to work better. The function +recurse_back_and_change_bar() is no longer in use. + +The test tune was added to split.abc in the doc/programming/ folder. + + +December 14 2013 +abc2midi: The warning "track x is xxxx units long instead of ..." +was changed to "track x is .... quarter notes long instead of ..." +The change is was made in writetrack() in genmidi.c. + + + +December 25 2013 +abc2midi bug: abc2midi does not read customstress files correctly +using the -CSM option. + +The following file containing + +Lesnoto +7/8 +7 7 +110 1.3 +90 1.0 +80 0.7 +100 1.2 +90 0.8 +100 1.2 +90 0.8 + +is not read correctly. Neither the name Lesnoto or the meter is stored +in the stresspat structure. + +Analysis: in the function read_custom_stress_file() in stresspat.c +the lines +stresspat[index].name = name; +stresspat[index].meter = meter; + +copy the address instead of the contents of string arrays name and +meter. The lines should read +strcpy(stresspat[index].name,name); /* [RZ] 2013-12-25 */ +strcpy(stresspat[index].meter, meter); /* [RZ] 2013-12-25 */ + +also gain and expand are not copied into the structures. +add +stresspat[index].vel[i] = gain; /* [RZ] 2013-12-25 */ +stresspat[index].expcoef[i] = expand; /* [RZ] 2013-12-25 */ + +I am grateful to roman.zimmermann@gmx.at for identifying the +bug and providing the fix. + + + +January 01 2014 + +Abcmatch: fixed matchsup.c so it catches only the first title +of a tune in case that it has alternate titles. + + +January 05 2014 + +Midiabc: bug the msb and lsb values were interchanged in mftext_pitchbend. +mftext_pitchbend now also returns the value of bend in MIDI units. + + +January 06-09 2014 +abc2midi new feaure: introducing an option to provide microtone tuning +in the key signature for example K:F ^1/2D besides flattening +B also flattens D's by a half a semitone. + +Implementation includes changes to parsekey in parseabc.c which +now has to check for microtones in the list of notes following +the key signature. A new parameter modmicrotone is introduced in the +function event_key() which is found in parseabc.c, store.c, yapstree.c, +toabc.c and matchsup.c. A new struct 'fraction' was added in parseabc.h. +In store.c altermap() has a new parameter struct modmic[7], which +is used to transfer the key signature microtone specifications from +modmicrotone in event_key to a new struct in the voice struct called +basmic[7]. v->basmic stores the key signature microtone specs if present. +Function newvoice in store.c transfers global->basemic to v->basemic. +Function pitchof_b in store.c checks v->basemic to see if the note +has a microtone defined in the key signature. parsenote in parseabc.c resets +microtone to 0 (through event_normal_tone()) if the note is not a microtone. +This is a lot of changes. I hope, I have not introduced new bugs. + +If a microtone is detected by parsenote(), its parameters are +stored in the struct fraction setmicrotone. This struct is automatically +reset to 0,0 if no microtone is detected. + + +January 12 2014 + +abc2midi new feature: Makam style music (Turkish) uses a more +complex music scale (as opposed to the equal temperament scale). +The comma53 scale divides an octave into 53 microtones. To use +this scale put "%%MIDI tuningsystem comma53" in your abc file. + +Implementation: added to new functions in store.c +init_p48toc53 initializes the array pt48toc[]. convert_to_comma53() +changes midipitch and midibend values. Added a new command, +%%MIDI tuningsystem comma53 + +January 14 2014 + +corrections to convert_to_comma53(). Some debugging #defs. + +January 16 2014 + +some fixes to pitchof_b and parsekey. + +January 20 2014 + +abc2midi: microtones now propagate across a bar just like accidentals. +Major modifications to pitchof_b and other minor fixes (in store.c) were made. + +January 26 2014 +abc2midi: more microtone bug fixes. Each octave can hold its own +microtones. i.e. v->workmic is now a two dimensional array just +like workmap and workmul. + + + +February 05 2014 + +abc2midi: the following file causes abc2midi (and other programs) to +behave erratically. + +X:9 +T:Have you ever wondered? +L:1/8 +M:4/4 +Q:1/2=90 +K:G +V:1 +CDEF | +W:| Have you ever | wondered why the | girls do | skipping, and the +W:| boys play | football and the | grans do | knitting? +W:| Who made the | rules that the | people all o- | bey? And +W:| What's with the | "girls' thing", | "boys' thing" | anyway? + +X:10 +T:Warm-up 1 +L:1/4 +M:2/2 +Q:1/2=80 +K:Bb +|[B,DFB]2z2 | + +abc2midi returns the message +Warning in line 9 : Potentially ambiguous line. +Warning in line 9 : Ignoring reserved character W +Error in line 9 : Unrecognized character: o +Error in line 9 : Malformed note : expecting a-g or A-G +Error in line 9 : Unrecognized character: r +Error in line 9 : Unrecognized character: w +Error in line 9 : Unrecognized character: o +Error in line 9 : Unrecognized character: n +and many more messages + +Analysis: abc2midi sees :| after the W and assumes it is an end +repeat in the body. It tries to treat the rest of the line like +music. + +Fix: I have improved the warning in parseabc.c so it is more meaningful. +It is now +Warning in line 9 : Potentially ambiguous line - either a :| repeat or a field command -- cannot distinguish. + +This applies to all programs, yaps, abc2abc etc but it is too much trouble +to give them new version numbers. + + + +April 03 2014 + +Abc2midi bug: tied note at end of bar combined with Barfly stress model. +In the following example: + +X:1 +T: Stress model bug +L:1/8 +M:2/4 +K:Gmin +%%MIDI ptstress 4 100 1.10 100 1.10 100 1.0 100 0.8 +|Gc BA-|AG FG| + +Abc2midi returns the following error message +writing MIDI file stress1.mid +Warning in line 7 : Bar 1 has 21/10 units instead of 2 + +Analysis: the problem is with the tied note A which +crosses a measure. The tied notes A-|A are tied together +into a single note by the function tiefix() in store.c +and the stress model is applied to the combined note. This +becomes obvious when running abc2midi with -v 2 option.r 2 +pitch 67 from = 0/1 (0/1) to 1/2 (1/1) becomes 0/1 11/20 - 11/20 +pitch 72 from = 1/2 (1/1) to 1/1 (2/1) becomes 11/20 11/10 - 11/20 +pitch 70 from = 1/1 (2/1) to 3/2 (3/1) becomes 11/10 8/5 - 1/2 +pitch 69 from = 3/2 (3/1) to 5/2 (5/1) becomes 8/5 51/20 - 19/20 +bar 3 +pitch 67 from = 0/1 (0/1) to 1/2 (1/1) becomes 0/1 11/20 - 11/20 +pitch 65 from = 1/2 (1/1) to 1/1 (2/1) becomes 11/20 11/10 - 11/20 +pitch 67 from = 1/1 (2/1) to 3/2 (3/1) becomes 11/10 8/5 - 1/2 +bar 4 +writing MIDI file stress + +The fix is to apply the stress model prior to combining +the tied notes. The fix was applied to the function finishfile() +in store.c + + +April 10 2014 + +Abc2midi bug: The P: field was introduced to allow repeating +parts of the tune in complex patterns such as P:ABCBD; however +it is frequently used just to annotate a section of the music. +When it is used as annotation, you often get annoying warnings +such as. +Error in line 10 : Part must be one of A-Z +In some situations, this annotation may cause the music to +play incorrectly. For example in this tune, + +X:1 +T: part annotationmistaken +M: 3/4 +K: G +V:1 +B3c BA|B3c BA|B4e2|B3d ef| + g4 g2|f4 e2|f3 gf2|B6| +V:2 +G3A GF|G3A GF|E4B2|G4E2| +P: section B +B4 B2|^d4 ^c2|^d3 e d2|F6| + +the last line in V:2 is played twice. + + +Fix: in event_part() in store.c we check whether a valid P: +command like P:A2BC was detected in the header. If none was +found, abc2midi ignores any P: commands after the header. + + + +April 24 2014 + +abc2midi: slur bug +Abc2midi sometimes reports unbalanced slurs when they are +actually correct. For example + +X:1 +T: Slur error messages +L:1/8 +M:2/2 +Q:1/2=110 +K:Dm +P:A +|: "Dm"a2ag a2ag | "^/"agfe dcAF | "Gm"GABA B^cdc | "^/"d^cBA BAGB | +"A"A=B^cB cded | "^/"efgf eA=B^c | "^/"d(^ga)(e f)(^cd)(A |1 "^/"B)AFE GAdf :|2 "^/"B)AFE DCB,A, | +P:B +|: "Gm"G,BBB BcBB | "^/"B,BBB BcBB | "Dm"FAAA Adde | "^/"fedc AFED | +"Gm"DBBB BcBB | "A"EAAA A=B^cA | "^/"d(^ga)(e f)(^cd)(A |1 "^/"B)AFE DCB,A,:|2 "^/"B)AFE "Dm"D4 | + +The following messages were returned. +Warning in line 9 : No slur to close +Warning in line 12 : No slur to close +writing MIDI file colin1.mid +Error in line 12 : Unexpected start of slur found +Error in line 12 : Unexpected start of slur found +Error in line 12 : Unexpected start of slur found + +analysis: abc2midi could not match the slurs when they cross into +a part section (eg :[2 "^/" B) ...). +fix: slur indications do not affect the output midi file so the +messages are somewhat irrelevant. The warnings and error messages +have been suppressed. + + +August 11 2014 + +Introduced a new variable abcversion and parse the comment +%%abc-version 2.0 +or +%%abc-version 2.1 +if present. + + + +August 14 2014 + +Bug: line continuation of a lyric field w: does not work. +In the following example, + +X:1 +T: vocal +M: 4/4 +L: 1/4 +K: G +G A G B|\ + E A G B| +w: ga ba la ba |\ + fa ma da ka| +GGGB| +w: la ma fa da| + +the line fa ma da ka is not processed as part of the previous +w: field. + +Apparently there was an attempt in preparse_words(s) (in parseabc.c) +to handle continuations of the w: field, however, the implementation +was not complete. (There is no signal, telling parseline() to +treat the continuation of the w: field.) Therefore this feature +never worked in all of the abcmidi programs (abc2midi, abc2abc and yaps). +I have decided not to support this feature and instead plan to +introduce an alternative using the +: command defined in the +2.1 abc standard. The following warning message is now being issued when +this situation is detected. +Warning in line 8 : \n continuation no longer supported in w: line + + +August 15 2014 + +New feature: the abc-version 2.1 standard introduces a new method for +continuing the w; using the +: for lyrics. It also discourages the use +of the backslash continuation. To handle the +: line, it was necessary +to keep track of the last field command. A new global +char lastfieldcmd was introduced in parseabc. The variable is modified +at the end of function parsefield in parseabc.c. Presently it only +signals a w: field command. For all other field commands it is set +to a blank. A new case statement for +: was also introduced in parsefield(). +It calls a new function, append_fieldcmd() if lastfieldcmd == 'w'. +The function parseline() was extended to recoginize +: as a valid +field command. The function parsefield() was modified to allow the ++: command to appear in the body of the tune. + +August 16 2014 + +Continuing from above: introduced a new function concatenatestrings() +in parseabc.c. In store.c, yapstree.c, toabc.c and matchsup.c +introduced a new function called appendfield(). Appendfield() was +only implemented in store.c where it calls a new function called +append_words. In the files, appendfield() merely returns a message +that it is not implemented yet. + + +September 07 2014 + +Continuing from above: the function appendfield() in toabc.c was +replaced so abc2abc will also handle the +: command. Note that +abc2abc the -n X option which reformats with a new linebreak +every X bars will probably not work correctly when the tune +contains lyrics. + + +September 09 2014 + +Abc2midi fix: the !bend! action does not apply correctly to microtones. +In the following example: + +X:1 +T: bend about microtone +M: 4/4 +L: 1/4 +K: G +!bend!_1/4D2 z2|!bend!D2 z2| +!bend!^1/4D2 z2|!bend!D2 z2| + +All the bends start from D natural. + +Analysis: queues.c always initializes pitchbend to 8192 rather than +the value set by the microtone. + +Fix: it was necessary to introduce another global variable, int bendstate, +to be shared between genmidi.c and queues.c. The variable bendstate +stores the pitchbend value when midi_noteon is called (in genmidi.c). +In note_effect() in queues.c, pitchbend is set to bendstate rather +than 8192. + + +September 10 2014 +September 11 2014 +Abc2midi: introducing %%MIDI bendstring n1 n2 n3 ... +This is a more general way of specifying the pitchbend track for +a note. The command is followed by a series of integers n1, n2 +etc. which specify the change to pitchbend following each time +increment. + +Method: In genmidi.c introduced the array benddata[16] which +holds the series of integers and bendnvals the number of these +integers. Benddata and bendvals is passed to genmidi through +an extern declaration. In dodeferred() in genmidi.c added a test for +%%MIDI bendstring. In queues.c added a new function, note_effect2() +which increments the pitchbend variable by benddata[i], and +produces a %%MIDI pitchbend command at regular time intervals. +In genmidi.c introduced a variable bendtype and set it to 1. +The %%MIDI bendstring command sets bendtype to 2 to signal that the +function note_effect2() should be called instead of note_effect(). + + +September 22 2014 +September 23 2014 +September 24 2014 +Abc2midi: when only one integer follows the %%MIDI bendstring +command, the !bend! command now applies the pitchbend to the +entire note. This provides another method for shifting the +pitch of the note instead of preceding it with a microtone +accidental. At the end of the note, the pitch of the note +is restored to its original value. + +Implementation: in dodeferred() in genmidi.c we check for just +one value following the bendstring command and set the bendtype +variable to 3 so that queues.c calls the new function +note_effect3(). + +September 28 2014 + +Extended the maximum bendstring length to 50. + + +October 16 2014 + +Abc2midi: in some applications it may be desirable to suppresses +all messages. A new option -silent was introduced to suppress the +the other warnings and messages not handled by the -quiet option. +eg. +abc2midi nottingham.abc -silent -quiet +produces almost not output except for the MIDI files. + + +October 29 2014 ... + +Abc2midi: more work was done with the bar repeat code in store.c +Abc2midi returns the incorrect line number when it detects a +problem with bar length on repeat. + +Analysis: there are two functions which attempt to detect and +fix problems with repeats in store.c -- scan_for_missing_repeats() +and fixreps() each trying to fix different problems. When the +abc tune does not have voices or parts, it was discovered that +voicestart[0] is still initialized to zero and does not indicate +the position of the start of the music line further the inserted +DOUBLE_BAR code was placed in the wrong place by the function +headerprocess(). The function scan_for_missing_repeasts() was +modified to search for the first instance of MUSICLINE and +to insert a DOUBLE_BAR feature immediately after. The voicestart[0] +variable was set to this position. + +November 02 2014 + +Incorporated changes to the makefile and manpages suggested by +Ross Gammon who does Debian Quality Assurance. + + +November 02 2014 + +Abc2midi bug: the b code in the gchord string does not work +correctly when there are inversions. eg. + +X:1 +T: gchord +M: 4/4 +L: 1/4 +K: C +%%MIDI gchord fb +"C" z4|"C/E" z4| + +The second bar is played at E,,4 [C4G,4E,4C,,4] instead of +E,,4 [C4G,4E,4E,,4] + +Fix: +In dogchords() (genmidi.c) case 'b' was changed so that it +is identical to case 'f' except that there is no break ending +that case (it progresses to case 'c'). + + +November 9 2014 +Abc2midi grace bug: in the following example, the grace notes +cause a loss of synchronization between the two voices. + +X:1 +T:Grace problem +M: 2/4 +L: 1/4 +K: G +Q:1/4 =60 +V:1 +{cde}f/|ed|cB| +V:2 +z|CD|CD| + +According to the documentation the grace notes are given +a length of 1/8 or half of the unit length specified in the L: field. +The three grace notes cde add up to be longer than the home note f, +so it is impossible to trim f in order to accommodate the grace +sequence. According to the documentation, abc2midi should cut out +the grace sequence in order to avoid loss of synchronization. +Instead abc2midi does not affect the grace sequence and the +two voices are out of synchronization. + +Analysis: the function applygrace_new() in store.c computes the +difference between the length of the grace sequence and the +home note, but the test should read +if (adjusted_num <= 0.0) /* not long enough */ +instead of +if (adjusted_den <= 0.0) +I would guess this bug has been around since 2004. + +In addition I added a warning that the grace sequence is too long. + +The code to change the length of the grace notes to zero +did not work correctly for some reason that I have not +tried to figure out -- (mf_write_midi_event tries to +record a delta_time = -1). Instead I just removed all the +grace notes from the feature representation. + + +November 18 2014 + +Abc2midi fermata bug: the !fermata! instruction applied to a rest +also applies to the following chord. In the following example, + +X:1 +T: fermata rest bug. +L: 1/8 +M: 6/8 +K:D + !fermata!z6 |[A,DF]2G [CDFA]GF |C D2 C D2| + +Both z6 and [A,DF]2 are doubled in length. + +Incidentally if we substituted Hz6 for !fermata!z6, the +program works correctly. + +Analysis: as evident in this file, this is not the +first !fermata! bug. Apparently in this case, decorators[FERMATA] +flag was not reset to 0 after the event_rest() in parseabc.c. +The fix was to add the statement decorators[FERMATA] = 0 +after the event_rest() call in parseabc.c. + +Note it is not correct to apply a fermata to a multirest. +i.e. Z3| means three bars of rests. HZ3 does not mean +three bars of fermata rests and the same applies to +!fermata!Z3. + +In addition, I have improved the bar length warning to +include the track number where it was applied. The track number +is related to the voice number in some way. + + +December 25 2014 + +Abc2midi new feature: the error and warning messages now provide +both the line and character position location in the abc tune +where the message was issued. + +Implementation: the character position is stored in the variable +lineposition in parseabc.c. This variable is linked as an extern +to store.c and genmidi.c. A new array charloc[] in store.c was introduced +to record the character position when addfeature() is called. +When writetrack is executed in genmidi.c, lineposition is updated +for each feature element processed. lineposition and linenum are +now both printed by event_error() and event_warning() in store.c. + + + +February 22 2015 + +bugs.debian.org reported that abc2abc, abcmatch, yaps, and midi2abc +crash with certain malformed input parameters. Fixes were applied +to toabc.c, abcmatch.c, yapstree.c and midi2abc.c. + +March 11 2015 + +Abc2midi multirest bug. It is common to list the voices before +the time signature and unit length declaration. + +X:1 +T: correct test file +V:1 name="1_Requinta_Eb" sname="1Re_Eb" %config, program 1 72 /control 7 80 /transpose +3 +V:2 name="1_Clarineta_Bb" sname="1Cl_Bb" %config, program 2 71 /control 7 80 /transpose -2 +V:3 name="1_Saxofone_Eb" sname="1Sx_Eb" %config, program 3 65 /control 7 80 /transpose +3 +V:4 name="1_Corneta_Bb" sname="1Cr_Bb" %config, program 4 59 /control 7 80 /transpose -2 +M: 2/4 +L: 1/8 +K: G +V: 1 +C4| C4| C4| C4| +V:2 +z4| z4| z4| z4| +V:3 +Z| Z| Z| Z| +V:4 +Z4| + +In this example abc2midi does not get the correct time signature and +unit length for voices 1 to 3. + +Fix: Added a new function meter_voice_update(n,m) which sets +the meter for all declared voices if not past the header. + + + +March 16 2015 + +Abc2midi - new feature. In theory there should not be any limit +on the number of tracks that is produced provided that the user +takes care of assigning the right channels to the voices. +I have extended the voicecode array in parseabc.c so that 24 +voices can be handled without overruning the array. In genmidi.c +I have merely changed the name of the array channels[] to +channel_in_use[] so its purpose is better understood. The +use of more than 16 tracks will lead to some warnings issued +but the program should still produce a useful MIDI file. + + +March 23 2015 + +Abc2midi - improvements. + +In order to support extended voice overlay, +introduced two new functions event_start_extended_overlay() and +event_stop_extended_overlay which are called from parsemusic() in +parseabc.c when (& or &) are detected in the abc file. The +two functions are defined in store.c, toabc.c, yapstree.c and +matchsup.c. The functions turn on and turn off the state variable +extended_overlay_running. + +In event_specific() in store.c we verify that channel in +%%MIDI channel command lies between 1 and 16 inclusive. If +not it is set to 1 and an error message is issued. + +A new state variable no_more_free_channels is introduced in +store.c and set to zero in finishfile(). When findchannel() +in genmidi.c cannot find a free channel a message "All 16 +MIDI channels used up" is issued and the variable no_more_free_channels +is set to 1. + + +March 24 2015 + +Abc2midi - improvements. + +Abc2midi in the past did not keep track of the channel assignments. +If we allow inheriting channel assignments for split voices, now +called voice overlays, we need to know the MIDI channel assigned +to the voice. I added midichannel to the voicestruct in store.c +to store the MIDI channel when a %%MIDI channel is encountered. +So far %%MIDI channel also calls addfeature() to add a channel +feature in the feature array. (This is how the channel number +has been passed to writetrack in the past.) + +The function findchannel() in genmidi.c does not know that a +channel number was already assigned to the track (if that was +the case). The voicestruct is not passed to genmidi.c from store.c +but trackdescriptor is passed as an external. I therefore added +midichannel to trackstruct in genmidi.h and set trackdescriptor.midichannel +in the function setup_trackstructure() in store.c. Added an +argument tracknum to starttrack() in genmidi.c so it can grab +the midichannel number from trackdescriptor[]. + +The function event_split_voice() now passes the midi channel number +assigned to the voice to the new voice that it creates. The behaviour +of the split voice now depends on whether a channel number has +been assigned to the original voice. If no channel number has +been assigned, then both the original and child voice will have +a midichannel of -1. If the value is -1, then a new and distinct channel +number is assigned to each voice. Otherwise the original and +child voices will assume to the same channel number that was +given when the voice was created. + + +March 25 2015 March 26 2015 + +Adding code to support extended split voices. In event_bar (store.c) +do not recurse back to the original voice if inside an extended_overlay. +In stop_extended_overlay(), recurse back to the original voice. + +The following is an example of the extended voice overlay. + +X:1 +T: extended voice overlay +M:2/4 +L:1/4 +K:C +GA|(&Bc|de|de&FG|FG|FG|&)|DE| +GA|(&Bc|de|de&FG|FG|FG|&)|DE| + + +April 08 2015 + +The parsing of the key signature when it contains modifiers with +double flats or double sharps does not work correctly. For +example: + +X:1 +T: double flat +M: 2/4 +L: 1/8 +K: Ab _F__B_/2C +F2 B2|C2D2| + +The double flat preceding B in the key signature was interpreted +as a single flat and B2 in the first bar was converted to Bb instead +of A. + +Fix: the logic in readword() in parseabc.c was changed so that +a break does not occur on the second flat or sharp. + + +April 13 2015 + +Abc2midi, abc2abc, yaps : minor bug. The tune + +X:1 +T: single colon +M: 2/4 +L: 1/8 +K: F +[|: ABcd|ABDF:|] + +returns a message 'Single colon in bar', otherwise the output is +correct. + +Analysis: this is a problem with parsemusic() in parseabc.c. +When the parser encounters | it check for a : following and +treats them both as BAR_REP. On the other hand if the parser +encounters [| it neglects to check for a following : and the +: is not associated with anything. + +Fix: added a check for ':' in case '['. + + +April 17 2015 + +Abc2midi staccato chord bug. + + +%abc-2.1 +X:1 +T: staccato problem +M:2/4 +L:1/4 +Q:1/4=116 +K:D +% +V:K +% +% Case 1: works if isolated: +% F A/ .[DF]/ | +% +% Case 2: works: +% F A/ [.D/.F/] | E E & Cx | +% +% Case 3: works: +% F A/ [DF]/ | E E & Cx | +% +% Case 4: doesn't work: + F A/ .[DF]/ | E E & Cx | +% +% Case 5: doesn't work: + F A/ [.D.F]/ | E E & Cx | + +Both cases 4 and 5 return an error message + +Warning in line-char 26-28 : Track 2 is 4.554167 quarter notes long not 4.054167 +and the note C# in the voice overlay comes 1/2 beat late. + +Analysis, the staccato introduces a REST in the internal representation +of the chord. When the length of the chord is specified at the end of +the abc chord representation, eg. [CEG]n/m), abc2midi calls the function +fix_enclosed_note_lengths which changes the lengths of all the enclosed +notes to n/m. Unfortunately, the REST in the chord was not expected +and was not modified. The representation of the underlying voice +is incorrect and as a result the overlain voice does not get +synchronized at the right place. + +Fix: now test for NOTE, TNOTE and REST in the chord in the function +fix_enclosed_note_lengths in store.c. + + +April 28 2015 + +Abc2midi: dotted slur + +The abc standard recognizes dotted slurs which abcm2ps displays as a +slur with a dotted curve. The dotted slur is indicated with parenthesis +preceded by a period as shown below. + +X:1 +T: DottedSlur +M: 2/4 +L: 1/8 +K: A +.(ABcd)|(ABcd)|ABcd| + +Currently abc2midi reports the error. +Error in line-char 6-0 : Malformed note : expecting a-g or A-G + +Analysis: parsemusic() in parseabc.c assumes '.' is a staccato decoration +and expects a note to follow. Instead it sees a '(' and reports an error. +Since abc2midi does not treat slurs differently, the resulting MIDI +file is correct. + +Fix: +If a '.' is encountered, parsemusic checks for a following '('. +The fix also affects abc2abc, yaps, and abcmatch. + + +April 29 2015 + +Abc2midi always prints its version number when it runs. + + + +May 11 2015 + +Abc2midi does not recognize the inline command [r: some remark]. + +X:1 +T:Remark not allowed +C:JWDJ +M:4/4 +L:1/4 +K:C +[K:D] A2 B2| [r:!fermata!]G4 |] + + +Analysis: the 2.1 standard allows users to enter a remark inside a +line using the [r: ...] inline field. This command should be treated +the same way as a comment indicated with a '%' in the first column of +the text line (eg.) +% comment +Abc2midi does not recognize r: inside an inline field command and reports an error. +Error in line-char 7-13 : Field not allowed in tune body + +Fix: +In parsefield() in parseabc.c, added r to the string EIKLMPQTVdswW+ . Thus +if ((inbody) && (strchr ("EIKLMPQTVdrswW+", key) == NULL)) /* [SS] 2015-05-11 */ +The following switch statement falls into case default: which +treats the field as plain text. + +Note: Though the standard probably allows the remark to extend over +several lines, eg. + +X:1 +T:Long remark not allowed +C:JWDJ +M:4/4 +L:1/4 +K:C +[K:D] A2 B2| [r: some long +remark]G4 |] + +this is not supported in the abcmidi package. (It would require +more extensive modification.) The user should use '%' to insert +multiline comments. + + +May 13 2015 + +abc2midi, abc2abc, yaps voice transpose bug. + +In the following sample, + + +X:1 +T: octave problem +M: 4/4 +L: 1/4 +V:1 clef=treble octave=-1 +V:2 clef=treble octave=-1 +K:G +V:1 +ABCD|EFGA| +V:2 +abcd|ABCD| + +Applying abc2abc to the tune returns + +X:1 +T:octave problem +M:4/4 +L:1/4 +V:1 clef=treble octave=0 +V:2 clef=treble octave=0 +K:G +V:1 +ABCD|EFGA| +V:2 +abcd|ABCD| + +octave was changed to zero and abc2midi applied on the same tune +does not shift down the pitch by an octave. If we change V:1 and V:2 +to +V:1 octave=-1 +V:2 octave=-1 +the programs work correctly. + +Analysis: + +This is an issue with the code parsevoice() in parseabc. +The clef=treble also specifies the octave and sets the flag +cgotoctave to 1. This flag indicates that the octave is +also set by the clef command. If you wanted octave=-1 +you should say clef=treble-8. To avoid further confusion, +in the future, I modified parsevoice so that it allows octave= +following the clef= property to override the octave value set +by the clef= property. + +The parsevoice() code is rather brittle and expects all +the voice parameters to be in a specific order. The code +looks for the following properties in this order. +clef= +transpose= +octave= +name= +sname= +middle= + +If the properties are not in this order, they may be missed. +The function parsevoice scans the V: string looking for the properties +in the specific order using the 'while (*s != '\0). Each time +a property is found the pointer *s is advanced past that property +by one of the functions parsetranspose(), parseoctave(), +parsename(), and etc and the while loop goes back to the +beginning. parseclef() is called repeatedly and even though +it does not find clef=, it still returns the variable 'word' +which is used for matching by the above mentioned functions. + +If I am rewriting the code, I would replace casecmp() with +strcmp() and use a switch (word) control to call one of the +functions parsetranspose(), parseoctave(), and etc. This +involves changing all of those functions too. Note parsetranspose() +and parseoctave() are also called when the K: field is +scanned. + + +May 17 2015 + +abc2midi: %%MIDI makechordchannels bug + +The makechordchannels command was introduced in October 3 2006 +for handling chords consisting of notes consisting of microtones. +When the command appears after a V: declaration, too many chord +channels are created which may cause the 15 channel limit (one +channel is used for percussion), to be exceeded. For example, + +X:1 +T: too many chord channels +M: 2/4 +L: 1/4 +K:G +V:1 +%%MIDI beataccents +%%MIDI makechordchannels 7 +G2| +V:2 +%%MIDI program 42 +%%MIDI nobeataccents +E2| +V:3 +%%MIDI program 43 +C2| + +The following errors are reported. +Error in line-char 10-2 : All 16 MIDI channels used up. +Error in line-char 15-2 : Channel limit exceeded + + +Analysis: + +During the creation of track 0 (the header track in a type 1 MIDI file), +the entire tune is scanned and some of the MIDI commands are activated. +Unfortunately, the makechordchannels is activated twice; once for +track 0 and once for track 1. The chord channels created in track 0 +are never used. + +An abc tune that creates at type 0 MIDI file, (i.e. no voices, +guitar chords, percussion etc.) would not pose a problem for this +implementation. + +Fix: + +Added a test in the function makechordchannels (in genmidi.c) to +prevent the creation of chord channels in track 0 for multitrack +MIDI files. + + + +May 19 2015 + +Abc2midi temperament support was extended by Hudson F.M. Lacerda. +Microtone accidentals can be used along with temperamentlinear. +In that case, the accidental ratio is based on the new chromatic +semitone size, defined as 7 fifths minus 4 octaves. (Run abc2midi +with the verbose option (-v) to see the temperament values.) +As an exception, the microtonal deviation in cents can be represented +by using denominator=100 in the accidentals. For example: + +
+X:1
+T:\%\%MIDI temperamentlinear - microtone accidentals in cents
+%%postscript /ft5475{M -3 3 RM 6 -6 RL 2 SLW stroke}def
+%%postscript /ft35939{2 copy ft0 M -7.5 -3 RM 12 F3 (7) show}def
+M:none
+K:C
+%%scale 1.3
+V:1
+%%MIDI program 17
+%%MIDI temperamentlinear 1200 702 %% Pythagorian tunings
+%%MIDI makechordchannels 3
+"^Pure;major;chord"\
+[C_22/100EG]8 y |\
+"^Pythagorian;major;chord"\
+[CEG]8 y ||\
+"^Pure;4:5:6:7;chord"\
+[C_22/100EG_141/100B]8 y |\
+"^Pythagorean;7-chord"\
+[CEG_B]8 y ||
+
+ +

+A new command %%temperamentequal was introduced. +
+%%MIDI temperamentequal [octave_cents] [fifth_steps] [sharp_steps] + +This command sets a tempered scale defined by 'ndiv' equal divisions +of 'octave_cents' (default is the octave = 1200 cents). +The optional parameter 'fifth_steps', if provided, is an integer that +defines the size of the fifth in steps of the temperament. +This sets where is the note G in the temperament. +When 'fifth_steps' is omitted or 0 (zero), the program computes it +as an approximation of the frequency ratio 3/1, minus the +(possibly tempered) octave. +The optional 'sharp_steps' defines the meaning of the accidentals. +'sharp_steps' is the number of steps between a natural note and +a sharpened note (e.g. between =C and ^C). +By default, the size of a sharp/flat deviation is based on the +size of the chromatic semitone in the specified temperament: 7 fifths minus +4 octaves. The values in use in the temperament can be viewed +by running abc2midi with the command-line option -v (verbose). +With temperamentequal (as with temperamentlinear), microtone accidentals +are interpreted as fractions of the sharp size in the +specified temperament, except if they use denominator=100, which +defines microtonal deviations in cents. +The conventional temperament can be reset with the command temperamentnormal. +See also: temperamentlinear, temperamentnormal, makechordchannels + + +Implementation: Changes in store.c are marked with [HL] 2015-05-15 +New global variable 'sharp_size' + It is the the size, in pitchbend units, of the chromatic step + between (e.g.) =C and ^C. (This is computed from octave and + fifth sizes when using temperamentlinear or temperamentequal.) + + +event_specific() + Function changed to modify the command temperamentlinear + and to add the command temperamentequal. + + temperamentlinear: + Compute 'sharp_size'; + Print information when -v (verbose option); + Fix the command name in the error message. + + temperamentequal (new command): + Compute octave_size, fifth_size, sharp_size; + Temperament information when -v (Verbose option). + + +pitchof_b() + Function changed to handle microtones in user-defined temperaments. + Global variable 'sharp_size' is used for that. + + +event_microtone() + Rounding instead truncation as slight improvement of precision. + (MIDI bend is rough for tuning.) + + + + +May 21 2015 + +Abc2midi drone bug: + +The %%MIDI drone command is ineffective. In the following example, + +X: 1 +T:Banks and Braes +M:6/8 +L:1/8 +S:Slow March +K:HP +%%MIDI program 109 +%%MIDI gracedivider 4 +%%MIDI drone 67 44 45 90 90 +%%MIDI droneon + {Gdc}d2{g}d{g}ede|\ +{g}faf{gef}e2{g}d/2e/2| + +the %%MIDI drone 67 44 45 90 90 does not change the drone characteristics. + +Analysis: The drone is put in a separate MIDI track. The %%MIDI drone +command is processed in the first track, and updates the elements +of the drone structure. When the drone track is written starttrack() +in genmidi.c, initializes the drone structure destroying any information +that was recorded. + +Fix: initialization of the drone structure is done during compilation +time. Note, if the tune has more than one %%MIDI drone command, +only the last one is effective. + + +June 01 2015 + +Abc2midi new feature: introducing new commands %%MIDIdef and %%MIDIx. +%%MIDIdef code line +links code a unique string less than 7 letters to a line of strings +that normally occurs in a MIDI command. For example +%%MIDIdef bnd1 bendstring 400 400 300 100 -100 300 400 400 400 +link the string bnd1 to " bendstring 400 400 300 100 -100 300 400 400 400" +Now you can call up the MIDI command +%%MIDI bendstring 400 400 300 100 -100 300 400 400 400 +using a shorthand +%%MIDIx bnd1. + +Example: + +X:1 +%%MIDIdef type1 bendstring 0 0 600 600 600 600 0 -600 -600 -600 -600 -600 -120 0 +%%MIDIdef type2 bendstring 0 0 0 0 0 0 400 800 800 -800 -800 -400 -400 -400 +%%MIDIdef inst program 67 +%%MIDIdef t3 bendstring 0 0 0 0 0 500 500 600 600 -600 -600 -500 -500 +T: MIDI +M:2/4 +L:1/2 +K: D +%%MIDIx inst +%%MIDIx type1 +!bend!A|B|\ +%%MIDIx type2 +!bend!C|D| + + +This is useful when you have several different bendstrings and you +wish to call them up in different places in the tune using a code. + +There is a limit of 20 distinct MIDIdef's in your tune. + +Implementation: in parseabc.c added a new function readaln which +is like readstr but scans for the next word (that may contain numerics) +in the input string. (The words are separated by spaces or tabs.) +In store.c, added two new functions parse_mididefs(s) and +expand_midix(s) for handling the %%MIDIdef and %%MIDIx commands. +These functions are called in the function event_specific(). + +June 02 2015 +continuation: added strcmp(key, "MIDIx") in event_info_key() in +store.c + + +June 07 2015 + +Abc2midi bug: the !bend! command does not work inside a slur. +In the following example, + +X:1 +T: slur and bend +M: 2/4 +L: 1/8 +K: F +%%MIDI bendstring 500 500 500 0 -500 -500 -500 +%%MIDI program 73 +!bend! D4|(!bend! F4| D4| + +a bend is not applied on F4. + +Analysis: writetrack() in genmidi.c tests whether a note is inside a +slur. If it is inside a slur, both note triming and note bending were +suppressed. Fix, writetrack() was modified to allow note bending inside +a slur. + +The MIDIdef, MIDIx code word was allowed to contain up to 31 characters. +All characters except white spaces are allowed inside the code word. + + +June 08 2015 + +Abc2midi bug: !bend! causes tracklenth to be too small. Fix: +in timestep() in queues.c, update tracklen before note_effect is +called instead as after. + + +June 16 2015 +Abc2midi new feature: introducing %%MIDI expand m/n. This acts +like %%MIDI trim m/n except it expands the note by this amount. + +Implementation: added feature EXPAND to featuretype in abc.h. +In event_specific() in store.c, test for %%MIDI command 'expand' +and addfeature(EXPAND,...) if found. In genmidi.c introduce +new globals (expand, expand_num, and expand_denom) which are +set in writetrack when feature EXPAND is detected. If the +flag expand is set, then the active note is expanded. Here +is a test tune. + +X:1 +T: note expansion +M: 4/4 +L: 1/2 +K: G +%%MIDI program 52 +CD|GA| +%%MIDI expand 1/2 +de|fe|BA| + + +June 16 2015 +Abc2midi new feature: added track identification annotation to +midi file so we know whether it is a gchord, note, lyric, drum, etc +track. + + +June 30 2015 +Abc2midi split voice bug: change of unit length defined by L: does +not propagate to the voice overlay. eg. + +X:1 +T: split voice bug - unit length +M: 4/4 +L:1/8 +K: G +C8 & E8|\ +L:1/4 +cdAB & GAEF|G4 & D4:| + +causes loss of synchronization starting from the second measure. + +Analysis: the L:1/4 does not change the unit length in the split +voice and the notes GAEF and D4 are too short. + +Fix: in event_split_voice() in store.c set the unit length +to the same length as the parent voice. + + +July 02 2015 + +Abc2abc bug: the fix introduced in May 13 2015 introduced another +problem. In the example + +X:1 +T: Octave +M: 2/4 +L: 1/8 +K: G +V:1 clef=treble+8 +CDEF|ABcd| + +Applying abc2abc returns + +X:1 +T:Octave +M:2/4 +L:1/8 +K:G +V:1 clef=treble+8 octave=1 +CDEF|ABcd| + +Unfortunately the added parameter octave=1 causes abcm2ps to +also display the notes one octave higher. + +Analysis: the parameter octave=1 is useful to abc2midi as +it tells the program to shift the notes up one octave when +it creates the midi file; however, this is not desired when +running abcm2ps. Abcm2ps uses clef=treble+8 to place an 8 +above the treble clef and that is sufficient. +The problems occurs in the function isclef() in parseabc.c. +The function changes gotoctave to 1 when it sees treble+8. +The fix on May 13 2015 forces event_voice to issue an octave=1 +when it sees cgotoctave = 1. + +Fix: in isclef() a conditional block {} was created for all +if (fileprogram == ABC2MIDI && *gotoctave != 1 && *octave != 1) +statements, and *gotoctave = 1 was moved inside this block. + + +July 08 2015 + +abc2midi feature: added sus4 to the list of chord names recognized. +Added hint to message 'Unrecognized chord name ...". + + +July 15 2015 + +abc2midi bug: abc2midi crashes (segmentation error) on %%MIDIx. +In the following example: + +X:1 +T: segmentation error +M: 2/4 +L: 1/8 +K: G +%%MIDIx crash +ABCD| + + +abc2midi fails. + +Analysis: abc2midi fails to detect that there is no corresponding +%%MIDIdef for the code word 'crash'. + +Fix: the function expand_midix() now checks for this case. + + +July 24-28 2015 + +abc2midi: new feature !shape! and %%MIDI controlstring. +Introduced a new midi command +%%MIDI controlstring n m1 m2 m3 ... +where n, m1, m2, and etc are numbers between 0 and 127. +%%MIDI controlstring n m1 +is equivalent to the %%MIDI control command. When more than +one data value m1 and etc. follow, then this defines how +to shape the note following the !shape! instruction. The +following example illustrates shaping the note F4 by +varying the mod wheel. + +X:1 +T: control string +M: 4/4 +L: 1/4 +K: G +%%MIDI controlstring 1 125 80 40 0 +%%MIDI program 60 +!shape! F4| D4|F2G2| + +The midi file produced will look like + +Header format=0 ntrks=1 division=480 +Track 1 contains 115 bytes + 0.00 Metatext (Text Event) note track + 0.00 Metatext tempo = 120.00 bpm + 0.00 Metatext key signature G (1/0) + 0.00 Metatext time signature=4/4 + 0.00 Metatext (Seqnce/Track Name) control string + 0.00 Program 1 60 (French Horn) + 0.00 Note on 1 f#4 105 + 1.00 CntlParm 1 Modulation Wheel = 125 + 2.00 CntlParm 1 Modulation Wheel = 80 + 3.00 CntlParm 1 Modulation Wheel = 40 + 3.99 CntlParm 1 Modulation Wheel = 0 + 4.00 Note off 1 f#4 0 + 4.00 Note on 1 d4 105 + 8.00 Note off 1 d4 0 + 8.00 Note on 1 f#4 105 + 10.00 Note off 1 f#4 0 + 10.00 Note on 1 g4 95 + 12.00 Note off 1 g4 0 + 12.05 Meta event, end of track + +The whole note F# is modified in 4 equal segments. + +Note the !shape! does not work in combination with the !bend! command +presently. + +Implementation: created the new function note_effect4() in queues.c + +The maximum number of codenames for %%MIDIdef has been increased +to 200. The codename can now be as long as 31 letters. + + +July 27 2015 - August 3 2015 + +abc2midi: extension of !shape! for combining %%MIDI controlstring +and %%MIDI bendstring. + +Implementation: added a new struct eventstruct and a struct +array eventlist[200]. Created new procedures note_effect5(), +output_eventlist(), and compare_events(). + + +August 4 2015 + +abc2midi: channel bug. The following tune plays incorrectly. + +X: 1 +T: channel problem +M: 6/8 +L: 1/8 +K: G +%%MIDI channel 1 +%%MIDI bassprog 68 +%%MIDI chordprog 20 +D | "G"G3 GAB | "D"ABA ABd | + +The melody should be played on the Acoustic Piano; instead +it is played on the oboe (MIDI program 68). + +Analysis: + +The %%MIDI channel setting is redundant and causes the problem. +Both the melody and the bass accompaniment use the same channel. +The command %%MIDI bassprog 68 causes the melody to be played +by program 68 (the oboe). The bug was introduced in March 16 2015. +The variable channel_in_use[channel] was not set to 1 correctly in +starttrack() in genmidi.c. + + +August 06 2015 + +Fixed compile issue on Mac OS 10.10.4 in genmidi.c + + +August 10 2015 - August 11 2015 + +abc2midi new feature: +%%MIDI controlstring restores the controller back to its default after +the shaped note is played. The default can be changed with a regular +%%MIDI control command. + +Implementation: added a new array controldefaults[] in genmidi.c which +is linked to queue.c. + +Updated abcguide.txt. + + + +August 18 2015 + +abc2midi: Support for the directive +%%propagate-accidentals not | octave | pitch +was extended to include the three choices described in +http://abcnotation.com/wiki/abc:standard:v2.1#accidental_directives +Furthermore, the default was changed to 'pitch' in compliance +with the standard. + +Implementation: All the changes were limited to the source code +store.c. The flag retain_accidentals was eliminated and the +switch nopropagate_accidentals was changed to propagate_accidentals +in store.c. In event_specific(), the switch propagate_accidentals +is set on the basis of the directive %%propagate-accidentals, +to 0, 1, or 2. + +In pitchof_b(), the code for propagating accidentals (including +microtones) was reworked. + +Here is a simple test file. + +X:1 +T:accidental +M:2/4 +L:1/8 +K:C +%%propagate-accidentals pitch +^C2c2| +%%propagate-accidentals not +^C2c2|\ +%%propagate-accidentals octave +^C2c2|\ +%%propagate-accidentals no + +The c2 note is affected by only the pitch directive (default). +The last %%propagate_accidentals returns an error message. + + + +August 19 2015 + +Abc2midi: complex time signature extension. Abc2midi now +interprets M: 2+3+2/8 as M:7/8. + +Implementation: a small loop was added in the function +readsig() in parseabc.c + + +August 20 2015 + +Abc2midi new feature: introducing %%MIDI controlcombo. This allows +combining two controlstrings into 1. Here is an example: + +X:1 +T: control string combo +M: 4/4 +L: 1/4 +K: F +Q: 1/4 = 60 +%%MIDI program 123 # bird tweets +%expression +%%MIDI controlstring 11 110 90 60 40 60 60 90 110 +%%MIDI controlcombo +%panning +%%MIDI controlstring 10 0 0 20 40 60 80 100 120 127 127 +!shape! c4 | + +controlstring 11 varies the expression and controlstring pans +the output from the left to right speaker. The %%MIDI controlcombo +command tells abc2midi that the panning controlstring should be +included with the expression controlstring. + +Implementation: in genmidi.c, the controldata array has been +converted into a two dimensional array and controlvals has been +converted from a scalar to a single dimensional array. A flag +controlcombo indicates whether to replace or combine the new control +string. Each one dimensional component of controldata stores one +of the control strings into a 'layer'. In queues.c, the function +note_effect4 scans all layers for data and appends it to the +eventlist[]. + + +August 20 2015 + +Abc2midi new feature: If two controlstring are referenced in the +%%MIDIx they will combined in the manner described above. +Here is a sample file. + + +X:1 +T: control string combo +M: 4/4 +L: 1/4 +K: F +Q: 1/4 = 60 +%%MIDI program 123 # bird tweets +%expression +%%MIDIdef expr controlstring 11 110 90 60 40 60 60 90 110 +%%MIDIdef pan controlstring 10 0 0 20 40 60 80 100 120 127 127 +%%MIDIx expr pan +!shape! c4 |C4| + + +Implementation: expand_midix was renamed to process_midix and the +code was reworked so that it would loop through all the code words +and call event_midi() to process all the %%MIDI commands that +were generated. + + +August 24 2015 + +abc2midi bug: the following tune was not processed correctly. + + +X:1 +T: control string bug +M: 4/4 +L: 1/4 +K: F +Q: 1/4 = 60 +%%MIDI program 2 +%%MIDI controlstring 11 110 +!shape! c4 | +%%MIDI controlstring 11 60 +!shape!E4|D4| + +All three notes c4,E4 and D4 are played at the same time. + +Analysis: in note_effect5() the conditional if (j > 1) should +only apply to the qsort function. + + +August 25 2015 + +abc2midi bugs: the following tune was not processed correctly. + + +X:1 +T: controlstring and bendstring problems +M: 4/4 +L: 1/4 +K: F +Q: 1/4 = 120 +%%MIDI program 60 # French Horn +%%MIDIdef expr110 controlstring 11 110 +%%MIDIdef expr60 controlstring 11 60 +%%MIDI bendstring 0 2000 2000 +%%MIDIx expr60 +!shape! c2 c2 | + +The resulting midi file had two problems. The first c2 was extended +in length and the pitch of the second c2 was effected by the !shape! +command. + +Fixes: the pitchwheel was restored to its initial value at the end +of the altered note. When restoring the controller to the initial +state we checked whether a bend string was also processed. + + +August 28 2015 + +abc2midi bug: + +The following file produces an artefact at the end of note. + + +X:1 +%%MIDIdef voloff100 controlstring 11 100 90 80 70 60 50 40 30 +%%MIDIdef no-bend bendstring +T:? +C: ? +M: 4/4 +L: 1/4 +Q:1/4=130 +K: none +%%propagate-accidentals not +%%MIDI beat 100 95 80 1 +%%MIDIdef petasth bendstring 0 0 900 900 0 -900 -900 0 -400 +V:1 +%%MIDI program 60 % french horn +[M:3/4][I: MIDIx= petasth]!shape!A[I: MIDIx=no-bend voloff100]!shape!E2 + + +Analysis note_effect5 restores the controller defaults before the +note ends causing a transient at the end of the note. + +Fix: the restoration is done after the note. + + +August 30 2015 + +abc2midi bug: in the following tune, + + +X:1 +%%MIDIdef voloff100 controlstring 11 100 90 80 70 60 50 40 30 +%%MIDIdef no-bend bendstring +T: controlstring state not initialized at start of track +M: 4/4 +L: 1/4 +K: C +%%MIDIdef petasth bendstring 0 0 900 900 0 -900 -900 0 -400 +V:1 +%%MIDI program 60 % french horn +[I: MIDIx= petasth]!shape!A2[I: MIDIx=no-bend voloff100]!shape!E2 + +the voloff100 is applied to A2 despite the fact the command +occurs after A2 + +Analysis: abc2midi creates a two track file. While it is creating +the header track, controlnvals[0] was set to a nonzero value after +MIDIx=no_bend voloff100 was processed and controldata[] contained +appropriate data to perform the voloff100. Unfortunately, when +the next track written controlnvals[0] was not reset. + +Fix: reset controlnvals[] + + +August 31 2015 + +abc2midi bug: in the following file + +X: 1 +%%MIDIdef slur2 bendstring 0 0 0 0 0 1000 +T: last bendstring not picked up +M: 4/4 +L: 1/4 +K: G +Q: 1/4=80 +%%MIDI program 42 % french horn +V:1 +G[I: MIDIx= slur2]!bend!A + +the bendstring value 1000 is not picked up + +Fix: in do deferred() (genmidi.c) the statement +if (p* == 0) break; was moved after i = i +1; + + + +September 07 2015 + +Abc2midi new feature: in genmidi.c, the %%MIDI bendstring command can +now accept up to 100 increments to accommodate long notes (benddata[100]); +and the %%MIDI controlstring command can now accept up to 100 values +to accommodate long notes (controldata[3][100]). In queues.c eventlist +array was extended to 500 to handle the additional complexity. + + +September 08 2015 + +Abc2midi: new commands %%MIDI vol n and %%MIDI volinc m introduced +where n is a number between 0 and 127 and m is a positive or negative +integer. The purpose of these commands is to provide to set the velocity of +the note immediately following. All remaining notes are unaffected. +The commands override the effects of %%MIDI beat, %%MIDI beatstring, +%%MIDI beataccents, %%MIDI beatmod, %%MIDI nobeataccents, +%%MIDI stressmodel, !ppp!, !pp!, !p!, !mp!, !mf!, !f!, !ff!, !fff!, +!crescendo) for the particular note +that is affected. + +%%MIDI vol n + +sets the velocity of the next note to n. + +%%MIDI volinc m + +increments (or decrements) the velocity of the next note +by m, automatically ensuring that the velocity is in the +range 0 to 127. + +For example: + + +X: 1 +T: Velocity alteration +M: 4/4 +L: 1/4 +K: F +CDEF|C\ +%%MIDI volinc -30 +D E [I: MIDI = vol 100] F| CDEF| + +By default the velocities of the notes CDEF are 105, 80, 95 and 80. +(You can use the %%MIDI beat command to change these values.) +The %%MIDI volinc -30, decrements the default velocity of D by +30 so its velocity is 50 instead of 80. The MIDI vol 100 +command embedded in the info field, sets the velocity of F +to 100. The velocities of the remaining notes in the last +bar retain their defaults 105,80,95 and 80. + +Implementation: + +Introduced two global integer variables single_velocity_inc and +single_velocity which are set to the default values 0 and -1 +in the writetrack() in genmidi.c. These default values indicate +that no alterations are to be made to the following note. +Introduced new functions apply_velocity_increment_for_one_note() +and set_velocity_for_one_note() which is called by noteon() +in genmidi.c. The function dodeferred() in genmidi.c acts +on the new %%MIDI commands and changes the default values of +single_velocity_inc and single_velocity. + + + +September 08 2015 + +Abc2midi new feature: a different syntax can be used for changing +the velocity of a single note as illustrated below. + +X: 1 +T: Velocity alteration -different syntax +M: 4/4 +L: 1/4 +K: F +CDEF|C\ +I: volinc = -30 +D E [I: vol = 100] F| CDEF| + +The behaviour is identical to the above example. + +Implementation: the function event_info_key() in store.c was updated +to recognize the key words vol or volinc, generate the respective +%%MIDI commands, and send these commands to event_specific() for +processing. + + + +September 08 2015 + +Abc2midi: new feature. The I: info command required to have an +'=' sign following the key word, so that it could handle a +group of commands such as +I: MIDI = program 20 MIDI = drum d2dd 76 75 75 +The purpose of the '=' sign was to allow the parser to +distinguish the key word(s) (here MIDI) from the value when more +than one key words appear. When only one command is embedded +it should be unnecessary to include the '=' sign. The +following sample illustrates the more lenient syntax that +is now permitted. + +X:1 +T: Generalized info syntax +M: 2/4 +L: 1/8 +K: F +I:vol= 60 +% equal sign is optional if only key word is included +% in I: field. +C2 E2 | [I:vol 20] D2 F2| E2 [I:volinc = 50] C2|D2 [I:volinc -50]C2| +C2 E2 |\ +%%MIDI vol 20 +D2 F2|E2 \ +% equal sign is required if more than one key word is present +I: MIDI= drum d2dd 75 76 76 MIDI = program 20 +%%MIDI volinc 50 +C2| +C2 E2| [I:MIDI= vol 20] D2 F2| + + +Implementation: the function event_info() in parser2.abc was +updated. + + + +October 04 2015 + +The #ifdef _MSC_VER block was changed from + #define snprintf _snprintf_s +to + #define sprintf _snprintf +in both parseabc.c and store.c +(The function _snprintf_s expects additional parameters and +prevents compilation on some systems.) + + +October 04 2015 + +Some problems with Makefile.in were fixed. In addition an uninstall +option was introduced. + +October 03 2015 + +Abc2midi: increased the size of benddata[100] to benddata[256], +controldata[MAXLAYERS][100] to controldata[MAXLAYERS][256], +%%MIDI bendstring will read up to 256 values in dodeferred (genmidi.c). +%%MIDI controlstring will read up to 256 values in doferred (genmidi.c) +eventlist struct was increased to eventlist[1000]. + + +October 08 2015 + +Edited abcmatch.c genmidi.c midi2abc.c parseabc.c store.c toabc.c in order +to eliminate warnings from Microsoft Visual Studio 2010. +makefiles/makefile.w32 was updated to make dynamically linked executables +(instead of static). + + +October 18 2015 + +Edited abcmatch.c, genmidi.c, matchsup.c, mftext.c, midi2abc.c, midicopy.c, +midifile.c, parseabc.c, queues.c, store.c, stresspat.c and toabc.c +to clean up all the implicit int warning messages reported by the +Debian compiler. + + +November 05 2015 + +abc2abc: + +keep 'M:C' and 'M:C|'; i.e. don't automatically change them to +'M:4/4' and 'M:2/2' + + +% sample4.abc - this file is part of abcm2ps +X:1 +%%abc-version 2.0 +T:testing 'common time' and 'split common time' signatures +T: These should be preseved when transposing +% use abc2abc generated from source including fixes from 'abcMIDI-2015.11.5_LM'. +% try command: 'abc2abc common_time_sigs.abc -t 2'; +% check that e.g. 'C' hasn't become '4/4'. +M:C +L:1/4 +K:C +CDEF |[M:4/4] GABc|] +M:2/2 +CDEF |[M:C|] GABc|] + + +November 15 2015 + +Addressed the following Debian compiler warning messages reported in +https://qa.debian.org/bls/packages/a/abcmidi.html + + I pointer-cast-size-mismatch midicopy.c:371 (alpha, arm64, kfreebsd-amd64, mips64el, ppc64, ppc64el, s390x, sparc64) + I pointer-cast-size-mismatch yapstree.c:1338 (alpha, arm64, kfreebsd-amd64, mips64el, ppc64, ppc64el, s390x, sparc64) + I pointer-cast-size-mismatch yapstree.c:1352 (alpha, arm64, kfreebsd-amd64, mips64el, ppc64, ppc64el, s390x, sparc64) + I pointer-cast-size-mismatch yapstree.c:1513 (alpha, arm64, kfreebsd-amd64, mips64el, ppc64, ppc64el, s390x, sparc64) + I pointer-cast-size-mismatch yapstree.c:2176 (alpha, arm64, kfreebsd-amd64, mips64el, ppc64, ppc64el, s390x, sparc64) + W implicit-declaration abcmatch.c:1274 (alpha, arm64, armel, armhf, hppa, hurd-i386, i386, kfreebsd-amd64, kfreebsd-i386, mips, mips64el, mipsel, powerpc, ppc64, ppc64el, s390x, sh4, sparc64, x32) + + +In yapstree.c changed (void*) to (int *) to the calls to addfeature. +In midicopy.c changed the call arguments of metaseqnum from +(int seq) to (char c1, char c2). +In abcmatch.c added #include + + +December 19 2015 + +Abc2midi: bug fix - calculation of equal temperament scale was changed +on October 08 2015. It has now been restored in store.c thanks to +Hudson Lacerda. + + + +December 31 2015 + +Abc2midi bug: + +The following tune causes abc2midi to crash when running with -BF parameter. + +X:1 +T: Missing R: field +M: 2/4 +L: 1/8 +K: G +%%MIDI stressmodel 2 +CDEF|ABcd| + +abc2midi crash.abc -BF 2 +3.84 December 19 2015 abc2midi +Floating point exception + +Fix: startfile() in store.c initializes rhythmdesignator to an empty +string. apply_bf_stressfactors() in store.c ensures that rhythmdesignator is +set before allowing the function to continue. The function +load_stress_parameters() in stresspat.c now has an error return and reports +an unidentified rhythmdesignator to apply_bf_stressfactors(). + + +January 02 2016 + +Abc2midi > and < action: + +In the past broken notes indicated by A>B and AB A G, h --> B, and i --> D +%%MIDI gchord ghighi +"G" G6|G6|\ +% "G5" expands to G,D so g--> G, and h --> D but i --> does not map +"G5" G6|G6| + +i does not map producing a gap in the Alberti Bass + +Fix: dogchords() in genmidi.c was modified to map to the last +note in the gchord chord in this situation to prevent a gap. +In the above example i would also map into D. + + +February 08 2016 + +Abc2midi: changed dim9[5] to {0,3.6,9,13}, added sus2 and 7sus2 +(in store.c). + + +March 03 2016 + +Abc2abc: K: none sets all following occurrences of K: field +to K: none even when they occur in separate tunes. + +Analysis: the global variable nokey gets set by K: none, +but is never reset. This is fine if you are using the -nokeyf or +-nokeys runtime parameter which applies to all tunes but not +what you want if you are dealing with a tune containing a +K: none command. + +Fix: introduced a new global nokeysig initialized to 0 +into parseabc.c and toabc.c which responds to the abc2abc runtime +parameters -nokeys and -nokeyf. In parsekey() in parseabc.c, +the control variable nokey is initialized to nokeysig. + +March 15 2016 + +Fixed an assortment of spelling mistakes in the documentation in +this file. (Also readme.txt, abcguide.txt, genmidi.c, toabc.c, abc2midi.1, +crack.c, midi2abc.1, history.txt, coding.txt). Thank you Ross Gammon. + + +May 05 2016 + +Abc2abc: transposition of key modifier bug. + +The following example illustrates a problem with the code +to transpose the key modifiers. + +X: 25 +T: C Natural, with a D sharp added to the key signature +M: 2/4 +L: 1/8 +K: C ^d +| cdef | gabc | + +Transposing this up by one tone (-t 2), this becomes + +X:25 +T:C Natural, with a D sharp added to the key signature +M:2/4 +L:1/8 +K:Dmaj =F +| defg | abc'd | + +The key modifier was transposed to F natural instead of +e sharp (chromatically identical notes) but as a result + e was not upgraded to e# and the f# became f natural. + +The fix was a completely replacement of the code written +in February 21 2011 (see above) in toabc.c. 130 lines of +code was eliminated and a new function transpose_note() +was introduced. The new function borrowed the transposition +code from event_note, so that key modifiers were transposed +the same way the notes in the music body are modified. + + +July 20 2016 + +Midi2abc: note grouping for 3/4 time is incorrect. +For 3/4 meter midi2abc groups the notes as EFG AGF instead +of EF GA GF in a bar. + +Fix: in printtrack_with_splits(), printtrack_split_voice(), +and printtrack(), also check for waltz time (asig == 3) +before grouping notes as compound rhythm. + + +September 20 2016 and September 25 2016 + +Abc2midi: only handles user defined symbols between 'H' and 'Z'. + +Fix: allow user defined symbols between 'A' and 'z'. Also applies +to abc2abc and yaps. Parseabc.c was upgraded. + + +January 01 2017 + +Midi2abc: There are times when you may wish to suppress broken +rhythms but still allow triplets. For example, + +X:1 +T:A Tune For Paddy: A Pint Of Guiness And One For The Goat +M:6/8 +K:Emin +edB AGF | GEE E3 | +edB AGF | GEE E3 | + +Applying abc2midi and midi2abc results in the second and +forth bar appearing as GEE2D you need to use -nb. + + +February 01 2017 + +abc2midi: %%MIDI gchordbars bug. The gchordbars factor does +not start working until after the first bar. For the following example, + +X:1 +T: gchordbars +M: 6/8 +L: 1/8 +K: C +%%MIDI gchordbars 2 +%%MIDI gchord fffhhh +"G" G6|D6|G6|D6|G6|D6| + +The gchord accompaniment is not expanded until after the first +bar. + +Analysis: The variable gchordbarcount needs to be reset to 0 after +each call to set_gchords(). checkbars() will set gchordbarcount to +gchordbars if it is 0. Simarly drumbarcount should also be reset +after each call to set_drums(). The code is still temperamental, +so ensure that the MIDI gchordbars statement occurs prior to the +MIDI gchord declaration and precedes the bar line where it will +be applied. + + +April 10 2017 + +Abc2midi bug: abc2midi fails to create a midi file for + +X:1 +T: Microtone +M: 4/4 +L: 1/4 +K: G staffscale =1.2 +G F G =F| + +staffscale = is a specification for abcm2ps which is not +recognized by abc2midi. parsekey is attempting to treat +=1.2 as a specification of a microtone in the key signature. +sscanf() returns only one parameter instead of 3. + +if (j > 7) j = (int) c - 'a'; +if (j > 7 || j < 0) {printf("invalid j = %d\n",j); exit(-1);} + +j is not a valid value because the variable c is 0. + + + +Fix: changed + +success = sscanf (&word[1], "%d/%d%c", &a, &b, &c); + if (success > 0) + +to + +success = sscanf (&word[1], "%d/%d%c", &a, &b, &c); + if (success == 3) + + + +April 12 2017 + +Abc2midi,Abc2abc,Yaps new feature: Abcm2ps has many features +for creating a nice document. Abc2midi and other programs in +the abcmidi package may get confused when it sees certain lines. +I have introduced two new commands + +%%MidiOff +and +%%MidiOn + +which tell abc2midi and other programs to not parse the lines +in between. + +For example: + +X:1 +T: Booth Shot Lincoln +C: Traditional +C: Arr. Pete Showman +R: Reel +Q: 1/2=90 +M: 2/2 +L: 1/8 +K:A +|| y20 "A"ce2c e2ee | "D"fa2f a2fe- | \ +"A"eBcB AcBA | "D"F3F F2FF | +%%MidiOff +%%begintext + The next lines will not be played +%%endtext +%%MidiOn + +The commands %%MidiOff and %%MidiOn, delineate a block +of text that we do not want the parser to process. Otherwise, +all the e's, b, a and d in the line "The next lines..." +be treated as notes to be played in the output midi file. + + +Implementation: +Introduced a new global in parseabc.c, int ignore_line, which +is either 0 or 1. When it is set to 1, parseline() in parseabc.c +will ignore that line. ignore_line is automatically initialized +to 0 any time a new X: command is encountered. + + +April 16 2017 + +Fixed a bug I introduced in parseabc.c on April 12 2017. + +Had changed +parse_precomment (s) + char *s; + +to + +parse_precomment (s) + char **s; + +in order to eliminate a compiler warning; however, +this caused abc2midi to treat %%MIDI as a text comment. + + +April 19 2017 + +Abc2abc invisible rest bug: the invisible multirest X gets +transposed to Z. When transposing the following tune, + +X:1 +T: Invisible rests +M: 4/4 +L: 1/4 +K: G +ABcx|X2| + +X is changed to Z + +Analysis: parsemusic() in parseabc.c treats the multirests +X and Z the same way in event_mrest(). + +Fix: added a char parameter to event_mrest() so it knows +whether it is a X or a Z. This effects store.c, toabc.c, +yapstree.c and matchsup.c. + + + +June 02 2017 + +Abc2midi: Some of the documentation which comes with abc2midi +states that the MIDI program number should range between 1 and 128; +however, as far back as 2003, abc2midi expects the range to be +between 0 and 127 following the MIDI standard. The documentation +abcguide.txt and the man page abc2midi.1 have been corrected. +Unfortunately, the Abc standard was based on the old documentation. +It is too late to change abc2midi to comply with the abc standard +since there are too many abc existing files using the current +convention. As a temporary compromise, I have added a new +command %%MIDI programbase. + +The current default is (so you do not need this line). +%%MIDI programbase 0 + +To change to the abc standard use +%%MIDI programbase 1 + +Implementation: added global +int programbase = 0; +to store.s which can be modified by the %%MIDI programbase command. + +Genmidi.c links to programbase using an extern statement and +in the function write_program() I added the lines. + p = p - programbase; /* [SS] 2017-06-02 */ + if (p <0) p = 0; /* [SS] 2017-06-02 */ + +Test file: + +%%MIDI programbase 1 +X:1 +T: timpani +% The timpani has MIDI program number 47 if you count from 0 +% or 48 if you count from 1. +M: 2/4 +L: 1/8 +K: C +%%MIDI program 48 +CCDD|EEFF|CDEF|CDEF| + + +June 10 2017 + +Abcmidi: !shape! bug + +In the following example: + +X: 1 +%%MIDIdef peta bendstring 0 0 900 900 0 -900 -900 0 -400 +%%MIDIdef volon125 controlstring 11 125 +T: shape bug +C: 1 +M: 4/4 +L: 1/4 +Q:1/4=130 +K: C +%%MIDI program 64 +AGGF|\ +[I: MIDIx= peta]!bend!F[I: MIDIx=volon125]!shape!GAB| + +The note G in the second bar following !shape! is held +too long. + +Analysis: note_effect5 ends a note with + midi_noteoff(delta, Q[Qhead].pitch, Q[Qhead].chan); +however the delta does not account of the numerous pitchbend +commands which has shifted the time base to the end of the +note. + +Fix: computed last_delta = delta - eventlist[j-1].time; /* [SS] 2017-06-10 */ +and used that to end the note. +midi_noteoff(last_delta, Q[Qhead].pitch, Q[Qhead].chan); + + +July 10 2017 + +Abc2abc: new feature + +Added runtime reference -xref n which will only output the tune +with reference number n. + +Implementation: in toabc.c add global integer xmatch which is set +to n when the -xref parameter is found. Otherwise it is set to +-1. The function event_refno(n) turns the parser on or off. +We needed to add 'extern parsing' in order to handle blank lines +in event_blankline(). All % abcm2ps directives unfortunately +must be printed since they may not be embedded in the particular +tune. + + +July 11 2017 + +Abc2midi infinite loop. The following tune causes abc2midi to +become unresponsive and go into an infinite loop. + +X:1 +T: abc2midi infinite loop +P:A-B +M: 4/4 +L: 1/4 +K:C +P:A +DDDD| +P:B +EEEE| + +The loop occurs in the function read_spec() in store.c +which processes the line P:A-B. Fix: added a line +to increment the character pointer when it encounters the +character - or +. + + +August 9 2017 - September 19 2017 + +Midi2abc - added new option (-stats) to gather and print statistics +of a midifile. (eg. number of notes for a particular channel +in a particular track). This will be used by a new application +called midiexplorer. (The output is not documented and it is +work in progress.) + + +August 30 2017 + +Midi2abc - The metatext string is not terminated with a 0 and +as a result can contain random junk, in particular on the Windows +operating system. Fix in midifile.c, the Msgbuff is initialized to +0 when it is allocated. + +September 12 2017 + +Midicopy - two fixes to cover some unusual situations. + +September 18 2017 + +Midicopy - another fix + + +October 9 2017 +Abc2abc bug: the program crashes when it tries to parse the line + +V: V1 clef=treble2 middle=B nm="" snm="" merge stem=auto gstem=auto dyn=auto lyrics=auto gchord=auto scale=1 staffscale=1 stafflines=5 + +Fix: the buffer output[32] was expanded to output[128] to handle long +lines in event_voice in toabc.c + + +October 11 2017 + +Abc2abc bug: + +V: V1 clef=treble2 middle=B nm="" snm="" merge stem=auto gstem=auto dyn=auto lyrics=auto gchord=auto scale=1 staffscale=1 stafflines=5 + +parameters chopped short. Fix: in parseabc.h increased V_STRLEN to 256. +Probably effects abc2midi too. + + +October 18 2017 + +Abc2midi: the complex guitar chords which extend over one octave, were +converted from closed form to open form in store.c. For example: + /* static int list_11[6] = {0, 4, 7, 10, 2, 5}; */ + static int list_11[6] = {0, 4, 7, 10, 14, 17}; + + +October 22 2017 + +Midicopy: cleaned up the code somewhat. Midicopy no longer outputs +tracks that are not needed. + + +October 23 2017 +abc2midi and yaps: The parser normally reports a warning +Potentially ambiguous line - either a :| repeat or a field command -- cannot distinguish. +when it sees a line like +A:|cdef|A4| +or +B:|cdef|A4| +(The A: or B: could be interpreted as field commands.) By default the +line is treated as a music line, and in most cases everything works fine. +However, for a line like +w:| A____le-lu-ia | A____le-lu-ia a-le-lu-| +we would prefer that it is treated as a w: command or lyric line. + +Fix: parseabc.c was modified to make a special exception for the +w: line and call preparse_words(). + + +November 01 2017 November 08 2017 November 10 2017 November 19 2017 + +Midi2abc: minor enhancement for -stats function. + + +November 27 2017 +Midicopy: introducing new options -focusontracks n1,n2,... and +-focusonchannel n1,n2.... This attenuates the velocity values of the +notes in all tracks (channels) except except n1,n2,... by the +attenuation (default 70) units. The attenuation can be specified +by -attenuation n. + +December 06 2017 +Midicopy: added an option -xchns to exclude specific channels. + + +December 10 2017 +Abc2midi: abc2midi now implements the command +%%abc-include per.abc +where per.abc is typically a header file which defines various +global parameters. For example, the file could remap the channel +pitches to particular percussion instruments using the %%MIDI drummap +command. + +Implementation: in genmidi.c the function parse_drummap() is no longer +static so it can be called in store.c. In store.c, the command +%%MIDI drummap is recoginized in the function event_specific_in_header(). +The function init_drummap, is no longer activated in the function +finishfile(), but only once in the main() function. This means that, +the %%MIDI drummap command will apply to all the tunes in the file, +irrespective of whether it is in the header (global) area. Finally, +parsefile() in parseabc.c has been extended to recognize the +abc-include file. All the contents of this include file are parsed +as if the lines were included in the open abc file, except that the +line counters do not count the lines in the include file. The +extension to parseabc.c also impacts abc2abc, yaps, and abcmatch. + +December 15 2017 +Midicopy: added -nobends option. + + +December 20 2017 +Midi2abc bug: When midi2abc.c is compiled without the debugger on +Debian Linux, it fails with the message +**buffer overflow** +On compilation there are frequent warnings: +n function 'strncpy', + inlined from 'setupkey' at midi2abc.c:3209:3: +/usr/include/x86_64-linux-gnu/bits/string3.h:126:10: warning: call to __builtin___strncpy_chk will always overflow destination buffer + return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); + +Analysis: strncpy was attempting to copy 16 characters from a 12 character +string into a 12 character string. + +Fix: changed strncpy to memcpy and limited the copy to 12 characters. + + +January 02 2018 January 24 2018 February 07 2018 February 22 2018 + March 06 2018 +Midi2abc -stats (detecting key signature and time signature meta commands) +Midi2abc -stats returns pitchentropy +Midi2abc -stats returns drumhits, progs, progsact +Midi2abc -stats check for program number between 0 and 127 + + +February 22 2018 + +Abc2abc does not handle correctly the %%MidiIOff and %%MidiOn +which was introduced on April 12 2017 as seen below. +X:1 +T:Booth Shot Lincoln +C:Traditional +C:Arr. Pete Showman +R:Reel +Q:1/2=90 +M:2/2 +L:1/8 +K:A +|| y20 "A"ce2c e2ee | "D"fa2f a2fe- | \ +"A"eBcB AcBA | "D"F3F F2FF | +ignore_line = 1 + + + + +ignore_line = 0 +%%MidiOn + +Janus Meuris (jmeuris@gmail.com) has contributed several fixes and +minor improvements to parseabc.c, toabc.c and store.c. + +In parseabc.c, the printf("ignore_line ...") was removed from +handle_abc2midi_parser(). The error message "Single colon in bar" +was removed since it is perfectly legal in music notation. +In parseline() flushes out the blocked lines enclosed by MidiOff and +MidiOn in the case that abc2abc is running. + +The abc2abc output now looks like: +X:1 +T:Booth Shot Lincoln +C:Traditional +C:Arr. Pete Showman +R:Reel +Q:1/2=90 +M:2/2 +L:1/8 +K:A +|| y20 "A"ce2c e2ee | "D"fa2f a2fe- | \ +"A"eBcB AcBA | "D"F3F F2FF | +%%MidiOff +%%begintext + The next lines will not be played +%%endtext +%%MidiOn + + +In toabc.c, in printlen(a, b) , an option to print a/2 and a/4 as +a/ and a// was introduced. + +In store.c, more warnings were suppressed. A guitar chord beginning +with a space is also ignored -- eg. " A major" + + +March 08 2018 +abc2abc bug: abc2abc deletes the leading space in the string following +the w: field command. For example + +X:1 +T:foo +M:4/4 +L:1/4 +K:C +c d e f | c d e f | +w: | he-llo wor-ld | + +There is a space following w: to prevent parseline from seeing :|. +Unfortunately, abc2abc produces +w:| he-llo wor-ld | +which poses a problem to abc2midi. + +abc2midi out.abc +4.02 February 22 2017 abc2midi +Warning in line-char 7-18 : Potentially ambiguous line - either a :| repeat or a field command -- cannot distinguish. + +Analysis: the leading blank was already removed by parseline() in parseabc.c +by the time that preparse_words() sees the text. Rather than messing +around with parseabc.c, I modified event_field() in toabc.c so that it will +automatically place a space between : and | whether or not it is missing. + + +March 21 2018 +abc2midi bug: The only the A part is rendered by abc2midi and +there is no error message. + +X:1 +T: parts +M: 6/8 +L: 1/8 +P: A BB CC +K: G +P:A +DCB BAG| +P:B +GGB CBG| +P:C +GF2 G3| + +Analysis: the P: command should be written as ABBCC without the spaces. +When this is done, the tune is rendered correctly. The code for deciphering +the P: command (read_spec() in store.c) has been unmodified +since I have taken over the support of abc2midi. For some reason, +the P: specification allows the user to use a dot '.' to control +the spacing of the command; so A.BB.CC would be legal; however, +the use of spaces causes the command to fail. + +The P: command has served two purposes in the past. When the abc +notated tune is rendered to sheet music, the P: command has also +been used to label the different sections of the tune. As a result, +if the P: command does not follow the exact syntax, abc2midi assumes +it is not being used for controlling repeats and ignores the command. +When P: is used for controlling repeats only the characters A-Z, +0-9,-,+,(,), and . are allowed. If a different character, say lower +case letters are encountered, read_spec() immediately ignores the +rest of the specification without any error message. + +Fix: the code read_spec() was upgraded so that it now reports +an error in the event that the P: command in the header does not +follow the correct syntax. This can lead to a lot of error messages +if the P: command was used for adding comments to the title. +Fortunately, the user can use the -silent option to suppress these +messages. Furthermore, if read_spec encounters this error, it +restores the state of abc2midi so that all the parts are still +played (in the same order that they are presented and with no repeats). + +Finally, I do not see any reason why read_spec() should fail when +it encounters spaces, so I have modified the code so that spaces +can be used to improve the clarity of the command. + + +April 01 2018 + +abc2midi reports an error when it encounters a within body I: which +does not contain one of the keys octave, MIDI, MIDIx, vol, or volinc. +For example, for the file + +X: 1 +T: Test 2 - I:leftmargin, I:rightmargin +T: abcm2ps sets the page margins +L: 1/4 +M: 4/4 +K: C +% +I:leftmargin 3cm +I:rightmargin 3cm +CCCC|DDDD|EEEE|FFFF|GGGG| + +abc2midi normally returns: +Error in line-char 8-0 : I: key ' leftmargin' not recognized +Error in line-char 9-0 : I: key ' rightmargin' not recognized +writing MIDI file test21.mid + +The error messages can now be suppressed by running abc2midi with +either the -quiet or -silent run time option. + + +April 14 2018 + +abc2midi bug: the following file + +X:1 +%%MIDI ptstress 3 100 1.5 100 0.75 100 0.75 +T: Barfly stress test +L:1/4 +M:3/4 +K:C +gGg | GgG | gGg | GgG | gGg | GgG + +does not apply the Barfly stress model when abc2midi +is called with the -BF option, but it works correctly +when the -BF option is not included in the runtime parameters. +This can be a confusing issue when abc2midi is called from +a user interface such as EasyAbc. + +Analysis: when the -BF option is included, abc2midi is looking +for a R: designator and attempts to match the rhythm designation +with one of the rhythms in the library. If it fails then the +stress model is turned off despite the fact that the stress +pattern has been specified explicitly by a %%MIDI ptstress command. + +Fix: parse_stress_model (in genmidi.c) is called when a +%%MIDI ptstress command is encountered. If the command is valid, +parse_stress_model sets beatmodel to 2 enabling the Barfly +stress model. + +April 15 2018 + +abc2midi bug: + +If the -BF runtime parameter is not followed by 1 or 2 (as it +occurs in EasyAbc), the stress model should default to 2, the +Barfly model instead of 1. This has been fixed in store.c. + + +April 16 2018 + +abc2midi bugs: more issues with the %%MIDI ptstress command. The +%%MIDI ptstress command was working for the Barfly model 1, but +was never working for Barfly model 2. + +Model 2 is applied as a separate pass to the abc file +by the function apply_bf_stress_factors() in store.c. It essentially +changes all the note length values prior to creating the midi file. +The %%MIDI ptstress command is processed by dodeferred() in genmidi.c +during the last pass when the midi file is being written. This is +already too late. In order to fix this issue the processing of +the %%MIDI ptstress command was moved to the function event_midi() +in store.c. + +There is also a conflict on how the stress factors are determined. +If no %%MIDI ptstress command is present, abc2midi normally uses the +builtin stress factors which are selected by the rhythm designation +in the R: command. It is necessary to disengage this mode when +the %%MIDI ptstress command is present. A new variable, +stress_pattern_loaded was used to signal that the stress factors +were set by %%MIDI ptstress. + +Please note that the abc tune should have not more than one +%%MIDI ptstress command. If more than one is present, only the +last one is effective. The %%MIDI ptstress command requires knowing +the meter of the music, so it should be placed after the M: time +signature specification. By default, the ptstress command assumes +model 2; however, if you wish to use model 1, you can include +%%MIDI stressmodel 1 command. + +Here is a sample use of the ptstress command. + + +X:1 +T: another Barfly test +M:3/4 +%%MIDI ptstress 3 120 1.6 60 0.8 40 0.6 +L:1/4 +R: Waltz +K:C +cc/d/e | d2g | e/d/ cB | c3 :| + +The R: designation is unnecessary and will be ignored. Furthermore, +you do not need the -BF runtime parameter unless you want to +select model 1. + + + +April 24 2018 + +Midi2abc -stats: some midi files do not define the channel to +program assignments until we reach the last track number. This +results in erroneous data in the progs and progcolor output. +Fortunately we also compute the chanactivity. We can fix this +problem by transfering the chnactivity to the progactivity. + + +May 02 2018 + +Abc2midi - deprecated !ped-end! and introduced !ped-up! in +store.c + +June 13 2018 + +Midi2abc - catches negative time increment in midi file. +Check made in readtrack() in midifile.c + + +June 23 2018 + +Abc2midi bug: the %%MIDI gchordbars n command is very +idiosyncratic and only works correctly unless the abc is +formatted exactly like this. + + +X: 1 +T: gchord +M:4/4 +L:1/4 +K: G +%%MIDI gchord ghih +"G" z4 +%%MIDI gchordbars 4 +%%MIDI gchord ghih +| z4| z4| z4| z4| + +it will not run correctly if the input looks like + +X: 1 +T: gchord +M:4/4 +L:1/4 +K: G +%%MIDI gchord ghih +"G" z4 | +%%MIDI gchordbars 4 +%%MIDI gchord ghih +"G" z4| "G" z4|"G" z4| "G" z4| + +(Bar line appears just before %%MIDI gchordbars rather than after.) + + +Fix: the variable gchordbarcount was eliminated since it was +not useful and the cause of some problems in the function +checkbar(). In dogchords(), we check that g_ptr does not exceed or +equal the length of the gchord string. In dodeferred(), we +reset g_ptr to 0 when we encounter a %%MIDI gchordbars command. + +Abc2midi bug: the %%MIDI drumbars n command is also idiosyncratic +in a similar fashion. + +Fix: the drumbars feature was implemented in the same way as +the gchordbars, so all of the above applies. + + +October 25 2018 + +midi2abc: introduced option mftextpulses which will output in +pulse units instead of beat units. + + + +December 01 2018 + +abc2abc bug: for multivoiced files where the voices are interleaved, +abc2abc produces error messages regarding repeat symbols. For example, +seymour@corsair:~/abc$ cat repeats.abc +X:1 +T: abc2abc repeats in multivoice +M:4/4 +L:1/4 +K:G +[V: S] gfed|: abcd | +[V: A] edcB|: ABCD | +[V: H] GFED|: ABCD | +[V: S] abcd :| +[V: A] ABCD :| +[V: H] ABCD :| + +abc2abc repeats.abc +X:1 +T:abc2abc repeats in multivoice +M:4/4 +L:1/4 +K:G +[V:S] gfed|: abcd | +[V:A] edcB +%Error : Expecting repeat, found |: +|: ABCD | +[V:H] GFED +%Error : Expecting repeat, found |: +|: ABCD | +[V:S] abcd :| +[V:A] ABCD +%Warning : No repeat expected, found :| +:| +[V:H] ABCD +%Warning : No repeat expected, found :| +:| + +Analysis: in event_bar in toabc.c, the variable expect_repeat +determines whether the error message is emitted. This works +well as long as each voice is processed in sequence but +when the voices are interleaved, it is nececessary to maintain +the expect_variable for each voice. The expect_repeat variable +was moved to the voice struct. Unfortunately event_bar +(which is used in abc2midi, yaps, and abcmatch) does not pass +the voice struct, so it was necessary to reference the +voice struct as a global variable. + +December 17 2018 + +abc2midi: does not recognize the abcm2ps options when embedded +in a inline information command. For example, +K: G clef=bass +F [I:setbarnb 1]| +appears in one of the abc files. [I:setbarnb 1] tells abcm2ps +to start counting bar numbers here from 1. However, abc2midi +does not recognize this command and outputs the message: + +Error in line-char 269-2 : I: key ' setbarnb' not recognized + +There are numerous abcm2ps options that can be embedded in +an abc file. I am not too sure how to handle this situation. +I can give abc2midi the most common messages and tell it +to ignore these. In store.c I introduced the function +is_abcm2ps_option(). Presently I only check for setbarnb. + + +December 21 2018 + +abc2midi: does not recognize THICK_THIN bar line. In the +following example, + +X: 1 +T: THICK_THIN bar line +M: 2/4 +L: 1/8 +K: D +EDFD|FGD2]| + +abc2midi reports the error +Error in line-char 6-9 : Chord already finished + +Analysis: ]| is a type of bar line, however abc2midi assumes that +] is ending a chord. Fix: in the function parsemusic() in parseabc.c +we now check that whether we are in a chord before calling event_chordoff. +We introduce a new function event_ignore() in store.c, yapstree.c, toabc.c, +and matchsup.c to handle such situations. + +December 28 2018 + +toabc.c +The gcc compiler produces numerous warnings like +toabc.c:1223:45: warning: '%s' directive writing up to 256 bytes into a region of size 250 [-Wformat-overflow=] + if (vp->gotclef) {sprintf(output," clef=%s", vp->clefname); +fix: changed output[250] to output[300] in event_voice. + +January 01 2019 + +abc2midi: warnings from time signature change. + +Abc2midi processes this file without warnings. + +X:1 +T: time signature placed at the beginning of the bar +M: 3/4 +L: 1/8 +K: G +C2 C2 C2 |[M:2/4] C2 C2 |[M:3/4] D2 D2 D2 | [M:2/4] E2 E2| + +However, abc2midi produces several warnings when the time signature +is placed before the next bar line. + +X:1 +T: meter change +M: 1/4 +L: 1/4 +K: G +C [M:2/4] | C C [M:3/4] | D D D [M:4/4]| E E E E [M:1/4]| C| + +Warning in line-char 6-24 : Track 0 Bar 1 has 2 units instead of 3 +Warning in line-char 6-39 : Track 0 Bar 2 has 3 units instead of 4 +Warning in line-char 6-56 : Track 0 Bar 3 has 4 units instead of 1 + +Analysis: Note that measures count from zero. Though both forms +are musically correct, the latter form confuses abc2midi. Abc2midi +applies the time signature to the bar in which it is embedded. +To fix this issue, I introduced the function +check_for_timesig_preceding_bar_line () in genmidi.c +It scans the entire feature[] representation of the tune and +switches TIMESIG with SINGLE_BAR any time TIME_SIG is immediately +followed by SINGLE_BAR. This function is applied prior to writing +the tracks in the midi file. + +January 20 2019 + +abc2midi: suppressing the warning "clef= is overriding octave= setting" +when the clef is specified in the K: or V: command. Parseabc.c was modified. +It probably effects abc2abc, yaps, and abcmatch. + +January 31 2019 + +abc2midi: offering the option to suppress the messages +4.11 January 01 2019 abc2midi +Warning in line-char 20-11 : Different length notes in tuple +Warning in line-char 20-13 : Different length notes in tuple +Warning in line-char 21-4 : Different length notes in tuple +Warning in line-char 21-6 : Different length notes in tuple +.... +using the -quiet option + +(A lot of early baroque music may contain tuplets of different +length like: +[M:2/1](3F6E2D4 | (3C6D2E4 | (3D6E2F4 | (3:2:4G6F2D2E2 | (3F6E2C4 | + +Abc2midi should be able to handle tuplets with notes of different lengths. + + +February 08 2019 + +abc2midi: does not recognize dotted bar lines. In the example, + +X:1 +T: Dotted bar lines +M: 2/4 +L: 1/4 +K: D +GA : BD|EF : CF| D2 : D2| + +abc2midi returns the message +Warning in line-char 17-13 : Track 0 Bar 1 has 4 units instead of 2 +Warning in line-char 17-22 : Track 0 Bar 2 has 4 units instead of 2 + +Fix: in abc.h introduced DOTTED_BAR in featuretype. +In parsemusic() in parseabc.c call event_bar(DOTTED_BAR,"") if a +':" occurs by itself. In event_bar() in store.c the DOTTED_BAR is +treated the same as the DOUBLE_BAR. + +March 14 2019 + +abc2midi: warnings and error messages reference the wrong line number. +For example for the tune + +X:1 +T: warnings +M: 4/4 +L: 1/4 +K: G +[V:1]A| +[V:2] A| +[V:1]Bcd| +[V:2]EFGA| +[V:1]DAxD| +[V:2]Bcd| +[V:1]EFGA| +[V:2]DAxD| + +abc2midi reports that bar 1 (Bcd) has 3 beats instead of 4 in line 7. +Line numbers start from line 1, so bar 1 is in line 8 and not line 7. +Analysis: writetrack() in genmidi did not see feature(LINENUM) because +it bypasses the features whose voice is not the actual voice (track) +being written. Fix: the function findvoice() in genmidi.c now ensures +that the global variable lineno is always updated. + + +Mar 18 2019 -- Mar 22 2019 + +abc2midi new feature: if one is not careful, it is easy for one or +more voices to get out of synchronization with the other voices. +When the abc music score is displayed, the barlines +do not align. Abc2midi checks whether the number of beats in +a bar matches the time signature. However, it does not check +whether the beats in the corresponding bars in the different +voices, match. This is rather difficult to do, since abc2midi +writes out each track sequentially. As an experiment, +abc2midi counts the number of beats played up to each bar line, +and as an option (-c) will output these numbers in a file +called barloc.txt for each voice. The numbers should match for +all voices. Recall that the -c option processes the entire abc +file (which may contain numerous tunes) and only returns warnings +and error messages without producing any midi files. +In this implementation barloc.txt only applies to the first +tune in the file. (This feature is still experimental.) + +Implementation: introduced the integer array, barloc[1024] in genmidi.c +which can handle up to 1024 measures in the tune. This array is +reused for each voice. In checkbar() in genmidi.c, barloc[barno] +stores the current track length (in midi pulses). A new function, +dump_barloc() is introduced in genmidi.c that writes the barloc +data in barloc.txt file. In store.c, introduced a new file handler +diaghandle for creating the output file barloc.txt. dump_barloc() +is called from finishfile() in store.c when abc2midi is running +with the -c option (check flag is nonzero). + +The number of measures in each voice may be different, (one +voice could end prematurely), but it is fairly easy to determine +during the first pass when the feature array is filled. The +number of measures in the output midi file can be much larger +since all repeats are expanded. A new variable, nbars, was +introduced in the voicecontext structure in store.c. + + +Mar 23 2019 + +abc2midi bug. abc2midi can be used for just checking the abc file for +errors using the -c option. No midi files are created. Unfortunately, +abc2midi running in this mode may halt when processing a big file +with the message, + +eputc: aborting because of file runaway (infinite loop) + +This is a check introduced in October 15 2004 in case abc2midi gets +into an infinite loop and produces a midi file of unbounded size. +The output midi file is prevented from growing over 500,000 bytes. +/* if ((back[trans[p]] != p) || (key[po] == 1)) { [SS] 2010-05-07 */ + if (back[trans[p]] != p ) { /* [SS] 2019-05-07 */ +/* if ((back[trans[p]] != p) || (key[po] == 1)) { [SS] 2010-05-07 */ + if (back[trans[p]] != p ) { /* [SS] 2019-05-07 */ +The check occurs in midifile.c by monitoring the variable, +Mf_numbyteswritten. +Since abc2midi with the -c option does not actually create any +midi files, it is not desirable to do this check. + +Analysis: the function finishfile() in store.c calls writetrack() +directly when it is run with the -c option; however when it +is run without this option, writetrack() is called from mfwrite() in +midifile.c. mfwrite() takes care of initializing Mf_numbyteswritten +for each tune. In order to initialize Mf_numbyteswritten when +abc2midi is run with the -c option, we need to link it to store.c +by declaring it as an extern. + +April 13 2019 + +midi2abc bug: midi2abc crashes with a message "out of memory cannot malloc" +on Windows 10. + +Analysis: in the function addstring checkmalloc allocates strlen(s)+1, +but strncpy can copy up to strlen(s)+2 characters. + +Fix: increased checkmalloc to allocate strlen(s)+2 characters. + + + +April 22 2019 + +midi2abc bug: midi2abc insists on making all rests invisible (x). Temporary +fix: printchord() was modified so that it always prints a visible rest (z). + + +May 08 2019 +midi2abc bug: accidentals fail to propagate resulting in + +X: 1 +T: from accid1.mid +M: 4/4 +L: 1/8 +Q:1/4=120 +K:G % 1 sharps +% note track +% accidentals +^C2 ^C2 ^C2 ^C2| + +Fix: in function printpitch(), removed (key[po] == 1) in +the conditional, +if ((back[trans[p]] != p) || (key[po] == 1)) +(I could not figure out the purpose of key[po].) +Introduced barback[] array which is used to reinitialize +the back[] array after each bar line. + + +May 12 2019 + +midiabc bug: -splitvoices and -splitbars is handled by the functions +printtrack_split_voice and printtrack_with_splits which are rather +complex and buggy. Preceding rests in the midi file corresponding +to the following file + +X:1 +T: anacrusis +M: 4/4 +L: 1/4 +K: G +Z2|z2AB|zdef| + +are handled correctly without the -splitbars -splitvoices options +but are missing with either options. The gap variable was not +set properly in the code. + +May 15 2019 + +midi2abc issue. By default abcm2ps chooses the clef (bass or treble) +automatically on the basis of the pitch of the following note. +For some tracks, the pitch range falls in both the +the treble and bass ranges resulting that the clef may oscillate +between treble and bass. If the clef is specified in the voice corresponding +to the track (or channel), then it is locked in. To avoid this +oscillation the pitch histogram is determined for each channel, +and a decision is made whether to lock in the clef. A new +function pitch_percentiles() was introduced in the code to +accomplish this action. + +May 29 2019 + +midi2abc issue: midi2abc makes a mess of type 0 midi files because +it does not separate the music in the different channels. +Fix: for type 0 midi files, the different channels are treated +as if they are put into separate tracks. New functions +txt_trackstart_type0, txt_noteon_type0, txt_program_type0, +addnote_type0, and addtext_type0 which copy the channel command to +to track[chn] instead of track[0]. + +June 06 2019 + +abc2abc bug: the fix to recognize the THICK_THIN bar line ]| +introduced a new problem. In the following example, + +X: 1 +T: bar line chord interference +M: 4/4 +L: 1/4 +Q:1/4=142 +K:F# % 6 sharps +z [gdGG,] z[gdGG,]|z [gdGG,] z [gdGG,]| +z [gdGG,] z[gdGG,]|z [gdGG,] z [gdGG,]| + +applying abc2abc to this file with the -e option returns + +X:1 +T:bar line chord interference +M:4/4 +L:1/4 +Q:1/4=142 +% Last note suggests minor mode tune +K:F# % 6 sharps +z [gdGG,] z[gdGG,|z [gdGG,] z [gdGG,| +z [gdGG,] z[gdGG,|z [gdGG,] z [gdGG,| + +The even numbered chords are not ended properly resulting +in nested chords. + +Fix: the code in parsemusic() in parseabc.c for handling +the closing of chords was corrected. +Parseabc.c is part of abc2midi, abc2abc, yaps, and +abcmatch. + + +June 13 2019 + +Major changes were made to midi2abc.c +The conditional code separated by #if defined SPLITCODE and #endif is now +permanently included in midi2abc. The conditionals have been removed. +The option -splitbars (which produces splitbars with & separators) +is now gone including the function printtrack_with_splits. The code +was unreliable and I cannot support it. Instead you should use -splitvoices +which was improved. +The function printtrack_split_voice() was separated into two +functions; the first with the same name and the second called +printtrack_split(). Printtrack_split_voice assigns splits +to each of the notes using the function label_split_voices(). +Label_split_voices returns nsplits, the number of splits that were needed, +and printtrack_split is called for each of the splits. +Printtrack_split creates a new voice for each of the splits. + +June 14 2019 + +Midi2abc: to prevent printing blank lines, newline_flag global variable was +introduced. + +June 17 2019: +Midi2abc: added initialization of chordhead and chordtail in +printtrack_split(). + +June 20 2019: +abc2midi crashes with the message +.20 March 30 2019 abc2midi +*** buffer overflow detected ***: abc2midi terminated +Aborted (core dumped) +for some abc files. + +Analysis: the crash occurs in sync_voice() in store.c when attempting +to print a message with more than 80 characters (case PLAY_ON_REP). +Fix: char message[128]; + + +June 26 2019 +abc2midi bug: trill - tie problem. The trill-tie combination +disrupts the chordal accompaniment in the following example. + +%abc-2.1 +X:6 +T:trill-tie problem +M:3/4 +L:1/4 +%%MIDI chordname m7b5 0 3 6 10 %0 _3 _5 _7 +I:MIDI=program 110 MIDI=chordprog 24 MIDI=bassprog 32 +K:A +"Am"A/^G/ B/A/ c/B/|d/c/ e/d/ f/e/|"Bm7b5"Te3-|"E"e3| +"Am"A/^G/ B/A/ c/B/|d/c/ e/d/ f/e/|"Bm7b5"e3-|"E"e3|| + +Unfortunately, there is no easy fix. In order to apply +the trill to the tied note, the tied note is converted +into a long note. This is an example where two features +clash with each other. + + +June 26 2019 +midi2abc -splitvoices: fixing more problems in +printtrack_split() function. Introducing firstgap[] +and function set_first_gaps(trackno). Test file: + +X:1 +T: polyphonic chords +M: 4/4 +L: 1/4 +K: C +zC-[C-E-][CEG]|\ +zC-[C-E-][CEG]|\ +[DF-A-][FA-]Az|\ +[DF-A-][FA-]Az| + +More information was added to file programming/midi2abc.txt. + + +June 29 2019 +midicopy requires that you specify the start and end times (or +start and end beats) even when you are copying the entire +midi file. + +midicopy returns the wrong number of seconds copied when -fromsec +and -endsec are specified and are beyond the range of the midi file. + +Fixes: functions cut_beginning() and cut_ending() check global +flags use_seconds and use_ticks. If neither are set then the +midi file is not trimmed. These flags are set in main() depending +on the options provided. + +We keep track of the current time (currentseconds) adjusting +for tempo changes. + + +July 05 2019 + +Midicopy aborts with the message "trackdata overflow" + +Analysis: the input midi file contained more than 20 tracks containing +no data. Each of those tracks contained 10 bytes. Midicopy while +adding extra bytes for compatibility with the winamp program, +caused the failure when the number of written bytes exceeded the +track_size. + +Fix: in the function append_to_string in midicopy.c, a margin of 6 +extra bytes was introduced in the check for overflow. Also midicopy +was modified to allow up to 64 tracks. A check is made to +ensure this is not exceeded. + + +July 12 2019 + +Midi2abc. The handling of lyric text is currently a problem with +midi2abc. For the present time I have added a new option -noly which +suppresses lyric output. Introduced a new flag noly in midi2abc.c. + +August 02 2019 +Midi2abc -stats returns incorrect count of notes in chord. +(This problem only affects midiexplorer.tcl.) +Analysis: chords are identified in stats_noteon by comparing the +Mf_currtime with the last_tick time. last_tick is also used to +compute the note length and is also updated in stats_noteoff. +Fix: introduced last_on_tick array which is only updated by +stats_noteon. + +August 11 2019 + +Abc2midi - valgrind detected a memory leak coming from store.c. +Analysis: event_refno in store.c creates a voice struct, but +it is destroyed without freeing up the the memory in startfile(). +Fix: it is not necessary to create the voice in event_refno, +since the function getvoicecontext(1) in event_key() will create +the voice the voice struct automatically if it does not exist. +The function clearvoicecontext() frees up all the voice structs +properly. + +Abc2midi - valgrind detected that the variable chord_num was +used in a conditional prior to being set in tiefix(). The +variable is now initialized. + +Both of these bugs were reported by James Cowgill to Debian +Bug Report log 890250 +(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=890250 ) + +yaps - valgrind detected that i was not set in the conditional + if ((n->beaming == endbeam)||(i==64)) { +in beamline() in drawtune.c when called from finalsizeline(). +https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=890250 +fix: initialized i to 0 in beamline(). + +midi2abc - Integer overflow leading to heap buffer overflow +in addstring(). +https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=924947 +Fix: limited the checkmalloc to 1024 sized string. + +October 13 2019 + +abc2midi: trill broken rhythm interference. Abc2midi returns the +following message when applied to this file. + +X: 1 +T: trill +M: 4/4 +L: 1/4 +K: C +A3A|Te>dc2| + +Warning in line-char 6-10 : Track 0 Bar 1 has 7/2 units instead of 4 + +In actual fact the broken rhythm is applied to the second A +and e instead of e and d. When the trill is removed, the program +runs normally. Fix: in event_note in store.c all call to marknote() +was added at the end of the conditional block beginning with + if ((decorators[ROLL]) || (decorators[ORNAMENT]) || (decorators[TRILL])) { +to ensure that the start and end of the broken rhythm sequence is +correct. + + +November 06 2019 November 13 2019 + +midi2abc: modified output for -midigram output. The header record +now returns miditype ntrks and ppqn. The program line returns +the current time in ticks. The changes were introduces to support +the function show_prog_structure in runabc.tcl. + +December 09 2019 + +abc2midi: some abc files use the $ character to indicate a linebreak +in the score. For example, +I:linebreak $ +The score contains numerous $ characters and abc2midi complains that +it does not recognize the character $. Fix, added the lines + +else if (fileprogram == ABC2MIDI && *p == '$') ; /* ignore [SS] 2019-12-9 */ + /* $ sometimes used as a score linebreak character */ + +in parsemusic() in parseabc.c + + +December 09 2019 + +abc2midi: new feature. Double quotes are supposed to be used to indicate +chord symbols (guitar chords) which abc2midi uses to create an +accompaniment. Unfortunately, the double quotes notation is frequently +misused to display other information that can cause a problem. +Added the option -NGUI to ignore any guitar chords in the body of +file. + + +December 22 2019 December 25 2019 + +midicopy: introduced new options for handling the percussion track. + + +December 30 2019 + +midi2abc: fix handling text messages (including %%MIDI and lyrics). + + +January 03 2020 + +abc2midi, abc2abc, yaps -- compatibility with abcm2ps. +The %%begintext and %%endtext enclose text which should not +be processed by abc2midi or abc2abc. The flag ignore_line is set +to 1 when parseline() encounters "%%begintext" and is reset to 0 +when %%endtext" is encountered. If ignore_line is 1, the rest of +the code in parseline() is ignored when abc2midi is running. + + +January 05 2020 + +midicopy: when copying a region in the middle of a midi file, +it may encounter and copy a midi noteoff message without a +corresponding midi noteon message. midi2abc complains when +it attempts to create an abc file. +Fix: the close_note() function in midicopy.c checks whether +the specified note is still playing. If it is not playing, +close_note() returns -1 and a noteoff channel message is +not issued by copy_noteoff(). In addition, it was necessary +to fix writechanmsg_at_0 called by winamp_compatibility_measure(). +To make a proper noteon message the velocity has to be nonzero. +The velocity of value 1 at pitch 0 should be nonaudible. + + +January 06 2020 + +midi2abc: chords such as [A3/2C3/2E3/2G3/2] are now expressed +more compactly as [ACEG]3/2. The patch was inserted in printchord() +in midiabc.c. + +January 14 2020 + +abc2midi: addressing ticket #25 on sourceforge. abc2midi hangs +on some systems for this example. + +X:1 +L:1/4 +K:C +2c/2fac'/c'/c'/c'/c'/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +Fix: add a test for zero denominator in genmidi.c +if (tnote_denom <= 0) { + event_error("note length denominator is zero or less"); /* [SS] 2020-01-14 to prevent infinite loop on some systems */ + exit(1); + } + +in function writetrack(). + +January 22 2020 + +abc2abc: added -useclef option, to specify the clef to use. It is +useful if you are trying to learn to read the bass clef and you are +transposing the music down an octave. + + +February 12 2020 + +abc2midi: minor changes suggested by Timm Reasbeck to the default gchord +patterns for various meters were incorporated in setbeat() in store.c. + + +March 25 2020 + +abc2midi: after the changes to parseabc.c on January 03 2020, abc2midi +no longer sees the %%MidiOn command. For example: + +X:1 +T:Tune with Repeat Text, MidiOff and MidiOn +M:4/4 +L:1/8 +K:C +C4 D4 | E4 F4 | \ +%%MidiOff +["Repeat" \ +%%MidiOn +G4 A4 | B4 c4 |] + +only the first 4 notes are recorded in the midi file. + + +Fix: in parseline() in parseabc.c, switched the order of the lines + + handle_abc2midi_parser (line); /* [SS] 2020-03-25 */ + + if (ignore_line == 1 && fileprogram == ABC2MIDI) return; + + +April 30 2020 + +abc2midi: reports warnings +Warning in line-char 6-0 : Ignoring reserved character S +Warning in line-char 6-3 : Ignoring reserved character P +Warning in line-char 6-7 : Ignoring reserved character O +when it encounters the characters S, P, and O in the music body. + +X:1 +T: decorations +M: 4/4 +L: 1/4 +K: G +SDBPAD|OBDEF| + +The abc standard defines S as segno, P as uppermordent, and O as +coda, so these are completely valid. + +Fix: add characters O,P and S to the decorations string in +parseabc.c. It is now +char decorations[] = ".MLRH~TuvOPS"; +In addition, DECSIZE in abc.h was increased to 13 and I added +#define CODA 10 +#define UPPERMORDENT 11 +#define SEGNO 12 + +May 06 2020 + +abc2midi: bug +The command clef=treble+8 or clef=treble-8 fails to have any +effect. This bug was probably introduced on December 19 2011 +and was just reported recently. +Analysis: the bug was traced to the code in the function +isclef() in parseabc.c. The code was modified on December 19 2011 +to fix another bug. The modification contains the line + + if (fileprogram == ABC2MIDI && *gotoctave != 1 && *octave != 1) + +which causes the problem. Prior to this test, the input string +was matched to 'treble' and *gotoctave was set to 1. The string +also matched 'treble+8', but *octave could not be reset to 1 +on account of the above modification. + +I see no purpose in the test *gotoctave != 1 or *octave != 1 +in the above test, so I changed it to simply to + + if (fileprogram == ABC2MIDI) + +wherever it occurred. This enabled the code for clef=treble+8 +and clef=treble-8. It was found that it was still possible to +switch back from clef=treble+8 to clef=treble. + +Unfortunately, the clef=treble+8, affects other designations +such as clef=tenor. It was therefore necessary to reset +*octave = 0. For all these situations and similar. + + +June 02 2020 + +Peter Sutton (petersutton2009@gmail.com) who packages abcmidi +for Arch Linux reported a linkage error +/usr/bin/ld: toabc.o:(.bss+0xd7c): multiple definition of ingrace'; parseabc.o:(.bss+0x788): first defined here /usr/bin/ld: drawtune.o:(.bss+0x168): multiple definition ofingrace'; parseabc.o:(.bss+0x788): first defined here + +My suspicion is that the changeover to gcc ver. 10 (2020-05-08) +is causing these problems + +Fix: in parseabc.c changed +int ingrace = 0; +to +static int ingrace = 0; /* [SS] 2020-06-02 */ + + +June 03 2020 + +gcc-10: Stuart D Gathman (stuart@gathman.org) detected numerous +potential problems in the C code. eg variables used for they are +initialized, variables declared and not used, missing defaults +in switch statements, indenting in if statements not matching +blocks, possible missing nulls in strings, ... +Suggested changes were inserted without changing the logic +of the code. Changes were marked with [SDG] 2020-06-03 in case +bugs are discovered later. + + +June 20 2020 + +In order to improve the handling of the SymbTr Turkish Makam +database https://compmusic.upf.edu/node/287 which was converted +to abc format in https://ifdo.ca/~seymour/runabc/makams/index.html , +the abc representation of the note pitches has been changed. +The collection of abc notated files will be replaced shortly +and will work with both abc2svg and abcm2ps thanks to the +help of Jef Moine and Hudson Lacerda. Hudson has contributed +patches to the abcmidi package which have been incorporated into +parseabc.c and store.c. + +June 22 2020 + +A minor change was made to midi2abc so that the pitchbend values +are presented in units of cents. + +June 23 2020 + +parseabc: renamed readlen_nocheck() to read_microtone_value(). +If the microtone value is an integer instead of a fraction, +(i.e. no / is present), then b (the denominator) is set to 0 +to signal that it is an integer. An integer microtone such +as ^n or _n, implies that its pitch shift is given by n +octave divisions where the number of divisions ndiv is specified +in the command. + +%%MIDI temperamentequal [octave_cents] [fifth_steps] [sharp_steps] + +For a detailed description of the temperamentequal command, +see the May 19 2015 insert in this document. The nonfraction +microtones will be used to represent the accidentals for the pitches +in the Turkish Makam database mentioned previously. + +June 25 2020 + +parseabc: parsekey now accepts integer microtones when %%MIDI temperamentequal +is set. The temperament flag is declared in parseabc.c and linked to +store.c with an extern statement, so that the parser knows whether %%MIDI temperamentequal statement +was included in the abc file. + +June 27 2020 + +abc2midi: in pitchof_b() in store.c (which implements various +temperaments), the Hudson Lacerda modified the pitchbends so +that the key of A is still 440.0. + /* [HL] 2020-06-27 Adjust for A=440.0 with zero pitchbend */ + pitch4096 += (9*SEMISIZE) - (3*fifth_size-octave_size); + + +July 03 2020 +abcmidi: %%temperament command has been implemented by Hudson +Lacerda (in store.c) +July 05 2020 +parseabc.c updated to reflect that the temperament integer flag +can take various values. + +You can find a test file detune.abc in the samples folder. + + + diff --git a/doc/abc2abc.1 b/doc/abc2abc.1 new file mode 100644 index 0000000..2d50110 --- /dev/null +++ b/doc/abc2abc.1 @@ -0,0 +1,123 @@ +.TH ABC2ABC 1 "07 June 2011" +.SH NAME +abc2abc \- a simple abc checker/re-formatter/transposer +.SH SYNOPSIS +\fBabc2abc\fP \fIfile\fP [ \fB-s\fP ] [ \fB-n\fP ] [ \fB-b\fP ] +[ \fB-r\fP ] [ \fB-e\fP ] [ \fB-t \fP\fIsemitones\fP ] [ \fB-nda\fP ] +[ \fB-u\fP ] [ \fB-d\fP ] [ \fB-v\fP ] [ \fB-V\fP\fIvoice number\fP] +[\fB-P\fP\fivoice number\fp] [\fB-nokeys\fP] +[ \fB-nokeyf\fP] [ \fB-usekey\fP\fI(sharps/flats)\fP] +[\fB-useclef\fP\fI(treble/clef)\fP] [ \fB-OCC\fP ] +.SH "DESCRIPTION" +.PP +.B abc2abc +is a simple abc checker/re-formatter/transposer. +It will check whether the \fIfile\fP given on the command line +obeys basic abc syntax. +.PP +If you want to check an abc tune, +it is recommended that you use +.B abc2midi +with the \fB-c\fP option. +This performs extra checks that +.B abc2abc +does not do. +.PP +The output of +.B abc2abc +goes to standard output. +Use redirection to save it to a file. +.SH OPTIONS +.TP +.B \-s +Rework spacing in the file (which affects how notes are beamed together +when the music is printed out). This option does not appear to be working +correctly. +.TP +.BI \-n " X" +Reformats the abc file with line breaks every \fIX\fP bars. +.TP +.B \-b +Don't do bar checking. +.TP +.B \-r +Don't do repeat checking. +.TP +.B \-e +Don't report errors. +.TP +.BI \-t " n" +Transpose tune by \fIn\fP semitones. This function will also +work with K: none or one of \-nokeys or \-nokeyf. +If a voice is assigned to channel 10 (drum channel) using a +%%MIDI channel 10 +command, then this voice is never transposed. + +.TP +.B \-nda +Convert double accidentals in guitar chord to another chord though +strictly not correct. +.TP +.B \-u +Update notation; the older notation \fB+ +\fP for chords is replaced by +\fB[]\fP and \fBs s\fP for slurs is replaced by \fB()\fP. +.TP +.B \-OCC +Accept the old notation for chord. Normally this is turned off, +since it conflicts with abc draft standard version 2.0 for +decorations (eg. +crescendo(+). +.TP +.B \-d +Re-notate the tune with all note lengths doubled. The unit length specified by the L: field +command is halved (e.g. L:1/8 to L:1/16). +.TP +.B \-v +Re-notate the tune with all note lengths halved. The unit length specified by the L: field +command is doubled (e.g. L:1/8 to L:1/4). +.TP +.B \-ver +Prints version number and exits. +.TP +.BI \-V " X[,Y...]" +For multivoiced abc files (i.e. contains V: field commands), only voices \fIX[,Y,...]\fP are copied. +.TP +.BI \-P " X,[,Y...]" +For multivoiced abc files (i.e. contains V: field commands), all voices except \fIX[,Y...]\fP remain the same. Voices X,Y... are modified according the other runtime parameters. +.TP +.BI \-X " n" +For a file containing many tunes, the X: reference numbers are renumbered sequentially +starting from number \fIn\fP. +.TP +.BI \-xref " n" +Only the tune with X: n is processed. +.TP +.B \-nokeys +No key signature will be assumed. Instead, sharps and naturals will +be placed wherever they are needed. +.TP +.B \-nokeyf +No key signature will be assumed. Instead, flats and naturals will +be placed wherever they are needed. +.TP +.B \-usekey " sf +This will force abc2abc to output the notes in the key signature +keys[sf] where sf specifies the number of flats (\-negative) or +sharps (+positive) in the key signature. It is a number between +\-5 and +5 inclusive. +.TP +.B \-useclef +This works with only the -t (transpose) and provided the abc +file does not already have a clef command in the K: field. It +does not support voices. +.PP +* Normally abc2abc will convert the deprecated notation for +decorations (eg. !ppp!) to the abc version 2.0 draft standard (eg. +ppp+). +If you do not wish to change to this standard include the \-OCC flag. + +.SH "SEE ALSO" +.IR abcmtex "(1), " abc2midi "(1), " midi2abc "(1), " mftext "(1)" +.SH AUTHOR +This manual page was written by Anselm Lingnau and is now supported by Seymour Shlien +for the GNU/Linux system. +.SH VERSION +This man page describes abc2abc version 2.04 from January 22 2020. diff --git a/doc/abc2midi.1 b/doc/abc2midi.1 new file mode 100644 index 0000000..f548895 --- /dev/null +++ b/doc/abc2midi.1 @@ -0,0 +1,568 @@ +.TH ABC2MIDI 1 "June 2017" +.SH NAME +\fBabc2midi\fP \- converts abc file to MIDI file(s) +.SH SYNOPSIS +abc2midi \fIinfile\fP [\fIrefnum\fP] [\-c] [\-v] [\-ver] [\-t] [\-n limit] [\-CS] [\-quiet] [\-silent] [\-Q tempo] [\-NFNP] [\-NFER] [\-NGRA] [\-NGUI] [\-STFW] [\-OCC] [\-NCOM] [\-HARP] [\-BF] [\-TT] [\-o outfile] \-CSM [filename] +.SH DESCRIPTION + The default action is to write a MIDI file for each abc tune + with the filename N.mid, where is the filestem + of the abc file and N is the tune reference number. If the \-o + option is used, only one file is written. This is the tune + specified by the reference number or, if no reference number + is given, the first tune in the file. +.SH OPTIONS +.TP +.B \fIrefnum\fP +process the tune with reference number \fIrefnum\fP +.TP +.B -c +selects checking only +.TP +.B -v n +selects verbose option where n is the level (optional) +.TP +.B -ver +prints version number and exits +.TP +.B -t +selects filenames derived from tune titles +.TP +.B -CS +use 2:1 instead of 3:1 for broken rhythms +.TP +.B -quiet +Suppresses some common warnings. +.TP +.B -silent +Suppresses other messages. +.TP +.B -n \fI X\fP +limits the length of the file name stem to X characters +.TP +.B -Q \fI tempo\fP +sets the default tempo in quarter notes per minute if it was not +specified in the abc header. +.TP +.B -NFNP +Ignore any dynamic indications !f! !ff! etc. +.TP +.B -NFER +Ignore any fermata indications (eg H or !fermata!). +.TP +.B -NGRA +Ignore any grace notes. +.TP +.B -NGUI +Ignore any guitar chords enclosed in double quotes. +.TP +.B -STFW +Place lyric text in separate MIDI tracks. +.TP +.B -NCOM +Suppress some comments in the output MIDI file. +.TP +.B -OCC +Accept old chord convention (eg +D2G2+ instead of [DG]2). +.TP +.B -BF +BarFly mode: invokes a stress model if possible. +.TP +.B -HARP +Roll ornaments=roll are generated for the harpist (same pitch) +.TP +.B -TT +Changes the tuning from A = 440 Hz. +.TP +.B -o \fIoutfile\fP +write output to \fIoutfile\fP +.TP +.B -CSM \fIinfile\fP +load a set of custom stress modes from a file +.SH FEATURES +.PP +* Broken rhythms (>, <), chords, n-tuples, slurring, ties, staccatto notes, +repeats, in-tune tempo/length/time signature changes are all supported. +.PP +* R:hornpipe or r:hornpipe is recognized and note timings are adjusted to +give a broken rhythm (ab is converted to a>b). +.PP +* Most errors in the abc input will generate a suitable error message in +the output and the converter keeps going. +.PP +* Comments and text fields in the abc source are converted to text events +in the MIDI output +.PP +* If guitar chords are present, they are used to generate an accompaniment +in the MIDI output. +.PP +* If there are mis-matched repeat signs in the abc, the program attempts to +fix them. However, it will not attempt this if a multi-part tune +description has been used or if multiple voices are in use. +.PP +* Karaoke MIDI files can be generated by using the w: field to include +lyrics. +.PP +* Nonnumeric voice id's, eg. V: soprano, as proposed for the new +abc standard is accepted. +.PP +* Invisible rests specified by x are treated the same way as +normal rests (z). +.PP +* Decorations may be indicated using either the deprecated +notation (eg. !fermata!) or the standard version 2.0 notation +(eg. +fermata+). +.PP +.SH LIMITATIONS +* No field is inherited from above the X: field of the tune. + + +.SH "ABC SYNTAX EXTENSIONS" +* There are some extensions to the abc syntax of the form +.PP +%%MIDI channel n +.PP +These control channel and program selection, transposing and various +other features of abc2midi. +.PP +Each of these should appear on a line by itself. All of them are allowed +within the abc tune body. By using these in combination with the part +notation, one can, for example, play a part transposed or in a different key. +.PP +The idea behind this syntax is that other programs will treat it as a +comment and ignore it. +.PP +%%MIDI channel n +.PP +selects melody channel n (in the range 1-16). +.PP +%%MIDI program [c] n +.PP +selects program n (in the range 0-127) on channel c. If c is not given, the +program is selected on the current melody channel. Most modern tone +generators follow the General MIDI standard which defines the instrument +type for each program number. +.PP +%%MIDI beat a b c n +.PP +controls the way note velocities are selected. The first note in a bar has +velocity a. Other "strong" notes have velocity b and all the rest have velocity +c. a, b and c must be in the range 0-127. The parameter n determines which +notes are "strong". If the time signature is x/y, then each note is given +a position number k = 0, 1, 2 .. x-1 within each bar. Note that the units for +n are not the unit note length. If k is a multiple of n, then the note is +"strong". The volume specifiers !ppp! to !fff! are equivalent to the +following : +.P +!ppp! = %%MIDI beat 30 20 10 1 +.br +!pp! = %%MIDI beat 45 35 20 1 +.br +!p! = %%MIDI beat 60 50 35 1 +.br +!mp! = %%MIDI beat 75 65 50 1 +.br +!mf! = %%MIDI beat 90 80 65 1 +.br +!f! = %%MIDI beat 105 95 80 1 +.br +!ff! = %%MIDI beat 120 110 95 1 +.br +!fff! = %%MIDI beat 127 125 110 1 + +.PP +%%MIDI beatmod n +.PP +Increments by n (or decrements if n is negative) the velocities a, b and +c described above. The instructions !crescendo(! and !crescendo)! +are equivalent to inserting a %%MIDI beatmod 15 wherever they +occur. (Alternatively you can use !<(! and !<)!.) Similarly the +instructions !diminuendo(! and !diminuendo)! are equivalent +to %%MIDI beatmod \-15. + +.PP +%%MIDI deltaloudness n +.PP +where n is a small positive number. By default the crescendo and +diminuendo instructions modify the beat variables a, b, and c by +15 velocity units. This instruction allows you to set this default +to value n. + +.PP +%%MIDI nobeataccents +.PP +For instruments such as church organ that have no greatly emphasized beat notes, +using this will force use of the 'b' velocity (see %%MIDI beat) +for every note irrespective of position in the bar. This allows dynamics +(ff, f, etc) to be used in the normal way. +.PP +%%MIDI beataccents +.PP +Revert to emphasizing notes the the usual way. (default) + +.PP +%%MIDI beatstring +.PP +This provides an alternative way of specifying where the strong and weak +stresses fall within a bar. 'f' means velocity a (normally strong), 'm' +means velocity b (medium velocity) and 'p' means velocity c (soft velocity). +For example, if the time signature is 7/8 with stresses on the first, fourth +and sixth notes in the bar, we could use the following +.PP +%%MIDI beatstring fppmpmp +.PP +%%MIDI transpose n +.PP +transposes the output by the specified number of semitones. n may be +positive or negative. +.PP +%%MIDI rtranspose n +.PP +Relative transpose by the specified number of semitones. i.e. +%%MIDI transpose a followed by %%MIDI rtranspose b results in a +transposition of a+b. %%MIDI transpose b will result in a transposition +of b semitones, regardless of any previous transposition. +.PP +%%MIDI c n +.PP +specifies the MIDI pitch which corresponds to c. The default is 60. This +number should normally be a multiple of 12. +.PP +%%MIDI grace a/b +.PP +sets the fraction of the next note that grace notes will take up. a +must be between 1 and b-1. The grace notes may not sound natural +in this approach, since the length of the individual grace notes +vary with the complexity of the grace and the length of the +following note. A different approach (which is now the default) +assumes that the grace notes always have a fixed duration. +To use the other approach you would specify, + +%%MIDI gracedivider b + +where b specifies how many parts to divide the unit length +specified by the L: field command. For example if b = 4 and +L: = 1/8, then every grace note would be 1/(8*4) or a 32nd +note. Time would be stolen from the note to which the grace +notes are applied. If that note is not long enough to handle +the grace then the grace notes would be assigned 0 duration. + + + +.PP +%%MIDI chordname name n1 n2 n3 n4 n5 n6 +.PP +Defines how to play a guitar chord called "name". n1 is usually 0 and +n2, n3 to n6 give the pitches of the other notes in semitones relative +to the root note. There may be fewer than 6 notes in the chord, but not +more.If "name" is already defined, this command re-defines it. Unlike +most other commands, chordname definitions stay in effect from where they +are defined to the end of the abc file. The following illustrates how +m, 7, m7 and maj7 could be set up if they were not already defined. +.PP +%%MIDI chordname m 0 3 7 +.br +%%MIDI chordname 7 0 4 7 10 +.br +%%MIDI chordname m7 0 3 7 10 +.br +%%MIDI chordname maj7 0 4 7 11 +.PP +%%MIDI gchord string +.PP +sets up how guitar chords are generated. The string is a sequence made of +of z's, c's f's and b's for rests, chords, fundamental and fundamental +plus chord notes respectively. This specifies how each bar is to be played. +An optional length is allowed to follow the z's, c's f's and b's e.g. czf2zf3. +If the abc contains guitar chords, then abc2midi automatically adds chords and +fundamentals after encountering the first guitar chord. It keeps using that +chord until a new chord is specified in the abc. Whenever the M: field is +encountered in the abc, an appropriate default string is set : +.P +For 2/4 or 4/4 time default is equivalent to : +%%MIDI gchord fzczfzcz +.P +For 3/4 time default is equivalent to : +%%MIDI gchord fzczcz +.P +For 6/8 time default is equivalent to : +%%MIDI gchord fzcfzc +.P +For 9/8 time default is equivalent to : +%%MIDI gchord fzcfzcfzc +.P + +The gchord command has been extended to allow you to play +the individual notes comprising the guitar chord. This allows +you to play broken chords or arpeggios. The new codes g,h,i,j, +G,H,I,J reference the individual notes starting from the +lowest note of the chord (not necessarily the root in the +case of inversions). For example for the C major chord, g +refers to C, h refers to E and i refers to G. For a gchord +command such as, +.P +%%MIDI gchord ghih +.P +Abc2midi will arpeggiate the C major guitar chord to +CEGE. The upper case letters G,H,I, and J refer to +the same notes except they are transposed down one +octave. Note for the first inversion of the C major +chord (indicated by "C/E"), E would be the lowest +note so g would reference the note E. +.P +Like other gchord codes, you may append a numeral indicating +the duration of the note. The same rules apply as before. +You can use any combination of the gchord codes, +(fcbghijGHIJz). + + +.PP +%%MIDI chordprog n +.PP +Sets the MIDI instrument for the chords to be n. If the command +includes the string octave=n where n is a number between \-2 and 2 +inclusive, then this will shift the pitch of the instrument by n +octaves. For example %%MIDI chordprog 10 octave=1.) + +.PP +%%MIDI bassprog n +.PP +Sets the MIDI instrument for the bass notes to be n. If the command +includes the string octave=n where n is a number between \-2 and 2 +inclusive, then this will shift the pitch of the instrument by n +octaves. For example %%MIDI bassprog 10 octave=\-1.) +.PP +%%MIDI chordvol n +.PP +Sets the volume (velocity) of the chord notes at n. +.PP +%%MIDI bassvol n +.PP +Sets the volume (velocity) of the bass notes at n. There is no corresponding +melodyvol command since there are 3 velocity values for melody, set using the +beat command. +.PP +%%MIDI gchordon +.PP +Turns on guitar chords (they are turned on by default at the start of a +tune). +.PP +%%MIDI gchordoff +.PP +Turns off guitar chords. +.PP +%%MIDI droneon +.PP +Turns on a continuous drone (used in bagpipe music) consisting +of two notes. By default the notes are A, and A,, played +on a bassoon at a velocity of 80. This can be configured +by the %%MIDI drone command described below. +.PP +%%MIDI droneoff +.PP +Turns off the continuous drone. +.PP +%%MIDI drone n1 n2 n3 n4 n5 +.PP +Sets the drone parameters where n1 is the MIDI program, n2 and +n3 specify the MIDI pitches of the two notes in the chord, and n4 +and n5 specify the MIDI velocities of the two notes. +If you do not set these parameters they are by default +70 45 33 80 80. A value of zero or less indicates that +the setting of this parameter should be left as it is. +.PP +%%MIDI drum string [drum programs] [drum velocities] +.PP +This sets up a drum pattern. The string determines when there is a drum beat +and the drum program values determine what each drum strike sounds like. +.PP +e.g. %%MIDI drum d2zdd 35 38 38 100 50 50 +.PP +The string may contain 'd' for a drum strike or 'z' for a rest. By default +a voice starts with no drum pattern and '%%MIDI drumon' is +needed to enable the drumming. The drum pattern is repeated during +each bar until '%%MIDI drumoff' is encountered. The %%MIDI drum +command may be used within a tune to change the drum pattern. +This command places the drum sounds on channel 10 and +assumes your tone generator complies with the General Midi standard - if +it does not, then you may hear tones instead of drum sounds. +.PP +In both the gchord and drum commands, the standard note length of +a single note f,c,z or d is not set by the L: command. Instead it +is adjusted so that the entire gchord string or drum string fits +exactly into one bar. In other words the duration of each note +is divided by the total duration of the string. This means that, +for example, the drum string "dd" is equivalent to drum string "d4d4". +You cannot currently specify fractions directly (eg. C3/2) +as done in the body of the music, but it is still possible to express +complex rhythms. For example, to indicate a rhythm such as +(3ddd d/d/d/d, you would write the string "d4d4d4d3d3d3d3". +.PP +%%MIDI drumbars n +.PP +The %%MIDI drum line can sound quite monotonous if it is repeated +each bar. To circumvent this problem a new MIDI command +%%MIDI drumbars n +where n is a small number will spread out the drum string over +n consecutive bars. By default drumbars is set to 1 maintaining +compatibility with existing abc files. You should take +care that the drumstring is evenly divisible between the +drumbar bars. Also the time signature should not change +between bars in a drumbar unit. (Sample abc file in doc/CHANGES +June 24 2008.) +.PP +%%MIDI gchordbars n +.PP +This command spreads the gchord string over n consecutive bars +just like drumbars (above). (A sample is found in doc/CHANGES +March 17 2009.) + + + + +.PP +With version 1.54 Dec 4 2004 of abc2midi, notes in chords +(eg. [FAc]) are not played in the same instant but offsetted +and shortened by 10 MIDI time units. Thus the first note +in the chord (eg. F) is played for the full indicated time, +the second note (eg. A) starts 10 MIDI units later and is shortened +by the same amount and the third note starts another 10 MIDI +units later and is shortened by another 10 units. This introduces +an "expressivo" option and avoids the heavy attack. (This +does not apply to gchords or multivoiced chords.) The amount +of the delay and shortening may be configured by the MIDI command + +.PP +%%MIDI chordattack n + +.PP +where n is a small number. If n is zero, then abc2midi should +behave as in earlier versions. The delay n is in MIDI time units +where there are 480 units in a quarter note beat. The program +may not run correctly if n is too large and there are short +chords. + +.PP +%%MIDI randomchordattack n +.PP +Like above except that the delay is a random variable uniformly +distributed between 0 and n-1. + +.PP +%%MIDI trim x/y +.PP +where x and y are two numbers. This command controls the articulation +of notes and chords by placing silent gaps between the notes. The length +of these gaps is determined by x/y and the unit length specified by the L: +command. These gaps are produced by shortening the notes by the same amount. +If the note is already shorter than the specified gap, then the gap +is set to half the length of the note. The fraction x/y indicates +a note duration in the same manner as specified in the abc file. +The actual duration is based on the unit length specified by the +L: field command. It is recommended that x/y be a fraction close +to zero. Note trimming is disabled inside slurs as specified by +parentheses. You can turn off all note trimming by setting x to 0, +eg 0/1. By default, note trimming is turned off at the beginning +of a tune or voice command. + +.PP +%%MIDI expand x/y +.PP +where x and y are two numbers defining a fraction less than 1. +This command controls the articulation of notes and chords in the +reverse manner. The notes are lengthened by this fraction so they +overlap the start of the next note. + + +.PP +%%MIDI drummap note midipitch +.PP +Please see abcguide.txt. +.PP +%%MIDI ptstress filename +.PP +This command loads file filename into abc2midi which contains +the Phil Taylor stress parameters and puts abc2midi in the mode +where it applies these stress parameters on every note. This +model runs in opposition to the standard beat model, so the +MIDI beat, beatstring, beatmod commands become ineffectual. +This also means that the dynamic indications !f! !pp! etc. +do not work any more. +.PP +There are two different implementations of the stress model. +Model 1 modifies the note articulation and takes +control of the MIDI trim parameters too. To revert back to +the standard model, put the command %%MIDI beataccents. +Model 2 modifies both the onset and ending of each note +allowing a musical beat to expand or contract in time. However, +the length of a musical measure should be preserved. Note +if you using model 2, which the current default, you must +include \-BF as one of the runtime parameters of abc2midi. +.PP +The model divides a bar into equal segments. For each segment, +a loudness or MIDI velocity is specified and a duration multiplier +is specified. If a note falls into a specific segment, it assumes +the velocity of that segment and its duration is modified +accordingly. If the note overlaps more than one segment, then +the note assumes the average of those segment values. +.PP +The input file specifies the number of segments and the loudness +and duration multipliers for each segment. The file has the +following format. The first value is the number of segments and each line +specifies the velocity and duration multiplier of the specific +segment. The velocity is limited to 127 and the duration is a +decimal number. The note durations is modified by varying the +gap between notes, so it is not possible to extend a note. This +preserves the regular tempo of the music. The program scales, +the note duration indications by dividing it by the maximum +value which here is 1.4. + +.PP +%%MIDI stressmodel n +.PP + +where n is either 1 or 2, selects the stress model implementation. + +.PP + other %%MIDI commands such as bendvelocity, bendstring, +controlstring have been introduced recently and are described +in the file abcguide.txt. + + + +.SH "COMPATIBILITY WITH DRAFT STANDARD 2.0" + +.PP +The proposed standard introduces a new copyright field +using the syntax + +.PP +%%abc-copyright (c) Copyright John Smith 2003 + +.PP +Abc2midi now inserts this in the MIDI file in the form of a +metatext copyright tag. Changes were made to the event_specific +function in store.c to process the copyright information. It +is also copied into the Karaoke track (if it is created) as +as @T field. + +.PP + + +.SH SEE ALSO +abc2ps(1), midi2abc(1), yaps(1). +.SH AUTHOR +James Allwright +.SH SUPPORTED + by Seymour Shlien +.SH VERSION +This man page describes abc2midi version 2.27 June 25 2006. +.SH COPYRIGHT +Copyright 1999 James Allwright +.PP +abc2midi is supplied "as is" without any warranty. It +is free software and can be used, copied, modified and +distributed without fee under the terms of the GNU General +Public License. +.PP +More complete documentation may be found in abcguide.txt +which comes with the abcMIDI distribution. diff --git a/doc/abcguide.txt b/doc/abcguide.txt new file mode 100644 index 0000000..d3c4971 --- /dev/null +++ b/doc/abcguide.txt @@ -0,0 +1,1693 @@ +Guide to writing abc for abc2midi +--------------------------------- +Updated June 1 2017. %%MIDI program ranges from 0 to 127 not 1 to 128. + +The defining document for abc is the abc version 1.6 specification which can +be found at http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt . This document +is a description of abc as interpreted by abc2midi. + +An abc tune consists of a header followed by a body. Each line in the +header is a different field starting with a letter immediately followed +by : and then the text of the field. The body of the tune contains lines +of music, though it may also contain certain fields. The end of the tune is +marked by a blank line (so blank lines cannot appear within the tune header +or body). + +Comments are allowed in both the header and the body. A comment starts +with a % sign and continues to the end of the line. A comment may be on +a line of its own or at the end of a line of abc. + +The header should look something like this : + +X:1 +T:The Rose Tree +M:4/4 +L:1/8 +Q:1/4=120 +K:G + +X: is the reference number (each tune in a file should have a unique reference +number). T: is the title of the tune, M: is the time signature, L: is the +unit note length and K: is the key signature. Q: is the tempo field. In +the above example the tempo is given as 120 quarter-notes per minute. X: +must be the first field and K: must be the last field in the header. + +It is advisable to write the fields M:, L: and Q: in that order. The +reason for this is that M: can set up a unit note length which L: +overrides and the tempo field Q: can be written in other forms that +depend on unit note length. This order makes the meaning clear and +unambiguous. The original abc specification gives a rule for computing +a default value for the unit note length from the M: field. abc2midi +only uses this rule for choosing a unit note length in the header if +the L: field has been omitted. + + +The tempo is usually indicated with the Q: field command, +eg. Q:1/4=180 which is interpreted as 180 quarter beats per minute. +In compliance with the abc standard 2.0, you may also +indicate the tempo using directives such as "lento", +"allegro", "vivace" etc. + +The following table based on +http://www.music.vt.edu/musicdictionary/appendix/tempo/tempo1.html +was used to translate the indications: + +Larghissimo 1/4=40 Moderato 1/4=104 +Adagissimo 1/4=44 Allegretto 1/4=112 +Lentissimo 1/4=48 Allegro 1/4=120 +Largo 1/4=56 Vivace 1/4=168 +Adagio 1/4=59 Vivo 1/4=180 +Lento 1/4=62 Presto 1/4=192 +Larghetto 1/4=66 Allegrissimo 1/4=208 +Adagietto 1/4=76 Vivacissimo 1/4=220 +Andante 1/4=88 Prestissimo 1/4=240 +Andantino 1/4=96 + +Note: case is ignored (eg. ALLEGRO Allegro or allegro are treated +the same). The directive must be enclosed in double quotes. + +Reference: http://abc.sourceforge.net/standard/abc2-draft.html#Q:%20-%20tempo + +Examples: + +X:1 +T:tempo +M:2/4 +L:1/4 +K:G +Q: "Adagio" +CD|EF| +Q: "Adagio" 1/4=40 +GA|Bc| + +(In the second tempo command, the 1/4=40 overrides the default +1/4=59.) + + + +The symbols M:C and M:C| give common time (4/4) and cut time (2/2) +The symbol M:none omits the meter entirely (free meter). +It is also possible to specify a complex meter, e.g. M:(2+3+2)/8, to make explicit which beats should be accented. The parentheses around the numerator are optional. + +Other fields may also appear in the header. Common ones are C: composer +of the tune, D: discography, H: history of the tune, S: source, N: notes, +Z: transcription note, A: area from which the tune comes, B: book +and R: rhythm. + + +Key Signature: + +The K: is made up of a base note A-G possibly followed by b for flat or +# for sharp. This specifies a major key. A minor key can be specified +by adding an m while Mixolydian and Dorian modes can be specified by adding +Mix and Dor respectively e.g. + +K:Eb +K:EDor +K:EbDor + +The following table relates the number of sharps or flats you see on the +stave to what is in the K: field : + +7 sharps: C# A#m G#Mix D#Dor +6 sharps: F# D#m C#Mix G#Dor +5 sharps: B G#m F#Mix C#Dor +4 sharps: E C#m BMix F#Dor +3 sharps: A F#m EMix BDor +2 sharps: D Bm AMix EDor HP Hp +1 sharp : G Em DMix ADor +0 sharps: C Am GMix DDor +1 flat : F Dm CMix GDor +2 flats : Bb Gm FMix CDor +3 flats : Eb Cm BbMix FDor +4 flats : Ab Fm EbMix BbDor +5 flats : Db Bbm AbMix EbDor +6 flats : Gb Ebm DbMix AbDor +7 flats : Cb Abm GbMix DbDor + +As an extension, abc2midi also recognizes "Maj" for Major "Min" for Minor, +"Phr" for Phrygian, "Lyd" for Lydian, "Aeo" for Aeolian and "Loc" for +Locrian. Thus CMaj, EPhr, FLyd, AAeo and BLoc will all generate a stave with +no sharps or flats. If you use one of these modes in the key signature, it is +recommended that you add a comment giving the number of sharps or flats for +the benefit of other people who may not be familiar with modes. e.g. + +K: DLoc % 3 flats + +The key signature may be followed by modifiers. A modifier consists of ^^, ^ +=, _ or __ followed by a-g. As an example, ^g means every a should be played +sharp unless otherwise marked in the music. This adds ^g to the existing +key signature. For example + +K: G ^c^g + +will produce a key signature similar to A major. Following the abc draft +2.0 standard, inserting the string exp in the key signature will cause +abc2midi to override the existing key signature. Thus + +K: A exp _b + +will remove the f,c and g sharps and put a b-flat instead. You may use +both upper and lower case letters as key modifiers since they are +distinguished by abcm2ps. + + +Another extension of the K: field is that it can include a clef specifier +an octave specifier and a transpose specifier e.g. + +K:G clef=soprano octave=-1 transpose=-1 + +The clef is recognized by typesetting programs such as yaps and abc2mps +and in some situations it will cause abc2midi to transpose the notes +up or down by an octave. Recognized clefs are treble, +bass, baritone, tenor, alto, mezzo and soprano. There are also variants +of these clefs; treble-8, tenor-8, treble+8 covering ranges which are an +octave below and an octave above the normal treble clef. Other +variants are not recognized at this time. No transposition is +assumed for the bass clef since many abc files enter the notes +with all the commas. + +The octave specifier is a convenience to make entering music easier. +It allows the user to avoid repeatedly entering commas or apostrophes +when entering a sequence of low or high notes. Both yaps and abc2midi +will transpose the notes by the specified number of octaves during +the parsing stage. + +e.g. the passage B,,, C,, D,, E,, F,, could be written more compactly as + + I:octave=-2 + B, C D E F + I:octave=0 + + +Some instruments such as the Bb clarinet automatically transpose the +written music. For example in the case of the clarinet, the music is +written in the key of C but the instrument plays it in the key of Bb. +For multivoiced tunes, the %%MIDI transpose indication is not that useful +since it transposes all the voices by the specified amount. The +transpose=n subcommand in the K: field tells abc2midi to transpose +a particular voice by n semitones without affecting how it appears in +the printed score. For example for the tune, + +X:1 +T:tranposing +M:1/8 +L:2/4 +K:C +V:1 +K:C transpose=-1 +CDEF|GABc| +V:2 +K:C +CDEF|GABc +V:1 +CDEF|GABc| +V:2 +CDEF|GABc + +Voice 1 will be played one semitone lower than indicated. +These transposition features are disabled for channel 10 which +is reserved for percussion instruments. + + +Voice indication: + +Many multivoiced abc files now use the V: indication to +specify additional information such as the clef, name of +the voice (to appear in the score). Furthermore, the +V: indication may occur in the header (i.e. before the +first K: indication), for the sole purpose of specifying +such information. Abc2midi, yaps and abc2abc now recognizes +the subfields octave=, clef= and transpose= in the V: +field and treats them in the same manner as if they occurred +in a K: field (as discussed above). Thus the V: field may +appear as +V: 1 clef=treble+8 +or +[V: 3 transpose=3] +The V: field is also recognized in both the body and header +of the abc file. Note that not all abc applications may recognize +these extensions, so you use them at the risk that they may not be +treated as expected in some cases. Also in the event that +there is a conflicting indication in either the voice or +key signature field, eg. [V: 1 clef=transpose+8 octave=-1] +the clef indication predominates. + +These transposition features are disabled for channel 10 +which is reserved for percussion instruments. + + + +The Body of the Tune +-------------------- + +Following the header is the tune. This is a textual notation for the things +you might see on a stave : + +Notes: + +A note consists of a pitch specifier followed by a length. Available pitch +specifiers are : + +C, D, E, F, G, A, B, C D E F G A B c d e f g a b c' d' e' f' g' a' b' + +This covers 4 octaves. abc2midi allows lower octaves to be reached by +adding extra , characters and higher octaves to be reached by adding +extra ' characters. However, this is not standard abc and may not be +supported by other abc utilities. + +You can raise or lower the pitch specifier a semitone by preceding it with +^ or _ respectively. The key signature and preceding sharps, flats and +barlines modify the default pitch in the same way as on a stave. Preceding +a note with = generates natural pitch and ^^ and __ can be used for double +sharp and double flat respectively. + +Microtones are indicated by following a ^ or _ with a fraction. +^/C is played as one quarter tone (i.e. half a semitone) above C. +_/C is played as one quarter tone (i.e. half a semitone) below C. +^^/4F is played as 1/4 of a semitone above F#. (The microtone always +follows any accidentals.) In general a microtone offset is indicated +by a fraction using the same convention as note length (described +below). Abcmidi uses the same microtone syntax as abcm2ps. +(See features.txt in the abcm2ps distribution.) + +Note that unlike accidentals, microtones do not propagate across a measure. +Microtones are implemented using the MIDI pitchwheel command. Since the +pitchwheel affects all notes played on a specific channel, a microtone +applied to any note in a chord specified by rectangular brackets, +(eg. [ACE]) will apply to all the notes in the chord. Microtone +accidentals override any sharpening or flattening induced by +key signatures. To illustrate + +K: G +^/F F ^^/2F F| + +does the following. Even though the key of G major causes F to be +sharp, the first note is F natural raised by half a semitone. +This effects the next note in making it F natural instead of F#. +The third note is F# raised by a half a semitone. The F# propagates +to the last note making it also F#. + +In accordance to the General MIDI recommendations the pitch range +of the pitchwheel is set to plus or minus two semitones. Therefore +abc2midi cannot go beyond this range. + +Microtones may be placed between tied notes, producing a pitch +bend effect. eg G- ^/G. + +Microtones have been introduced fairly recently into abcmidi (Mar 2005); +so far there is very little abc notated on the web which exploits +this feature. + + +The length is in general specified by a fraction following the pitch +specifier. However, the notation is made more concise by allowing much +of the fraction to be omitted. + +C - selects a note of 1 unit note length. +C2 - selects a note of 2 unit note lengths. +C/2 - selects a note of 1/2 unit note length. +C3/4 - selects a note of 3/4 unit note length. + +C/ is allowed as an abbreviation of C/2. +C// is allowed as an abbreviation of C/4. However, this is not standard +notation and is not allowed by all abc programs. + +No space is allowed within a note, but space may be used to separate +notes in the tune. + +Rests are written by using 'z' as the pitch specifier. + +z3 - a rest of 3 unit note lengths. + +Multiple bar rests can be created using 'Zn' where n is the number of +bars rest required. This is an extension to the standard syntax. + +Placing a dot before a note causes it to be played staccato. (.e) +Placing a M before a note indicates legato. (Me) +Placing a H before a note indicates a fermata. (He) +Placing a T before a note indicates that this note is trilled. (Te) +Placing a R before a note indicates that this note is rolled. (Re) + +Alternatively you may put !fermata! or !trill! before the +note. Other decorations have not been implemented in this manner. +The fermata may also be applied to a rest, (in order to handle +multivoiced files). + +Combining notes + +Three notes of the same length can be turned into a triplet by prefixing +them with (3. This has the effect of multiplying the note lengths by 2/3. +A chord can be represented by bracketting the notes together within [ and +] e.g. [a2e2]. An older notation which is also supported is to use + symbols +e.g. +a2e2+. The - symbol can be used to tie together notes of the same +pitch e.g. a2-a; this is equivalent to a3. + +From version 1.4 of abc2midi, the support of tuples and chords is +extended to include general tuple notation (p:q:r , [ and ] for chords +and a more flexible system of interpreting chords. + +(p:q:r means play the next r notes at q/p of their notated value. Thus +(3:2:3 is equivalent to an ordinary triplet (3 . + +It is possible in abc to write notes of different lengths within a chord +e.g. [ab2] . In this case, abc2midi takes the length of the first note +(or rest) in a chord is taken as the time before the next note is played. +However, if the music is to be typeset, this notation should be avoided +because the output will be ambiguous. Instead, the same effect can be +achieved using tied notes e.g. [ab2] c is equivalent to [ab-] [bc]. +A tie sign is always assumed to belong to the immediately previous note. + +A run of 2 or more different notes may be grouped together in a slur. +This usually means that the notes are to be played together as smoothly as +possible. In typeset music, a slur looks very similar to a tie, but in +abc, ( marks the start of a slur and ) marks the end. e.g. (ABc) . +abc2midi recognizes slurs, but they have no effect on the MIDI generated. + + + +Barlines and variant endings + +| is an ordinary barline +|| is a double barline +:| is "repeat last section". +|: is "repeat next section". +:: is "repeat last and next sections". +|1 or |[1 or | [1 is "first repeat ending". +:|2 or :|[2 or :| [2 is "second repeat ending". +|[1,3 is first and third ending +:|[2,4 is second and fourth ending +|] and [| are variants of ||. + +The notation :: is short for :| followed by |: . + +A tune with different ending for the first, second and third repeats has the +general form: + +|: common body of tune |1 first ending :|2 second ending :|3 third ending || + +You may also use this notation to indicate that the first ending is +played on the first and third repeat. For example + +|:common body of tune|1,3 first ending :|2 second ending :|4 forth ending| + +(The last variant ending should not end with a :|. In other words, +this will not work correctly. |: ... |[1,2 :|.) + +For multivoice abc files, you should be careful that the +different voices share the same repeat structure. When switching +voices (assuming they are interleaved) abc2midi does not cache +the repeat state. + + +Printed music commonly misses out a start repeat at the beginning of a tune. +abc2midi will try to fix up things if you miss out a start repeat in single +voice music. Where a tune starts with an anacrusis, abc2midi will always +fix a repeat to start at the anacrusis rather than the first barline. It is +recommended that you use matching start and end repeats rather than rely on +this behaviour. Missing start repeats are not supported in multiple voice +music. Also, abc2midi does not allow nested repeats. However, you can use +the more versatile part notation to achieve multiple repeats. + +It is not unusual to see music where a repeat does not coincide with the +end of a bar and the number of beats is not quite correct if the piece is +played exactly as written. A human player usually knows enough to correct +the mistake themselves, but abc2midi will play exactly what is written, so +care needs to be taken that this is corrected when the piece is transcribed +to abc. + + + +Rhythm field and Broken Rhythm Notation +--------------------------------------- + +R:hornpipe causes notes written in straight time to be played in dotted +time. The symbol > can be used to achieve a similar effect. For 4/4 +time this is applied to the 1/8 notes. For 2/4 time this is applied +to the 1/16 notes. + +a>b is notated as a3/2b/2 but played as a4/3b2/3. + +The symbols < >> << >>> <<< have similar meanings: + +a>b is notated and played as a7/4b/4. +a<>>b is notated and played as a15/8b/8. +a<< using the %%MIDI ratio command +described later. + +Beware that attempting "advanced" use of these symbols may mean your abc is +not portable between different abc programs. If the notes on either side of +the symbol are different lengths, this is reported as an error. If a and +b are not simple notes, or if there are other complications, then it is +safer to write the note lengths directly. + +Guitar chords : + +Anything in quotes is a guitar chord e.g. + +"A" "Gm" "B7" "Bm7" "D#aug" "Bbdim7" + +Guitar chords must use upper case A-G followed by optional # or b, then +the name of a chord type e.g. "m", "aug", "7". abc2midi currently +recognizes the following chord names : + + m, 7, m7, maj7, M7, 6, m6, aug, +, aug7, dim, dim7, 9, m9, maj9, M9, +11, dim9, sus, sus9, 7sus4, 7sus9, 5 + +You can also add your own; see the %%MIDI chordname command below. + +abc2midi automatically generates an accompaniment from the guitar chords. +There are a number of default chord/fundamental rhythms for common time +signatures which this uses, or you can set up your own. + +Lower case a-g followed by optional # or b will generate a single note, +the fundamental, only. + +The chord notation also allows chords such as "G/B" or "G/b". The +note following the / is interpreted in one of two ways: + +If the note following / does not exist as part of the given chord, it +is added to the chord below the root note of the chord (G in the above +example). + +If the note following / does exist in the chord, then the notes of the +chord are re-arranged so that it becomes the lowest pitch note of the +chord. This is known as an inversion of the chord. It does not matter +whether the note following the / is upper or lower case. They are +both treated the same. + +This notation has been extended so that finger numbers "1" "2" "3", +"4" or "5" are allowed. abc2midi ignores these, but a typesetting +program might support them. + +You may find some abc tunes that abuse this notation and use quotes +for things that are not guitar chords. Usually these are +tunes which have been typeset but never played by a computer. If you +don't want to just delete things in quotes, you can insert one of the +characters _, ^, @, < or > after the first quote e.g. "_Chorus" +"_Very Loud". This causes abc2midi to ignore the following text. However, +typesetting programs should recognize the first character as telling +them where to print the following text. + +Another extension is to allow musical instructions to appear in exclamation +marks e.g. !pizzicato! abc2midi currently supports the following : + !ppp! !pp! !p! !mp! !mf! !f! !ff! !fff! +Default volume is equivalent to !f!. In both the " " and ! ! fields, +abc2midi allows multiple terms separated by semi-colons e.g. "Am;1". + +The !breath! instruction causes the note to be played half length +followed by a rest of half its length (just like staccato). + +The !arpeggio! instruction affects the next chord and introduces +a larger delay between the onset of each note in the chord. (See +the text preceding %%MIDI chordattack in this file for more +explanations.) + +The !crescendo(! and !crescendo)! delineate the start and +end of a crescendo. Alternatively, you can use !<(! and !<)!. +Abc2midi does not implement a gradual loudness increase, +but instead increases the loudness at the start and end +of the crescendo by a fixed amount. (See %%MIDI beatmod +and %%MIDI deltaloudness for more information.) + +The !diminuendo(! and !diminuendo)! behave similarly but +reduce the loudness. These instructions have not been +implemented in yaps. + +!ped! and !ped-end! press and release the sustain pedal on +the piano. (The notes following !ped! and preceding !ped-end! are +held. This effect applies to all instruments besides the piano.) + +A line of music may contain any number of notes, barlines and guitar +chords. Spaces may be used to separate these. + +Some abc fields may appear within the body of the abc tune : + +K: - change key +L: - change unit note length +M: - change meter +Q: - change tempo +P: - part label +V: - voice label +w: - words to be matched syllable by syllable to notes + +Each field must be on a line by itself. + +Part Notation +------------- + +A part label must be a single character in the range A - Z. e.g. + +P:A + +A parts specifier in the header can be used to define the MIDI output as +some combination of the specified parts e.g. + +P:ABACABA + +You can use ( ) to repeat a part a specified number of times +e.g. P:A(AB)6 is equivalent to P:AABABABABABAB. If there are no brackets, +just the last part is repeated, so P:AAB3 is equicalent to P:AABBB. Dots +may be inserted into the part specifier to make it easier to read +e.g P:A.AB.AC + +If there is no parts specifier, the output is simply the parts (or just +the unlabelled music) in the order in which it appears in the tune body. + +You may if you wish have multiple voices sounding concurrently within each +part. These are indicated with V:N to indicate voice number N. + +e.g. + +V:1 + +V:2 + +and so on. + +A part label implicitly starts with V:1, as does the K: field which starts +the tune body, so you are not allowed to place a part label within a voice. +The duration of each of the voice parts must be the same for them to +synchronize correctly; abc2midi will warn you if they are not! From version +1.7 onwards, abc2midi allows any voice apart from voice 1 to be completely +omitted from a part. + +If no V: field appears after the first K:, whatever follows is assumed to +belong to voice 1 (the default voice). The V: field is an extension to +abc 1.5. + +The lines between one V:N field and the next V: field define a region +belonging to voice N. Within a part, you may have more than one such +region for each voice. The music for voice N within a part is all +the voice N regions taken in sequence. + +The M:, L: and K: fields in the header apply to all voices. After +the header, these fields apply only to the voice in which they appear. +In previous versions of abc2midi, an L:, for example, would affect +everything after it appeared up until the next L:, regardless of what +voice changes there were. + +The Q: tempo field should only appear in voice 1 and applies to all voices. + +The U: abbreviation field has limited use here. You can specify +an abbreviation such as +U: P = !trill! +and then in the body, eg. |DGAPF|, P will be replaced with !trill! +Only letters between H and Z can be used. Furthermore, you can +not redefine reserved letters such as H (fermata), L (unit length), +M (mordent) , R (roll) , T (trill). + + +Adding Lyrics to a Tune +----------------------- + +The W: field (upper case W) can be used for lyrics to be typeset separately +if the abc is printed out. The w: field (lower case w) in the body of a tune +supplies a line of lyrics to be matched syllable by syllable to the last line +of notes. These are usually printed below the notes if the abc is typeset. +abc2midi uses these to generate karaoke MIDI files. A karaoke MIDI file can +contain more than one set of lyrics in separate voices; an example is shown +at the end of this section. By default the lyrics are embedded in the same +MIDI track as the notes. If the runtime parameter -STFW is included, +then the lyrics will be placed in separate and adjoining MIDI tracks. +When the karaoke MIDI file is played using an appropriate player program, +the lyrics appear on the screen with the current syllable highlighted. +Within the lyrics, the following symbols may be used : + + break between words +- break between syllables within a word +| advance to next bar +_ indicates last syllable is to be held for another note +* indicates a one note rest for the singer. +~ appears as a space but connects syllables each side into one. +\- appears as - in the output +\ continuation character. Next w: field is part of the same line. + +A rest is not matched by any lyrics. +A tied note e.g. d2-d2 is treated as 2 notes (or however many parts it +is written as), despite the fact that it only plays as a single note. + +abc2midi ignores space characters if they occur either (a) between the +end of a word/syllable and a hyphen or underscore or (b) between a hyphen or +underscore and the beginning of a word/syllable. However, some software +incorrectly treats a hyphen as a separate word if there is a space between +it and the previous syllable, so, for example, you should write go-ing and +not go - ing to ensure that your abc is portable between programs. +Here are some examples taken from +http://abc.sourceforge.net/standard/abc2-draft.html + +w: syll-a-ble is aligned with three notes +w: syll-a--ble is aligned with four notes +w: syll-a -ble (equivalent to the previous line) +w: time__ is aligned with three notes +w: of~the~day is treated as one syllable (i.e. aligned with one note) + but appears as three separate words + + + +The following example illustrates most of these : + + gf|e2dc B2A2|B2G2 E2D2|.G2.G2 GABc|d4 B2 +w: Sa-ys my au-l' wan to your aul' wan\ +w: Will~ye come to the Wa-x-ies dar-gle? + +Note that the continuation character is used in a rather strange manner. +One w: field and all continuations will match one line of music, whether +or not the line of music ends with a continuation character. You can +think of the \ in a music line dividing that line into sections and \ +in a w: field further dividing these section into sub-sections. + +It is possible for a music line to be followed by several w: fields. +This can be used together with the part notation to create verses. +The first w: field is used the first time that part is played, then +the second and so on. If the tune uses repeats, these must be placed +at the end of a line of music in order to make sure that the start of +a w: field matches up with the repeat. + +Multivoiced lyrics example: + +X:1 +T:Multivoiced lyrics +M:2/4 +L:1/16 +K:C +V:1 +C4 C4 | E4 G4 | c8 |] +w: 1 2 3 4 5 +V:2 +C4 E4 | C4 B,4 | C8 |] +w: 11 12 13 14 15 + + +BarFly stress models +-------------------- + +If you include the run time parameter -BF in execution string, abc2midi +will attempt to apply the BarFly stress model on the tune if it +recognizes the rhythm designator (eg. R: jig) and if the time signature +also matches the associated meter. There are two different implementations +of the stress model which have different effects. (See %%MIDI ptstress +below for more details.) You can specify the implementation to use by +following the -BF flag with either the numeral 1 or 2. If you do not +specify a model, the program will use model 2. More details can +be found on http://ifdo.ca/~seymour/runabc/abcguide/abc2midi_guide.html + + +abc2midi-specific commands (%%MIDI) +------------------------------------ + +abc2midi supports a number of commands of the form + +%%MIDI command + +Each of these should appear on a line by itself; however there +is now provision to pass the MIDI command in an inline I: field +(see CHANGES file, March 25 2005 entry.) All of them are allowed +within the abc tune body. By using these in combination with the part +notation, one can, for example, play a part transposed or in a different key. + +The idea behind this syntax is that other programs will treat it as a +comment and ignore it. + +%%MIDI channel n + +selects melody channel n (in the range 1-16). + +%%MIDI program [c] n + +selects program n (in the range 0-127) on channel c. If c is not given, the +program is selected on the current melody channel. Most modern tone +generators follow the General MIDI standard which defines the instrument +type for each program number. These instrument types are listed at the end +of this document. Note that for multivoiced files, the program command +is placed in the track associated with the voice previously declared. +If the %%MIDI indications affect channels in other tracks, it is +recommended that they are placed in the first track or first declared voice. +See the note in the CHANGES file for the date January 1 2005. + + +%%MIDI beat a b c n + +controls the way note velocities are selected. The first note in a bar has +velocity a. Other "strong" notes have velocity b and all the rest have velocity +c. a, b and c must be in the range 0-127. The parameter n determines which +notes are "strong". If the time signature is x/y, then each note is given +a position number k = 0, 1, 2 .. x-1 within each bar. Note that the units for +n are not the unit note length. If k is a multiple of n, then the note is +"strong". The volume specifiers !ppp! to !fff! are equivalent to the +following : + +!ppp! = %%MIDI beat 30 20 10 1 +!pp! = %%MIDI beat 45 35 20 1 +!p! = %%MIDI beat 60 50 35 1 +!mp! = %%MIDI beat 75 65 50 1 +!mf! = %%MIDI beat 90 80 65 1 +!f! = %%MIDI beat 105 95 80 1 +!ff! = %%MIDI beat 120 110 95 1 +!fff! = %%MIDI beat 127 125 110 1 + +%%MIDI beatmod n +increments by n (or decrements if n is negative) the velocities a, b and +c described above. It is also used in implementing crescendo and +diminuendo (eg. !<(!, !crescendo(! etc.) + + +%%MIDI nobeataccents + +For instruments such as church organ that have no greatly emphasized beat +notes, +using this will force use of the 'b' velocity (see %%MIDI beat) +for every note irrespective of position in the bar. This allows dynamics +(ff, f, etc) to be used in the normal way. + +%%MIDI beataccents + +Revert to emphasizing notes the the usual way. (default) + + +%%MIDI deltaloudness n +where n is a small positive number. By default the crescendo and +dimuendo instructions modify the beat variables a, b, and c by +15 velocity units. This instruction allows you to change this default. + +%%MIDI beatstring + +This provides an alternative way of specifying where the strong and weak +stresses fall within a bar. 'f' means velocity a (normally strong), 'm' +means velocity b (medium velocity) and 'p' means velocity c (soft velocity). +For example, if the time signature is 7/8 with stresses on the first, fourth +and sixth notes in the bar, we could use the following + +%%MIDI beatstring fppmpmp + + +%%MIDI transpose n + +transposes the output by the specified number of semitones. n may be +positive or negative. + +%%MIDI rtranspose n + +Relative transpose by the specified number of semitones. i.e. +%%MIDI transpose a followed by %%MIDI rtranspose b results in a +transposition of a+b. %%MIDI transpose b will result in a transposition +of b semitones, regardless of any previous transposition. + +%%MIDI c n + +specifies the MIDI pitch which corresponds to c. The default is 60. This +number should normally be a multiple of 12. + +%%MIDI grace a/b + +sets the fraction of the next note that grace notes will take up. a +must be between 1 and b-1. The grace notes may not sound natural +in this approach, since the length of the individual grace notes +vary with the complexity of the grace and the length of the +following note. A different approach (which is now the default) +assumes that the grace notes always have fixed duration specified +by a fraction of the unit length. To use the other approach +you would specify, + +%%MIDI gracedivider b + +where b specifies how many parts to divide the unit length +specified by the L: field command. For example if b = 4 and +L: = 1/8, then every grace note would be 1/(8*4) or a 32nd +note. Time would be stolen from the note to which the grace +note is applied. If that note is not long enough to handle +the grace then the grace notes would be assigned 0 duration. + +%%MIDI chordname name n1 n2 n3 n4 n5 n6 + +Defines how to play a guitar chord called "name". n1 is usually 0 and +n2, n3 to n6 give the pitches of the other notes in semitones relative +to the root note. There may be fewer than 6 notes in the chord, but not +more.If "name" is already defined, this command re-defines it. Unlike +most other commands, chordname definitions stay in effect from where they +are defined to the end of the abc file. The following illustrates how +m, 7, m7 and maj7 could be set up if they were not already defined. +%%MIDI chordname m 0 3 7 +%%MIDI chordname 7 0 4 7 10 +%%MIDI chordname m7 0 3 7 10 +%%MIDI chordname maj7 0 4 7 11 + +%%MIDI gchord string + +sets up how guitar chords are generated. The string is a sequence made of +of z's, c's f's and b's for rests, chords, fundamental and fundamental +plus chord notes respectively. This specifies how each bar is to be played. +An optional length is allowed to follow the z's, c's, f's and b's e.g. czf2zf3. +If the abc contains guitar chords, then abc2midi automatically adds chords and +fundamentals after encountering the first guitar chord. It keeps using that +chord until a new chord is specified in the abc. Whenever the M: field is +encountered in the abc, an appropriate default string is set : + +For 2/4 or 4/4 time default is equivalent to : +%%MIDI gchord fzczfzcz + +For 3/4 time default is equivalent to : +%%MIDI gchord fzczcz + +For 6/8 time default is equivalent to : +%%MIDI gchord fzcfzc + +For 9/8 time default is equivalent to : +%%MIDI gchord fzcfzcfzc + +Please note, that the default gchord string is reissued any +time a time signature change is specified in the body of the music. +This means if one of the bars has an extra beat you included +a M: declaration before and after the measure, the gchord string +would be reset to the default string for that time signature +and not the one that you had declared. It is necessary for +you to send another %%MIDI gchord declaration after the +the time signature in order to set this back the way you want +it. This is one of the changes introduced into abc2midi so +that the accompaniment track always follows the meter of the +music for the regular time signatures. + +The gchord command has been extended to allow you to play +the individual notes comprising the guitar chord. This allows +you to play broken chords or arpeggios. The new codes g,h,i,j, +G,H,I,J reference the individual notes starting from the +lowest note of the chord (not necessarily the root in the +case of inverses). For example for the C major chord, g +refers to C, h refers to E and i refers to G. For a gchord +command such as, + +%%MIDI gchord ghih + +Abc2midi will arpeggiate the C major guitar chord to +CEGE. The upper case letters G,H,I, and J refer to +the same notes except they are transposed down one +octave. Note for the first inversion of the C major +chord (indicated by "C/E"), E would be the lowest +note so g would reference the note E. + +Like other gchord codes, you may append a numeral indicating +the duration of the note. The same rules apply as before. +You can use any combination of the gchord codes, +(fcbghijGHIJz). + +Another recent extension to gchords is the presence +of gchords in separate voices. Here is an example: + +X:1 +T: gchord multivoice extension +M: 4/4 +L: 1/4 +K: G +V: 1 +%%MIDI gchord ghih +"G" z4| z4|\ +%%MIDI gchordoff +z4| +V:2 +%%MIDI chordprog 12 +%%MIDI gchord GHIHG +z4|"D" z4|z4| + + + + +%%MIDI chordprog n + +Sets the MIDI instrument for the chord notes to be n. If the +command includes the string octave=n where n is a number between +-2 and +2, then the chord notes will be shifted n octaves from its +usual position, eg. (%%MIDI chordprog 32 octave=1). Any other +descriptors will be ignored, eg (%%MIDI chordprog 0 Acoustic Piano). + +%%MIDI bassprog n + +Sets the MIDI instrument for the bass notes to be n. If the +command includes the string octave=n where n is a number between +-2 and +2, then the bass note will be shifted n octaves from its +usual position. eg. (%%MIDI bassprog 32 octave=-1). + +%%MIDI chordvol n + +Sets the volume (velocity) of the chord notes at n. + +%%MIDI bassvol n + +Sets the volume (velocity) of the bass notes at n. There is no corresponding +melodyvol command since there are 3 velocity values for melody, set using the +beat command. + +%%MIDI gchordon + +Turns on guitar chords (they are turned on by default at the start of a +tune). + +%%MIDI gchordoff + +Turns off guitar chords. + +%%MIDI fermatafixed +Directs abc2midi to expand a fermata by one unit length. +Thus HC3 becomes C4. + +%%MIDI fermataproportional +This is the default. A fermata doubles the length of a +note so HC3 becomes C6. + +%%MIDI droneon + +This turns on a continuous drone used in bagpipe music. The +drone consists of two notes (by default A, and A,,) played +on a bassoon at a MIDI loudness (velocity) 80. If you +can configure the drone sound using the %%MIDI drone command +described below. + +%%MIDI droneoff + +This turns off the drone. + +%%MIDI drone n1 n2 n3 n4 n5 + +Configures the drone chord. n1 = MIDI program, +n2 = MIDI pitch 1, n2 = MIDI pitch 2, n4 = MIDI velocity 1, +and n5 = MIDI velocity 2. By default they have already +been set to 70 45 33 80 80. + + + +%%MIDI drum string [drum programs] [drum velocities] + +This sets up a drum pattern. The string determines when there is a drum beat +and the drum program values determine what each drum strike sounds like. + +e.g. %%MIDI drum d2zdd 35 38 38 100 50 50 + +The string may contain 'd' for a drum strike or 'z' for a rest. By default +a voice starts with no drum pattern. Like gchord, a command + +%%MIDI drumon + +is needed to enable the drumming. The drum pattern is repeated +during each bar until a + +%%MIDI drumoff + +is encountered. The %%MIDI drum command may be used within a tune +to change the drum pattern. This command places the drum sounds on +channel 10 and assumes your tone generator complies with the +General Midi standard - if it does not, then you may hear tones +instead of drum sounds. (Note the old method of using the +instruction !drum! and !nodrum! is being deprecated.) + +In both the gchord and drum commands, the standard note length of +a single note f,c,z or d is not set by the L: command. Instead it +is adjusted so that the entire gchord string or drum string fits +exactly into one bar. In other words the duration of each note +is divided by the total duration of the string. This means that, +for example, the drum string "dd" is equivalent to drum string "d4d4". +You cannot currently specify fractions directly (eg. C3/2) +as done in the body of the music, but it is still possible to express +complex rhythms. For example, to indicate a rhythm such as +(3ddd d/d/d/d, you would write the string "d4d4d4d3d3d3d3". + +For reference, the percussion instruments defined in the General MIDI +standard are given below. + +35 Acoustic Bass Drum 59 Ride Cymbal 2 +36 Bass Drum 1 60 Hi Bongo +37 Side Stick 61 Low Bongo +38 Acoustic Snare 62 Mute Hi Conga +39 Hand Clap 63 Open Hi Conga +40 Electric Snare 64 Low Conga +41 Low Floor Tom 65 High Timbale +42 Closed Hi Hat 66 Low Timbale +43 High Floor Tom 67 High Agogo +44 Pedal Hi-Hat 68 Low Agogo +45 Low Tom 69 Cabasa +46 Open Hi-Hat 70 Maracas +47 Low-Mid Tom 71 Short Whistle +48 Hi Mid Tom 72 Long Whistle +49 Crash Cymbal 1 73 Short Guiro +50 High Tom 74 Long Guiro +51 Ride Cymbal 1 75 Claves +52 Chinese Cymbal 76 Hi Wood Block +53 Ride Bell 77 Low Wood Block +54 Tambourine 78 Mute Cuica +55 Splash Cymbal 79 Open Cuica +56 Cowbell 80 Mute Triangle +57 Crash Cymbal 2 81 Open Triangle +58 Vibraslap + +Note you are able to change this mapping using the +the MIDI command %%MIDI drummap described below. + + +%%MIDI drummap note midipitch + +where the pitch of the note is notated using abc notation +and midipitch is a number between 35 and 81 inclusive referring +to the above table. This command is used if you +are notating a drum track, i.e. a voice played on +channel 10. Rather than being forced to use the note +corresponding to the desired percussion instrument, (for +example C (MIDI pitch 60) for hi bongo, you can use can +change the mapping to use a more convenient pitch. +for example to access bass drum 1 (MIDI pitch 36) you +would require the note C,, which is awkward to display +in common music notation. You can change the mapping to +say _D using +%%MIDI drummap _D 36. + +An example is provided in the file CHANGES (November 6 2005). + + +%%MIDI drumbars n + +The %%MIDI drum line can sound quite monotonous if it is repeated +each bar. To circumvent this problem a new MIDI command +%%MIDI drumbars n +where n is a small number will spread out the drum string over +n consecutive bars. By default drumbars is set to 1 maintaining +compatibility with existing abc files. You should take +care that the drumstring is evenly divisible between the +drumbar bars. Also the time signature should not change +between bars in a drumbar unit. (Sample abc file in CHANGES +June 24 2008.) + +%%MIDI gchordbars n + +This command spreads the gchord string over n consecutive bars +of equal length. The gchord string should be evenly divisible +by n or else the gchords will not work properly. A sample +abc file is found in CHANGES March 17 2009. + +%%MIDI control [bass/chord] n1 n2 + +This generates a MIDI control event. If the word "control" is followed by +"bass" or "chord", the event will be applied to the bass or chord channel, +otherwise it will be applied to the current channel. n1 and n2 are numbers +in the range 0-127. Generally, n1 selects a control parameter and n2 is +the value to which it is set. A couple of examples : + +%%MIDI control 7 50 + +will set the main volume of the channel to 50 + +%%MIDI control 10 0 + +will set the pan parameter (left/right balance) to 0. + +See the manual for your MIDI tone generator to find out what control events +are supported. + +%%MIDI portamento [bass/chord] n + +This will turn on the MIDI portamento controller and set the speed +of sliding between pitches to n. Like %%MIDI control, if the word +portamento is followed by "bass" or "chord", the event will be +applied to the bass or chord channel, otherwise it will be +applied to the current channel. The parameter n should be between +0 and 63. Large values imply a slow transition between pitches. +I have found the resulting effect to be rather weird, especially +for large pitch intervals. + +%%MIDI noportamento [bass/chord] + +This will turn off the portamento controller (current default). + +%%MIDI pitchbend [bass/chord] + +This generates a pitchbend event on the current channel, or on the bass +or chord channel as specified. The value given by the following two bytes +indicates the pitch change. + +%%MIDI nobarlines + +This is a somewhat obscure option to support early music without barlines. +Normally, an accidental applied to one note e.g. ^c will apply to every note +at the same point in the scale until the end of the bar (so C,, C, C c c' +would all be sharpened). This option turns off this behaviour, so that an +accidental applies only to the next note. It should be used in the header of +any tune requiring this behaviour. + +%%MIDI barlines + +This turns off the effect of %%MIDI nobarlines in the middle of a tune. This +is the default behaviour assumed at the start of every tune. + +%%MIDI ratio n m + +This sets the ratio of note lengths in broken rhythm (e.g. a>b). +The default behaviour is for note a to sound for twice as long as note b. +This can be achieved with + +%%MIDI ratio 2 1 + +and hornpipes are commonly played with approximately this ratio. However, +for other musical styles, a different ratio may be appropriate. If you +are using abc2midi to export music to another program for printing, then +you may wish to use a ratio of 3:1 which is how hornpipes are usually +notated. This can be achieved with + +%%MIDI ratio 3 1 + + +Arpegiation: + +With version 1.54 Dec 4 2004 of abc2midi, notes in chords +(eg. [FAc]) are not played in the same instant but offsetted +and shortened by 10 MIDI time units. Thus the first note +in the chord (eg. F) is played for the full indicated time, +the second note (eg. A) starts 10 MIDI units later and is shortened +by the same amount and the third note starts another 10 MIDI +units later and is shortened by another 10 units. This introduces +an "expressivo" option and avoids the heavy attack. (This +does not apply to gchords or multivoiced chords.) The amount +of the delay and shortening may be configured by the MIDI command + +%%MIDI chordattack n + +where n is a small number. If n is zero, then abc2midi should +behave as in earlier versions. The delay n is in MIDI time units +where there are 480 units in a quarter note beat. The program +may not run correctly if n is too large and there are short +chords. + +%%MIDI randomchordattack n + +where n is a small number. This is similar to above, except the +delay of each note in the chord varies randomly between 0 and n-1. +Therefore each chord is played differently. + + +Articulation: + +%%MIDI trim x/y + +where x and y are two numbers. This command controls the articulation +of notes and chords by placing silent gaps between the notes. The length +of these gaps is determined by x/y and the unit length specified by the L: +command. These gaps are produced by shortening the notes by the same amount. +If the note is already shorter than the specified gap, then the gap +is set to half the length of the note. The fraction x/y indicates +a note duration in the same manner as specified in the abc file. +The actual duration is based on the unit length specified by the +L: field command. It is recommended that x/y be a fraction close +to zero. The denominator, y does not need to be a power of 2. +Trimming is disabled inside slurs as indicated by parentheses. + +You can turn off all note trimming by setting x to 0, +eg 0/1. By default, note trimming is turned off at the beginning +of a tune or voice command. + + + + +To avoid the problem of breaking up a music line +in order to place a %%MIDI command, for example, +A2 B2|\ +%%MIDI drumon +C2 D2| +you can place the MIDI instruction inside an info field +using the following syntax. + +A2 B2|[I:MIDI= drumon] C2 D2| + +The '=' following the MIDI is very important. The info field +syntax allows you to place several MIDI commands in one inline +block, for example +[I: MIDI = program 73 MIDI=chordprog 29] +(Spaces are optional.) +Other examples can be seen in the file CHANGES in the +following the March 25 2005 entry. + +Another recent extension is the allowance of drum patterns +in separate voices. Here is an example: + +X:1 +T: drum multivoice extension +M: 4/4 +L: 1/4 +K: G +V:1 +%%MIDI drum dddd 45 45 45 45 70 50 60 50 +%%MIDI drumon +z4|z4|\ +%%MIDI drumoff +z4| +V:2 +%%MIDI drum ddddd 54 54 54 54 54 70 50 50 60 50 +z4|\ +%%MIDI drumon +z4|z4| + + + + +%%MIDI temperamentlinear octave_cents fifth_cents + +This command allows you to change the temperament of the +scale. Octave_cents specifies the size of an octave +in cents of a semitone or 1/1200 of an octave. Fifth_cents +specifies in the size of a fifth (normally 700 cents). +For example: +%%MIDI temperament 1200.5 698.0 +will produce a slightly stretched scale with narrowed fifths. + +More details on linear tempered scales can be found +on the site +http://www.xs4all.nl/~huygensf/scala/ +The pitch of each note is modified using a MIDI pitchbend +command to comply with the scale. In order to handle chords, +each note of the chord must be played on a different MIDI +channel. + +The normal musical scale has a temperament of +%%MIDI temperamentlinear 1200 700 + +but to avoid unnecessary pitchbends you should restore +to the normal temperament using the command +%%MIDI termperamentnormal + + +%%MIDI tuninsystem comma53 +quantizes the pitches of the notes using the comma53 system where +an octave is divided into 53 equally spaced tones. + + +%%MIDI makechordchannels n + +If you are not modifying the temperament or inserting +microtones you can ignore this command. Normally +in voice chords containing microtones e.g. [_/CE_/G] +will not be handled correctly because all the notes in the +chord are played on the same MIDI channel. If you include +the above command where n here is 2, then two separate channels +will be allocated for playing the other two notes in this chord. +These separate channels will be used whether the pitches +of the notes are bent or not. Once you allocate those channels +with this command, they are no longer available and since +there are only 16 MIDI channels you can easily run out. +Furthermore, you need to allocate chordchannels for any +other voices which may have in voice chords. The channel +allocation process will automatically propagate the program +assignment (musical instrument) to the other chordchannels, +so be sure you set the program before using this command. +If you need to change the program assignments, you can +find out the channel numbers that were assigned by running +abc2midi in verbose mode using the -v command in the +execution string. + + +%%MIDI ptstress filename + +This command loads file filename into abc2midi which contains +the Phil Taylor stress parameters and puts abc2midi in the mode +where it applies these stress parameters on every note. This +model runs in opposition to the standard beat model, so the +MIDI beat, beatstring, beatmod commands become ineffectual. +This also means that the dynamic indications !f! !pp! etc. +do not work any more. + +There are two different implementations of the stress model. +Model 1 modifies the note articulation and takes +control of the MIDI trim parameters too. To revert back to +the standard model, put the command %%MIDI beataccents. +Model 2 modifies both the onset and ending of each note +allowing a musical beat to expand or contract in time. However, +the length of a musical measure should be preserved. Note +if you using model 2, which the current default, you must +include -BF as one of the runtime parameters of abc2midi. + +The model divides a bar into equal segments. For each segment, +a loudness or MIDI velocity is specified and a duration multiplier +is specified. If a note falls into a specific segment, it assumes +the velocity of that segment and its duration is modified +accordingly. If the note overlaps more than one segment, then +the note assumes the average of those segment values. + +The input file specifies the number of segments and the loudness +and duration multipliers for each segment. The file has the +following format: + +8 +110 1.4 +90 0.6 +110 1.4 +90 0.6 +110 1.4 +90 0.6 +110 1.4 +90 0.6 + +where the first value is the number of segments and each line +specifies the velocity and duration multiplier of the specific +segment. The velocity is limited to 127 and the duration is a +decimal number. The note durations is modified by varying the +gap between notes, so it is not possible to extend a note. This +preserves the regular tempo of the music. The program scales, +the note duration indications by dividing it by the maximum +value which here is 1.4. + + +%%MIDI stressmodel n + +where n is either 1 or 2, selects the stress model implementation. + + +%%MIDI expand m/n + +This command,causes all the following notes be lengthened by +the amount factor m/n so that they overlap the next note. +Thus the next note is started at the proper time, but the +previous note ends after the beggining of the note. +This overlap causes a nice effect for particular MIDI instruments +such as choir voices. The %%MIDI expand function behaves in +the opposite manner as the %%MIDI trim function. + + +%%MIDI snt k pitch + +Since many MIDI devices do not support this function, use of +this command is not recommended. The command changes the tuning +of a single note using the "universal system exclusive messages". +k is the MIDI pitch being retuned (a number between 0 to 127) +and pitch is a floating point number representing the pitch's new +value in MIDI pitch units. + + +%%MIDI bendvelocity n1 n2 + +This command defines how to bend the a particular note following +the !bend! decoration. The pitch of the note shifts up or down +as the note is playing. n1 is the velocity of the pitch change +and n2 is the acceleration (how fast the velocity changes). +The bend is accomplished by modifying the MIDI pitchwheel where +the 8192 is the neutral. Minimum and maximum values +are 0 and 16383 correspond to two semitones shifts in either +directions. The velocity and acceleration may be positive or +negative. + + +%%MIDI bendstring n1 n2 n3 n4 etc + +This command is a more general way for defining how a note +is bent. It can also apply with !shape! decoration +discussed later. The note is split into n equal segments corresponding +to each of the n1, n2, etc values. The n1, n2, ... values are the +increments (or decrements if they are negative) which are added +to the pitchwheel value. Thus +%%MIDI bendstring 1000 1000 -500 -500 +will split a note into 4 parts and the pitchwheel values in +each part will be 9192, 10192, 9692, and 9192. + + + +%%MIDI controlstring m n1 n2 n3 ... + +This command defines how the m th MIDI controller changes for the +note following the !shape! decoration. The note is divided +into n segments where n is the number of values following +the m or controller number. n1, n2, n3, ... are the values for +controller m in each segment. This allows you to shape the sound +of the note. For example, by changing the modwheel or the expression. +All the values m, n1, n2 are numbers between 0 and 127. + + + + + + +Global settings for abc2midi +---------------------------- + +If you are creating an abc file with many tunes, abc2ps and abcm2ps +allows you to declare certain settings that apply to all tunes +by placing them at the beginning of the file prior to the +start of the tune. Abc2midi provides this feature but presently +only to a limited extent. The following MIDI commands will +change the defaults for all tunes if they are placed outside +of any tune. + +%%MIDI C ... +%%MIDI nobarlines ... +%%MIDI barlines ... +%%MIDI fermatafixed +%%MIDI fermataproportional +%%MIDI ratio ... +%%MIDI chordname ... +%%MIDI deltaloudness ... + +All other MIDI commands placed outside of a tune will be +ineffective and return a warning message + +"cannot handle this MIDI directive here" + +(For more details see CHANGES, May 06 2005 entry.) + +Any of these defaults can be changed as many times as you like +provided that they are occur outside a tune which is usually +delineated by a X: reference number and a blank line. + +Voice Splitting +--------------- + +Abcm2ps allows a voice to separate into two or more voices +in a specific bar using the symbol '&'. This feature +now works in abc2midi. Abc2midi places the split voice +into a separate MIDI track with intervening rests. +When a voice splits, the new voice inherits the program +number (musical instrument) from the parent voice. + + +Compatibility with proposed abc standard version 2.0 +---------------------------------------------------- + +The proposed standard introduces a new copyright field +using the syntax + +%%abc-copyright (c) Copyright John Smith 2003 + +Abc2midi now inserts this in the MIDI file in the form of a +metatext copyright tag. Changes were made to the event_specific +function in store.c to process the copyright information. It +is also copied into the Karaoke track (if it is created) as +as @T field. + + + + +Typesetting abc +--------------- +If you want to typeset your abc, there are some more features of abc syntax +that you need to know: + +If 2 notes appear consecutively with no space between them, they will be +grouped together under the same beam. A space between them prevents them +sharing a beam. + +A new line of stave music is generated by the newline at the end of a +line of abc music. To suppress this, put a \ character at the end of the +abc music line. + +An abc music line should end either at a bar line or at the space +between two notes which indicates they do not share a beam. This is true +whether or not the abc line ends with a \ character. + +Error Messages and Warnings +--------------------------- + +abc2midi attempts to perform various checks on the abc and +reports any problems via error and warning messages: + +A warning message indicates there is something strange in the abc - +possibly an error or possibly non-standard usage. + +An error message means that abc2midi thinks there is definitely an +error in the abc and the MIDI generated may not be correct. + +In a small number of cases, an error may cause abc2midi to stop. +This is usually either because it has run out of memory or because +there is some problem with reading or writing a file. + + + +Bar counting and checking +------------------------- + +Conventionally bars are numbered starting from one. If the first +bar is incomplete (anacrusis), then it is counted as zero. +Abc2ps and abcm2ps follows this convention but abcMIDI does not. +All bars are counted starting from zero and furthermore if there +is an incomplete bar just before a repeat (:| |: or ::), the +bar count is not incremented. It is difficult to change this +convention since abcMIDI assigns a number to the bar ahead +when it sees a bar line. It would be necessary to introduce +some look ahead for the first bar in the tune. + +If abc2midi reports a problem in a specific bar, you can use +yaps with the -k option (for print bar numbers) to locate this +bar. If you use another program such as abc2ps, then the bar +number in the displayed or printed version may be one unit +higher. + +The most common error seems to be a missing beat or having +an extra beat in a bar. In the vicinity of a repeat, abc2midi +tries to complete the first bar using the incomplete bar at +the end of the repeat. If the first bar can be completed, then +no warning is reported. The first bar may be complete the first +time the section is played but incomplete in the second repeat. +Complications occur when the left repeat symbol (|:) is +missing and abc2midi has to assume it is at the beginning. +More complications occur when there is a key change after +the repeat or the music is split into parts A,B,C, etc. +Yaps does the bar checking differently when it encounters +repeats so that it may not resolve as many incomplete bars +and report more warnings. + +The bar checking is present for providing warnings. For some +music, an extra beat may be intentional and it is not +marked by a meter change. If you are only printing the +music, there is probably no problem; however, if you are +producing a MIDI file and there is guitar (gchord) accompaniment +then a break or missing beat might be noticeable. + + + +General MIDI Program Number/Instrument Name +------------------------------------------- + + 0. Acoustic Grand Piano + 1. Bright Acoustic Piano + 2. Electric Grand Piano + 3. Honky-tonk Piano + 4. Electric Piano 1 + 5. Electric Piano 2 + 6. Harpsichord + 7. Clavi + 8. Celesta + 9. Glockenspiel + 10. Music Box + 11. Vibraphone + 12. Marimba + 13. Xylophone + 14. Tubular Bells + 15. Dulcimer + 16. Drawbar Organ + 17. Percussive Organ + 18. Rock Organ + 19. Church Organ + 20. Reed Organ + 21. Accordion + 22. Harmonica + 23. Tango Accordion + 24. Acoustic Guitar (nylon) + 25. Acoustic Guitar (steel) + 26. Electric Guitar (jazz) + 27. Electric Guitar (clean) + 28. Electric Guitar (muted) + 29. Overdriven Guitar + 30. Distortion Guitar + 31. Guitar harmonics + 32. Acoustic Bass + 33. Electric Bass (finger) + 34. Electric Bass (pick) + 35. Fretless Bass + 36. Slap Bass 1 + 37. Slap Bass 2 + 38. Synth Bass 1 + 39. Synth Bass 2 + 40. Violin + 41. Viola + 42. Cello + 43. Contrabass + 44. Tremolo Strings + 45. Pizzicato Strings + 46. Orchestral Harp + 47. Timpani + 48. String Ensemble 1 + 49. String Ensemble 2 + 50. SynthStrings 1 + 51. SynthStrings 2 + 52. Choir Aahs + 53. Voice Oohs + 54. Synth Voice + 55. Orchestra Hit + 56. Trumpet + 57. Trombone + 58. Tuba + 59. Muted Trumpet + 60. French Horn + 61. Brass Section + 62. SynthBrass 1 + 63. SynthBrass 2 + 64. Soprano Sax + 65. Alto Sax + 66. Tenor Sax + 67. Baritone Sax + 68. Oboe + 69. English Horn + 70. Bassoon + 71. Clarinet + 72. Piccolo + 73. Flute + 74. Recorder + 75. Pan Flute + 76. Blown Bottle + 77. Shakuhachi + 78. Whistle + 79. Ocarina + 80. Lead 1 (square) + 81. Lead 2 (sawtooth) + 82. Lead 3 (calliope) + 83. Lead 4 (chiff) + 84. Lead 5 (charang) + 85. Lead 6 (voice) + 86. Lead 7 (fifths) + 87. Lead 8 (bass + lead) + 88. Pad 1 (new age) + 89. Pad 2 (warm) + 90. Pad 3 (polysynth) + 91. Pad 4 (choir) + 92. Pad 5 (bowed) + 93. Pad 6 (metallic) + 94. Pad 7 (halo) + 95. Pad 8 (sweep) + 96. FX 1 (rain) + 97. FX 2 (soundtrack) + 98. FX 3 (crystal) + 99. FX 4 (atmosphere) + 100. FX 5 (brightness) + 101. FX 6 (goblins) + 102. FX 7 (echoes) + 103. FX 8 (sci-fi) + 104. Sitar + 105. Banjo + 106. Shamisen + 107. Koto + 108. Kalimba + 109. Bag pipe + 110. Fiddle + 111. Shanai + 112. Tinkle Bell + 113. Agogo + 114. Steel Drums + 115. Woodblock + 116. Taiko Drum + 117. Melodic Tom + 118. Synth Drum + 119. Reverse Cymbal + 120. Guitar Fret Noise + 121. Breath Noise + 122. Seashore + 123. Bird Tweet + 124. Telephone Ring + 125. Helicopter + 126. Applause + 127. Gunshot + +--------------------------------------------------------------------- +This reference written 1995-1998 by James Allwright diff --git a/doc/abcmatch.1 b/doc/abcmatch.1 new file mode 100644 index 0000000..ebff780 --- /dev/null +++ b/doc/abcmatch.1 @@ -0,0 +1,120 @@ +.TH ABCMATCH 1 +.SH NAME +abcmatch \- Search for specific sequences of notes in an abc file composed of many tunes. +.SH SYNOPSIS +\fBabcmatch\fP \fiabc\ file\fP [\fB-c\fP] [\fB-v\fP] [\fB-r\fP] [\fB-con\fP]\ + [\fB-fixed nn\fP] [\fB-qnt\fP] [\fB-lev\fP] [\fB-a\fP] [\fB-ign\fP]\ + [\fB-br %d\fP] [\fB-tp abc reference file\fP] [\fB-ver\fP]\ + [\fB-pitch_hist\fP] [\fB-wpitch_hist\fP] [\fB-length_hist\fP]\ + [\fB-interval_hist\fP] [\fB-pitch_table\fP] [\fB-interval_table\fP]\ + \fireference\ number\fP +.SH "DESCRIPTION" +.PP +.B abcmatch +is used to search for specific sequences of notes in an abc file +composed of many tunes. For example, if you know a few bars of a tune, +you can use this program to find the tune having this sequence and perhaps +identify the tune. +At a minimum, abcmatch requires two files. A template file called +match.abc which contains the bars that you are searching for and a large +file consisting of a hundred or more abc tunes. The program automatically +loads up the match.abc file and then scans every tune in the large file +.SH OPTIONS +.TP +.B -v and -c +mainly used for debugging when the program does not do what was expected. +.TP +.B -ver +prints version number and then exits +.TP +.B --norhythm +Causes the matching algorithm to ignore the length of notes in a bar, +thus E3/2F/D GA2 would match EFD G2A. The option ignores \-r parameter +since it is now irrelevant. +.TP +.B -pitch_table +Used to produce a interval weighted pitch histogram for each tune in +the file. If this is saved in an external file, that file could be used +as a database for finding tunes with similar pitch probability density +functions (pdf). +.TP +.B -r +Controls how the matching criterion handles small rhythm variations in +the melody. The \-r option must be followed by a number which specifies +the temporal resolution for the match. When the number is zero, this +indicates that a perfect match should be performed, meaning that the +lengths of each note in the bar must match exactly in order to be +reported. For larger values a looser match will be performed as +described below. Note lengths are converted into temporal units where +a quarter note normally is assigned a value of 24. Therefore an eight +note has a value of 12, a sixteenth has a value of 6, a half note has +a value of 48 and etc. If you specify a temporal resolution of 12, then +the pitch values of the notes only need to match at time units which +are multiples of an eighth note. +.TP +.B -fixed n +Causes the program to disregard bar lines when does the matching. It +allows matching of notes between tunes having different time signatures. +n is a number which specifies the exact number of notes to match. For +example if n is 4, the program could match +|C E G E| .. with |C E|G E| +Note the matcher still starts at a beginning of a given bar for both the +tune and template. +.TP +.B -con +Specifies contour matching. In this case, the program uses the key +signature only to indicate accidentals. The pitch contour is computed +from the pitch difference or interval between adjacent notes. +.TP +.B -qnt +Uses the contour matching algorithm but also quantizes the intervals +using the following table: + +unison and semitone 0 +minor 2nd to major 2nd 1 +minor 3rd to major 3rd 2 +any larger interval 3 + +Negative numbers are descending intervals. +.TP +.B -tp file name, reference number +Substitute any tune for the template match.abc. When using this +feature, the entire tune is used as a template. Abcmatch does not match +the template with itself, and only bars which match bars in other tunes +are reported. +.TP +.B -br threshold +Runs the program in a brief mode designed to identify groups of tunes +sharing common bars. In this mode, the program counts the numbers of +bars in the test tune which are also present in match.abc. If the +number of common bars is larger or equal to the threshold then the +program reports the tune and the number of common bars. +The program scans all the tunes in the abc file and returns a list of +all the tunes which have more than a specific number of bars in common +with the template, match.abc. In actual use, the program is run +repeatedly by a script. For each tune in a abc file, it creates a +template file called match.abc and then executes abcmatch. The outputs +are displayed on the screen in a form easy to interpret. The user has +no control of the matching criterion. The rhythm must match exactly +and the notes are transposed to suit the key signature. In other words +the \-r parameter is independent of what is specified in the parameter +list. +.TP +.B -pitch_hist or -length_hist +Runs the program in another mode. It produces a histogram of the +distribution of the notes in the abc file. +The pitch is indicated in midi units. Thus middle C is 60 and the +pitches go up in semitone units. Following the pitch is a count +of the number of times that note occurred. +.TP +.B -pitch_table or -interval_table +Used to create a database for a collection of tunes in a file for +future analysis. + +.SH "SEE ALSO" +.PP +.IR abc2abc "(1), " abc2midi "(1), " mftext "(1) ", midi2abc "(1) ", midicopy "(1) ", yaps "(1)" +.SH AUTHOR +This manual page was written by Ross Gammon based on abcmatch.txt by Seymour Shlien. +.SH VERSION +This man page describes abcmatch version 1.35 from January 15 2006. diff --git a/doc/abcmatch.txt b/doc/abcmatch.txt new file mode 100644 index 0000000..dd9d667 --- /dev/null +++ b/doc/abcmatch.txt @@ -0,0 +1,318 @@ +abcmatch version 1.35 January 15 2006. + +seymour shlien + +Introduction: +------------ + +The purpose of this program is to search for specific sequences of +notes in an abc file composed of many tunes. For example, if you +know a few bars of a tune, you can use this program to find the +tune having this sequence and perhaps identify the tune. + +At a minimum, abcmatch requires two files. A template file called +match.abc which contains the bars that you are searching for and +a large file consisting of a hundred or more abc tunes. +The program automatically loads up the match.abc file and +then scans every tune in the large file. + +The match.abc file is a regularly formatted abc file containing +the basic fields, X:, M:, L:, and K: and the body. +Normally, this file is created by runabc.tcl. +An example match.abc file is shown below. + + +X:1 +M:6/8 +L:1/8 +K:E +cff f2e| + +As well as the sample bars, abcmatch needs to know the meter +(given by M:) and the key signature (given by K:). The default note +length L: should also be given if it is not 1/8. It is important +that all bars be terminated with a bar line indicated by | +(otherwise that bar may not be seen by the program). + +Abcmatch uses the key signature to know the relative position +of the notes in the scale. It also uses the key signature to +determine all the assumed sharps and flats. Thus the program +can find matching bars in a tune transposed to another key +signature (assuming the key difference is not too large). +When the program finds matches, they are returned in a list that +looks like this. + +abcmatch.exe scotjig.abc +29 30 4 +30 31 4 + + +Each line indicates a particular match made by the program. +The first number, (eg. 29) indicates the relative position of +the tune in the abc file. Thus in this example, it indicates +that a match was found for the 29 th tune in compilation file +scotjib.abc. The next number is the X: reference number of +that tune, and the last number is the bar number of the matching +tune. Bar numbers are counted sequentially from the start of +the tune, ignoring all V: and P: indications. Thus the bar +numbers may not match the ones you get when you print the +tune using one of the variants of abc2ps or yaps. + +Though the program can be run stand alone, it is really meant to +be run with a graphics user interface such as runabc.tcl (version +1.59 or higher). Most of its output is rather cryptic. + +In performing the match, the program ignores all guitar chords, +karaoke, note decorations (eg. stacatto markings), grace notes +and hornpipe rhythm indications in either the match.abc template +file or in the target file. Furthermore if chords in the form +of [G2c2] are embedded in the abc file, only the higher note +c2 is matched. Any warnings and error messages that are normally +returned by the parser are suppressed unless the run time +parameter -c is included. + + +Installation: +------------ + +Unless you are running the program on Microsoft's windows +operating system, it will be necessary for you to build the +program from sources. For windows environment, I shall provide +the executable. Here is how the makefile looks. + +CFLAGS=-c +abcmatch: parseabc.o matchsup.o abcmatch.o + gcc parseabc.o matchsup.o abcmatch.o -o abcmatch.exe + +parseabc.o : parseabc.c abc.h + gcc $(CFLAGS) abcparse.c + +matchsup.o : matchsup.c abc.h + gcc $(CFLAGS) abcstore.c + +abcmatch.o : abcmatch.c abc.h + gcc $(CFLAGS) abcmatch.c + +The program has been built using the gcc (GNU compiler) as well +as Microsoft Visual C++ (with many warning messages). + + +Operation: +--------- + +Here is now an explanation of the program and its run time +parameters. If you run abcmatch without any parameters you +will see: + +abcmatch version 1.55 +Usage : abcmatch [-options] + [reference number] selects a tune + -c returns error and warning messages + -v selects verbose option + -r resolution for matching + -con pitch contour match + -fixed fixed number of notes + -qnt quantized pitch contour + -lev use levenshtein distance + -a report any matching bars (default all bars) + -ign ignore simple bars + -br %d only report number of matched bars when + above given threshold + -tp [reference number] + -ver returns version number + -pitch_hist pitch histogram + -wpitch_hist interval weighted pitch histogram + -length_hist pitch histogram + -interval_hist pitch interval histogram + -pitch_table separate pitch pdfs for each tune + -interval_table separate interval pdfs for each tune + + +When running this program, you must provide the name of the abc file name +containing the numerous tunes. The other parameters are optional and +are explained below. + +The -c and -v options are mainly used for debugging when the +program does not do what was expected. The -ver option does +nothing but return the version number of the program. (This +is used to perform a sanity check when you are running it +from runabc). + +All the remaining parameters (-r -con -a -br) control the matching +process. + +The option -norhythm, causes the matching algorithm to ignore +the length of notes in a bar, thus E3/2F/D GA2 would match +EFD G2A. The option ignores -r parameter since it is now +irrelevant. + +The option -pitch_table is used to produce a interval weighted +pitch histogram for each tune in the file. If this is saved +in an external file, that file could be used as a database +for finding tunes with similar pitch probability density functions +(pdf). + +The -r parameter controls how the matching criterion handles +small rhythm variations in the melody. The -r option must be +followed by a number which specifies the temporal resolution +for the match. When the number is zero, this indicates that +a perfect match should be performed, meaning that the lengths +of each note in the bar must match exactly in order to be +reported. For larger values a looser match will be performed +as described below. Note lengths are converted into temporal +units where a quarter note normally is assigned a value of +24. Therefore an eight note has a value of 12, a sixteenth has +a value of 6, a half note has a value of 48 and etc. If you +specify a temporal resolution of 12, then the pitch values +of the notes only need to match at time units which are multiples +of an eighth note. + +This means that the program would match the two bars +C2 D2| and C C D D|. +Similarly C2 D2| would also match C/D/C/D/D2|. By using +a suitable value of the resolution, you can perform the +matching only at the beginning of a measure or at the +beginning of each beat. + +The -fixed option causes the program to disregard +bar lines when does the matching. It allows matching +of notes between tunes having different time signatures. +n is a number which specifies the exact number of +notes to match. For example if n is 4, the program +could match +|C E G E| .. with |C E|G E| +Note the matcher still starts at a beginning +of a given bar for both the tune and template. + +Normally, when the program is presented with a sequence +of several bars, the program will try it match it with +a matching sequence. If abcmatch is run with the -a option, +then the bars are matched individually in any sequence. +In other words any matching bar found is reported. + +The -con option specifies contour matching. In this case, +the program uses the key signature only to indicate accidentals. +The pitch contour is computed from the pitch difference +or interval between adjacent notes. + +Thus C2 DE| and c2 de| and G2 AB| all have the same pitch +contour. + +The -qnt option will use the contour matching algorithm +but also quantize the intervals using the following table + +unison and semitone 0 +minor 2nd to major 2nd 1 +minor 3rd to major 3rd 2 +any larger interval 3 + +negative numbers are descending intervals. + +The -tp followed by a file name and reference number +allows you to substitute any tune for the template match.abc. +When using this feature, the entire tune is used as a +template. Abcmatch does not match the template with itself, +and only bars which match bars in other tunes are reported. + +The -br followed by a threshold, runs the program in a brief +mode designed to identify groups of tunes sharing common bars. +(-br stands for brief mode; I cannot think of a better name +right now.) In this mode, the program counts the numbers of bars +in the test tune which are also present in match.abc. If the +number of common bars is larger or equal to the threshold +then the program reports the tune and the number of common bars. +The program scans all the tunes in the abc file and returns +a list of all the tunes which have more than a specific number +of bars in common with the template, match.abc. In actual +use, the program is run repeatedly by a script. For each +tune in a abc file, it creates a template file called match.abc +and then executes abcmatch. The outputs are displayed on the +screen in a form easy to interpret. Currently, the user +has no control of the matching criterion. The rhythm must +match exactly and the notes are transposed to suit the key +signature. In other words the -r parameter is zero independent +of what is specified in the parameter list. + +The -pitch_hist or -length_hist runs the program in another mode. +It produces a histogram of the distribution of the notes in the +abc file. Thus if you type +abcmatch.exe scotjig.abc -pitch_hist + +pitch_histogram +64 2 +66 9 +67 11 +69 30 +71 18 +73 12 +74 14 +76 14 +78 14 +79 4 +81 4 + +The pitch is indicated in midi units. Thus middle C is 60 and the +pitches go up in semitone units. Following the pitch is a count +of the number of times that note occurred. If you type + +abcmatch.exe scotjig.abc -length_hist + +length histogram +12 100 +24 20 +36 6 +48 2 +72 4 + + +The program quantizes a quarter note into 24 units. Thus eighth notes +have a value of 12, dotted half notes 72, etc. The program does +not require the match.abc file to be present if you are computing +the histograms since it does not perform any matching. + + +abcmatch.exe scotjig.abc -interval_hist + +computes the histogram of the pitch interval in midi units +between adjacent notes. The histogram is restricted between +intervals -12 and 12 units. + +eg. +interval_histogram +-5 2 +-4 3 +-3 10 +-2 17 +-1 3 +0 8 +1 3 +2 23 +3 11 +4 1 +5 4 + +For a collection of tunes in a file, you can use -pitch_table +or -interval_table to create a database for future analysis. + + +Limits of the program +--------------------- + +The program has some limits. For example, the abc file must +have bar lines. Tied notes cannot be longer than 8 quarter notes. +Specifying a too small resolution (eg. -r 1) may causes some +buffers to be exceeded. When there are differences of key +signatures more than 5 semitones, the program may transpose +the notes in the wrong direction. + +Abc tunes with more than one key signature or time signature +may not be processed correctly. + +Comment: +________ + + +This program is designed to be a research tool to find +similarities between abc tunes. I have discovered a few +problems with tied notes and double or triple bar lines. + diff --git a/doc/gpl.txt b/doc/gpl.txt new file mode 100644 index 0000000..43fcd01 --- /dev/null +++ b/doc/gpl.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/doc/history.txt b/doc/history.txt new file mode 100644 index 0000000..c9245f5 --- /dev/null +++ b/doc/history.txt @@ -0,0 +1,525 @@ +This file has not been updated since I have taken over +the support of the abcMIDI package. To see the list +of the latest versions see the readme.txt file. To see +a log of all the changes I have made see the file CHANGES. +The abcguide.txt and the unix (linux) man files (eg. abc2midi.1) +contain the latest user guides. The abcguide.txt probably +contains the most detail. The official version number +of the abcMIDI package is given in the file VERSION. + +Seymour Shlien 26 October 2003. +------------------------------------------------------------- + + +current versions : +midi2abc version 2.4 +abc2midi version 1.24 +abc2abc version 1.19 +yaps version 1.12 + +Improvements made to abcMIDI package +------------------------------------ +1. abc2midi was found not to handle comments at end of lines properly. +This was fixed in the source code with release 1.2.1 of abc2midi. + +2. midi2abc was generating %MIDI instead of %%MIDI for a program change. +This was fixed in release 1.6.1 + +3. Release 1.2.2 of abc2midi introduced the -c checking only option and + some new error checking, as well as code to deduce repeats. + +4. abc2abc 1.0 was released on 25th July 1996 + +5. Release 1.2.3 of abc2midi allowed more flexible use of ::, :| and |:, + improved handling of tuples and other minor improvements. + +6. Added #ifdefs for Mac port. + +7. Added -xm and -xl options to midi2abc plus a straight quantization + algorithm for better handling of MIDI output by another package. + +8. Added -Q option to midi2abc. + +9. Removed the default heuristic algorithm and use a straight quantization + algorithm by default, with code to find a good note length by brute-force + trial - Original algorithm sometimes made mistakes in quantizing. + +10. Added V: field to allow multi-track output from abc2midi in version 1.3 + +11. Changed Error messages to Warning messages for some error conditions in + abc2midi. + +12. Improved bar length checking to prevent errors being generated by the + anacrusis in abc2midi. + +13. Added checking for equal track lengths in abc2midi. + +14. Made midi2abc fail cleanly when it runs out of memory for notes. + +15. Fixed part-handling bug in abc2midi. + +16. Improved handling of bar placement in midi2abc. + +17. Fixed various type inconsistencies in midifile.c to improve portability. + +18. abc2midi was not handling propagation of accidentals within a bar e.g. +|^cdc|. This was fixed. + +19. Added handling for the 7 key signature modes and re-wrote parsekey in +the process. + +20. Fixed bug in hornpipe handling routine (tomidi.c). + +21. Fixed bug in default unit calculation (toabc.c). + +22. Changed midi2abc to look at last note to decide between equally likely + key signatures and suggest a mode for the tune if it does not appear + to be major mode. + +23. Changed strchr to index in mftext.c to aid portability. + +24. Changed handling of grace notes to report more error conditions. + +25. Changed midi2abc to generate voice fields for format 1 files and also + to assume the same length anacrusis in each voice. + +26. -xa option added to midi2abc to deduce anacrusis by looking for a strong + beat. + +27. Release 1.4 of abc2midi allows [ and ] for chords, ( ) for slurs and also + introduced a queue mechanism for allowing general polyphony. + +28. Release 1.4 of abc2midi appears to a fix a problem with chord generation. + +29. Release 1.4 of abc2midi recognizes J, H, L and R as note decorations. + +30. Fixed bug in hornpipe routine. + +31. Fixed bug in note decoration recognition. + +32. Added support for multiple fields in " " and ! ! separated by ; . + +33. Fixed problem with grace notes before chords. + +34. Added support for new K: field standard + +35. Fixed bug that caused spurious ties from notes at the end of a slur +field. + +36. Release 1.4.2 of abc2midi made on 15th January 1997. + +36. Correction to midi2abc quantization algorithm + +37. abc2midi changed to allow TAB character instead of space. + +38. -n option added to abc2midi (not the PC version, which already uses +almost the maximum possible memory). + +39. Support added for augmented and diminished chords. + +40. Support added for repeats in part notation e.g. P:A(AB)6. + +41. Added transpose option to abc2abc. + +42. Release 1.4.3 of abc2midi made on 28th April 1997. + +43. Added support for w: field in abc2midi + +44. Fixed problem in chord handling in abc2abc + +45. %%MIDI gchord allowed in mid-tune + +46. added %%MIDI chordprog, bassprog, chordvol, bassvol + +47. length specifiers allowed in %%MIDI gchord string + +48. fixed bar-length checking in abc2abc to do chords and grace notes + +49. Made the linebreaking option more intelligent in abc2abc. + +50. Made abc2abc linebreak at P: + +51. added -u option to abc2abc + +52. added %%MIDI control command to abc2midi + +53. added support for karaoke MIDI to abc2midi. + +54. changed karaoke support to act line by line. + +55. Minor bug fix to karaoke support in version 1.5.1 + +56. Fixed bug in part handling pointed out by Steve Allen. + +58. Complete re-write of midi2abc to use dynamic data structures. +version 2.0 (beta) released on 8th June 1998. + +59. Added -k (specify key) and -ga (guess anacrusis) options to midi2abc. +Fixed bug in printing rests. + +60. version 2.0 of midi2abc released on 12th June 1998. + +61. non-portable error diagnosis removed from mftext and midi2abc. + +62. midi2abc fixed to always produce legimite length notes. + +63. Parser changed to allow arbitrarily long lines. + +64. midi2abc changed to recognize rests before each track. + +65. midi2abc changed to used c = 72 (and undo abc2midi pitches). + +66. Parser changed to allow decorations to be applied to chords. + +67. abc2midi changed to allow broken rhythm between chords. + +68. abc2midi changed to improve accuracy of reported line numbers. + +69. abc2midi mallocs more space for notes or text when needed. + +70. support for staccato notes in chord. + +71. improved tie handling code. + +72. fix to allow all channels to be used (suggested by De Clark). + +73. Static limit on number of syllables in w: fields removed. + +74. Allowed . in part specifier (P: field in header). + +75. Used %%MIDI beat to implement !ppp! to !fff!. + +76. Added -o option to abc2midi to specify filename. + +77. Corrected problem with Voice/Part conflict reported by Brendan Macmillan. + +78. Removed bug in line number generation for error reports. + +79. Version 1.5.8 of abc2midi released on 21st Sept 1998. + +80. Further bug fixing for Voice/Part problem. + +81. Trap buffer overflow in NOFTELL version - problem reported by Richard +Robinson + +82. Clean up NOFTELL modifications to remove linker problems (pcc version). + +83. New NOFTELL mechanism introduced - do a dummy write track to determine +track length in abc2midi. + +84. P:X in the header allowed to be a part marker in abc2midi. + +85. Changed save_note() so that chord generation takes account of transpose +- problem report and bug fix by Seymour Shlien + +86. Tidied up note off queue handling in abc2midi. Fixes problem with PCC +version NOFTELL fix. + +87. Changed min to long in midi2abc guesslengths(). Fixes PCC divide by +zero error. + +88. Added rtranspose to abc2midi. + +89. Cleaned up midi2abc and midifilelib code (no implicit declarations of +parameter types). + +90. Voices inherit global transpose, tempo and meter instead of values from +previous track. + +91. Removed spaces from after tie signs in midi2abc : abc spec. does not +allow spaces in chords. + +92. voicecontext structure introduced to make K: and L: fields local to +their own voice in file parsing stage. + +93. printf() fix: DJGPP seems to require %ld and not %Ld in printf to print +longs. + +94. exit value for all codes made 1 on error and 0 on normal termination. + +95. re-write of karaoke code to integrate it into main mywritetrack() code. +Also allows multiple verses and has better error-checking. + +96. Added %%MIDI chordname and library of named chords to abc2midi + +97. Fixed bug in | handling in abc2midi w: field. + +98. Better checking for M: field in abc2midi + +99. chord handling and broken rhythm handling moved to first pass of +abc2midi. + +100. Further bug fixes for abc2midi w: field. + +101. %%MIDI nobarlines and %%MIDI barlines options added to abc2midi - +based on changes suggested by Laura Conrad. + +102. Added support for M:none. + +103. Voice numbers changed from absolute voice numbers to numerical labels. + +104. Accompaniment written to separate track by abc2midi. + +105. Support put in the parser for abc2ps's [X: ] inline field notation. + +106. Fix to stop bogus Q: fields crashing abc2midi. + +107. Support for "_Ignored words" in abc2midi. + +108. abc2midi allows voices after voice 1 to be missing in some parts. + +109. Changed mf_sec2ticks() in midifile.c to get rid of rounding errors +that were affecting the PCC version of midi2abc. + +110. Fixed problem with tracks not starting at time=0 in abc2midi. + +111. Fixed overflow problem with long H: fields in abc2midi. + +112. [1 allowed to go mid-bar and [2 allowed to be separated from :| +in abc2midi. More robust repeat-fixing algorithm to take account of |1 and +:|2. + +113. Fix to midifile.c suggested by Seymour Shlien to fix problem with +porting to MS visual C++. + +114. Added support for trills in abc2midi. + +116. Fixed bug in midi2abc that caused it to crash if input MIDI file + contained long metatext strings. + +117. Added support for lyrics to tied notes in abc2midi. + +118. Fixed bug that mangled %%MIDI lines in abc2abc and also stopped + abc2abc filtering out comments outside tune. + +119. Added support for clefs in K: field. + +120. Replaced K:cclef with proper clefs; baritone, tenor, alto, mezzo + and soprano. + +121. Minor improvements to parseabc.c - recognizes multiple '/' in + length specifier and warns about c, or C'. + +122. Added support for the I: field to parseabc.c and changed abc2midi + to recognize I:octave=X. + +123. Added -d and -v options to abc2abc for changing unit note lengths. + +124. Parser changed to report an error for \ * ** or ! in mid music line. + +125. midi2abc changed to look for a filename if -f option is missing. + +126. part-handling changed in abc2midi to handle an arbitrary number of + parts. + +127. Support for variant endings more complicated than [1 and [2. Also + allow || to occur mid-bar. + +128. Support for Mac-style text files (with \r as end of line). + +129. -o and -sum options added to midi2abc by Seymour Shlien. + +130. Fixed bug in Part/variant ending interaction in abc2midi. + +131. Fixed bug in yaps' handling of in-tune M: fields. + +132. Added font selection commands to yaps. + +133. Added support for grace notes within broken rhythm to abc2midi. + +134. Added page numbering to yaps. + +135. Fixed bug in yaps which caused fonts to get lost after a newpage. + +136. Added vskip command to yaps. + +137. Added %% font and font-spacing commands to yaps. + +138. Minor changes to support Pacific C compiler. + +139. Added support in yaps for ties and slurs straddling 2 music lines. + +140. Added -x (number tunes with number in X: field) to yaps. + +150. Fix to yaps to handle guitar chords with characters in the +range 128-255. + +151. Added proper tuple support to yaps - uses half-brackets when notes +in the tuple are not a beamed set. + +152. Changed guitar chord transposition in abc2abc to handle A/B and A(B) +as well as not transposing anything with a leading underscore or other +special symbols. + +153. Added support for flipping note heads and spacing out accidentals in +yaps. + +154. Fix for K: parsing code which was running past the end-of-line character +in some cases and generating extra error messages in abc2midi. + +155. Added support for treble-8, treble+8 and similar variants in yaps. + +156. Fix for V: fields in header causing abc2midi to crash. + +157. Changed K: field parser to accept clef=, octave= and transpose= . + +160. Added support for %%staffsep to yaps. + +161. Fix to make yaps bar-length checking cope with in-tune metre changes. + +162. Changed yaps so that all tune spacing is calculated before output file + is opened. This is used to generate encapsulated PostScript and to + start a new page instead of breaking a tune across pages. + +163. Added %%MIDI beatstring to abc2midi - using code by Martijn Versteegh. + +164. Fixed BoundingBox generation in yaps. + +165. Added explicit function type declarations and re-ordered some functions + as well as adding genmidi.h and queues.h to make code compile under + Pacific C and hopefully improve portability. + +166. Added the %%MIDI drum command and !drum! and !nodrum! to abc2midi. + +167. Added support for %%titleleft and %%titlecaps to yaps. + +168. Fixed crash caused by !drum! with no %%MIDI drum statement. + +169. Fixed obscure division by zero error in midi2abc. + +170. Added landscape mode to yaps. + +171. Shortened tempo note tail length in yaps so that it never collides + with the title. + +172. Corrected positioning of C clef in yaps. + +177. Added support for -n X to give X bars per line in abc2abc, with + correct handling of associated w: field. + +178. Added support for dotted rests to yaps. + +179. Fixed bug with broken rhythm in yaps. + +180. Fixed bug causing abc2abc to crash with comments at end of w: field. + (code is still not ideal). + +181. Created parser2.c for common code between abc2midi and yaps. + +182. Made erroneous note-off events a non-fatal error in midi2abc. + +184. Added drum track detection to midi2abc, with output that selects + channel 10 for drums. + +185. Removed channel number from midi2abc %%MIDI program output, so that + abc2midi matches instrument to the correct voice in midi2abc output. + +186. Added -s option to midi2abc to retain very short notes. + +187. Support for abc2midi to handle very long filenames (provided by + Colin Watson). + +188. Fix to allow abc2midi/abc2abc/yaps parser to handle space between + key A-G and mode. + +189. Fix for abc2midi handling of non-consecutive voice numbers. + +190. More user-friendly error message when chord buffer overflows in + abc2midi. + +191. Support for w: line continuation characters in yaps. + +192. Fixed problem with trill generation in abc2midi (was the wrong + length). + +193. Fixed inconsistency in midi2abc.c causing a one octave transpose + if the -k switch was specified. + +194. Changed abc2midi to support _, ^, <, > and @ in guitar chords. + +195. Added support for / in abc2midi guitar chords. + +196. Fix for Q:1/2=X in yaps. + +197. Added support for breve notes and breve rests to yaps. + +198. Changed yaps to accept rests in tuples. + +199. Changed parser to accept tuples written as (n::r . + +200. Fix for handling ties across chords in yaps. + +201. Improved handling of M:none in yaps. + +202. Fixes for bar-length checking in yaps. + +203. Added %%MIDI ratio to abc2midi. + +204. Applied fix supplied by Ingo Saitz for change of tempo not being + handled properly by abc2midi in multi-voice music. + +205. Further fix for bar-length checking in yaps. + +206. Added code change by Seymour Shlien to midi2abc for -sr option to +handle MIDI with gaps between notes that come out as rests. + +207 Added %%chordsabove and %%chordsbelow to yaps. + +208. Added handling for U: field (abbreviation) to parser. + +209. Fix to abc2midi to stop accidentals in accompaniment chords from + being applied elsewhere in the bar. + +210. Changed K: field parsing so that it only starts a tune if it + contains a key signature. + +211. Trapped condition where double ties could cause segmentation faults + - thanks to Seymour Shlien for tracing down this problem. + +212. Added -t and -n options to abc2midi for better handling of filenames. + +213. Made parser more robust when handling L: field - thanks to Seymour + Shlien for telling me that this could cause division by zero errors. + +214. Fix for problem reported by Ronan Keryell - gchord generation now + works after a meter change in the tune. + +215. Added %%MIDI pitchbend command using code supplied by Peter Spath. + +216. Modified readstr() in abc2midi/yaps parser to avoid potential buffer + overflow problem. + +217. Added support for strings before and after Q: tempo field in yaps, + abc2midi and abc2abc. Also added support for yaps to print mid-tune + tempo change. + +218. Added support for N: field to yaps. + +219. Fixed problem with channel allocation in abc2midi following bug + report from Ronan Keryell. + +220. Fixed abc2midi problem with broken rhythm > applied to chords + thanks to bug report by Ronan Keryell. + +221. Added to support for multiple bar rests with Zn notation to + abc2abc, abc2midi and yaps. + +222. Fix to abc2abc guitar chord transposing thanks to bug report by + Atte Jensen. + +223. Fix to handling of reserved characters H-Z in abc2abc following + bug report by Luis Pablo Gasparotto. + +224. Tidied abc2abc code by creating emit_() routines. + +225. Fixed bug with broken rhythm marker able to insert itself in tied + notes. Thanks to Michel Chasseriau for reporting this. + +226. Added support for voice filtering (-V option) to abc2abc. Many of + of the code changes for this were made by Seymour Shlien. + +227. Added warning message to abc2midi when T: is found outside a tune. + +228. Added -nt option to midi2abc to ignore triplets and broken rhythm. + +229. Added -X n option to abc2abc. diff --git a/doc/mftext.1 b/doc/mftext.1 new file mode 100644 index 0000000..3975727 --- /dev/null +++ b/doc/mftext.1 @@ -0,0 +1,20 @@ +.TH MFTEXT 1 +.SH NAME +mftext \- Dump a MIDI file as text +.SH SYNOPSIS +.BI mftext " file" +.SH "DESCRIPTION" +.PP +.B mftext +gives a verbose description of what is in a MIDI file. +You may wish to use it to check the output from +.BR abc2midi . +It is part of the original midifilelib distribution +available from +.IR http://www.harmony-central.com/MIDI/midifilelib.tar.gz . +.SH "SEE ALSO" +.PP +.IR abcmtex "(1), " abc2abc "(1), " abc2midi "(1), " midi2abc "(1)" +.SH AUTHOR +This manual page was written by Anselm Lingnau , +for the Debian GNU/Linux system. diff --git a/doc/midi2abc-stats.txt b/doc/midi2abc-stats.txt new file mode 100644 index 0000000..5113d46 --- /dev/null +++ b/doc/midi2abc-stats.txt @@ -0,0 +1,106 @@ +The output of midi2abc with the -stats is used by +the midiexplorer application which can by found on +sourceforge.net. The output looks something like this + +seymour@corsair:~/abc$ midi2abc summer.mid -stats +ntrks 10 +ppqn 120 +trk 1 +timesig 4/4 0.00 +keysig C 0 0 0.00 +tempo 132.00 bpm +trk 2 +metatext 3 Synth Bass 1 +program 1 38 +trkinfo 1 38 156 774 41022 50468 +trk 3 +metatext 3 Brass 1 +program 2 61 +trkinfo 2 61 102 0 6618 2982 +trk 4 +... +trk 10 +metatext 3 Drums +program 10 17 +trkinfo 10 17 1390 1158 108340 25777 +npulses 58552 +tempocmds 1 +pitchbends 0 +programcmd 0 +progs 35 38 50 54 61 80 81 102 +progsact 49460 50468 15426 3237 2982 22295 15938 4703 +progcolor 0.00 0.00 0.00 0.00 0.00 1.71 0.00 0.26 0.06 0.05 0.00 0.00 0.00 0.65 0.00 0.08 0.00 +drums 36 38 39 42 54 +drumhits 548 287 128 1073 512 +pitches 473 0 1267 216 20 344 36 717 0 321 364 0 +pitchact 0.32 0.00 1.10 0.15 0.03 0.22 0.03 0.51 0.00 0.26 0.20 0.00 +chnact 0.86 0.05 0.06 0.27 0.38 0.26 0.08 0.84 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.00 +pitchentropy 2.567729 + + +Here is a description of some of the values which are outputted. + +timesig 4/4 beat number +is issued each time the time signature is redefined. The beat number +is a decimal number in quarter beats. + +The same apples for keysig (key signature) and tempo redefinition. + +For each channel, midi2abc prints a trkinfo vector which contains +the following information. + +the channel number +the first program number assigned to the channel +the number of notes not appearing inside a chord +the number of notes appearing in a chord +the sum of all the MIDI pitches of the notes +the sum of all the note durations in pulses + +Finally, midi2abc outputs the following data. + +npulses -- the length of the longest track in pulses +tempocmds - the number of tempo commands encountered +pitchbends - the number of pitchbend commands encountered +programcmd - the number of times the program assignment is + reassigned +progs vector - list of all the MIDI programs used +progsact vector - the activity for each of the above MIDI programs. The +activity is the sum of the note durations in pulses for each of the +above programs. +progcolor - described below +drums - a list of all the MIDI percussion numbers used +drumhits - the number of note on commands for each of the above percussion +instruments. +pitches - the number of note on commands for each of the 12 pitch +classes (C, C#, D, D# ... B) +pitchact - duration in pulses of all notes grouped by pitch classes +chnact - duration in pulses of all notes grouped by channel +pitchentropy - entropy of the pitchact probability density function + + +progcolor: The 128 MIDI program numbers are mapped into 17 classes. +These classes group keyboard instruments, brass instruments, guitar +instruments etc into separate groups defined here. +static int progmapper[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 2, + 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 4, 4, 4, 4, 4, 2, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 2, 7, 10, + 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, +11, 11, 11, 11, 11, 11, 11, 11, +12, 12, 12, 12, 12, 12, 12, 12, +13, 13, 13, 13, 13, 13, 13, 13, +14, 14, 14, 14, 14, 14, 14, 14, +15, 15, 15, 15, 15, 15, 15, 15, + 2, 2, 2, 2, 2, 12, 6, 12, + 1, 1, 10, 10, 10, 10, 10, 1, +16, 16, 16, 16, 16, 16, 16, 16 +}; + +The activity in each of these programs is measured, normalized to +a unit length vector and returned in the progcolor vector. + + diff --git a/doc/midi2abc.1 b/doc/midi2abc.1 new file mode 100644 index 0000000..bf06f38 --- /dev/null +++ b/doc/midi2abc.1 @@ -0,0 +1,264 @@ +.TH MIDI2ABC 1 "1 January 2017" +.SH NAME +\fBmidi2abc\fP \- program to convert MIDI format files to abc notation +.SH SYNOPSIS +midi2abc \-f \fIinfile\fP [\-xa] [\-ga] +[\-a \fIacbeats\fP] [\-m \fItime signature\fP] +[\-ppu \fiparts per unit\fP] [\-aul \fidenominator of unit length\fP] +[\-gu] [\-b \fIbars\fP] [\-Q \fItempo\fP] [\-u \fipulses\fP] +[\-k \fIkey\fP] [\-c \fIchannel\fP] [\-obpl] [\-bpl \fibars\fP] [\-bps \fPbars\fP] +[\-o \fIfilename\fP] [\-s] [\-sr \fiunits\fP] [\-sum] [\-nb] [\-nt] +[\-splitvoices] [\-midigram] [\-mftext] [-mftextpulses] [\-nogr] [\-title \fistring\fP] +[\-origin \fistring\fP] + + + +.SH DESCRIPTION +\fImidi2abc\fP takes a MIDI format file and converts it to something as close +as possible to abc text format. The user then has to add text fields not +present in the MIDI header and possibly tidy up the abc note output. +.PP +The output of midi2abc is printed to the screen. To save it to a file, use +the redirection operator, (e.g. \fImidi2abc \-f file.mid > file.abc\fP) or +specify the output file using the \-o option. +.PP +Use only one or none of the options \-u \-gu, \-b and \-Q. Midi2abc normally +converts the MIDI time units into quantum units normally corresponding to the +abc 1/16th note or 1/32nd note. If none of these is present, the +program will use the PPQN information in the MIDI header to compute the suitable +conversion factor. For most MIDI files on the web, it is recommended to rely on +the MIDI header information and not use any of the options other than +the formatting options. +.PP +The program will extract the time signature information from the MIDI file +if it is present. Otherwise it will assume 4/4 or you could specify it with +\-m. option. +.PP +If the tune has an anacrusis, you can use either the \-ga or \-xa option to estimate the its length. Alternatively, you can specify its value using the \-a +option. The anacrusis is specified in half unit lengths, where the unit +length is defined by the L: field. For example if L: 1/8, then a +quarter note would be indicated by the value 4, (4 1/16 units). +.SS OPTIONS +.TP +.B -a \fIacbeats\fP +where acbeats specifies the anacrusis in half unit lengths. +.TP +.B -xa +extract the anacrusis from file by finding the first strong note +.TP +.B -ga +guess the anacrusis by minimizing the number of ties across bars +.TP +.B -m \fItime signature\fP +time signature +.TP +.B -b \fIbars\fP +number of bars wanted in output +.TP +.B -Q \fItempo\fP +tempo in quarter\-notes per minute +.TP +.B -u \fipulses\fP +Allows you to specify directly the number of midi pulses per +abc time unit. +.TP +.B -ppu \fiparts per abc unit length\fP +Normally, the smallest note unit that midi2abc can extract +is half the L: unit length.This is called the quantum unit. +Thus for L: 1/8, midi2abc can extract 1/16 notes but not 1/32 notes. +You can change this by specifying \-ppu 4 for example. The number of parts +should be a power of 2. +.TP +.B -aul \fidenominator of abc unit length\fP +Normally midi2abc chooses a unit length of 1/8 or 1/16 +depending upon the time signature. For time signatures +smaller than 3/4 the L: 1/16 is used and for larger time +signatures L: 1/8 is used. You can specify the unit length +to be used using this parameter. Thus \-aul 32 will cause +midi2abc to use a unit length of 1/32 nd note. +.TP +.B -gu +Tells midi2abc to estimate the number of midi pulses per abc +time unit from the note duration or spacing in the MIDI file. +.TP +.B -gk +Tells midi2abc to guess the key signature by minimizing +the number of accidentals even if the key signature is +already specified in the MIDI file. By default the key +signature is the one specified in the MIDI file. +If it is not specified, then the program guesses the +key signature by minimizing accidentals. +.TP +.B -k \fIkey\fP +key signature: \-6 to 6 sharps. +.TP +.B -c \fIchannel\fP +select only this midi channel. +.TP +.B -f \fIinfile\fP +input file in midi format +.TP +.B -o \fIoutput file\fP +specifies the output abc file name. +.TP +.B -s +do not discard very short notes. +.TP +.B -sr \fIquantum units\fP +do not notate a short rest smaller than the specified size after a note. If the +size (in quantum units) is zero, nothing is done. For larger values, the rest +is absorbed into the preceding note. In other words, the preceding note +is lengthened to include that rest. +.TP +.B -sum +print a short summary of the input midi file. +.TP +.B -nb +do not look for broken rhythms +.TP +.B -nt +do not look for triplets +.TP +.B -obpl +Print only one bar per line instead of 4. For complex music this +improves the readability and avoids some problems with some abc +to postscript converters. This option is deprecated. +.TP +.B -nogr +(No note grouping.) Inserts a space between all notes. It makes +a less pretty postscript file but it is easier to edit. +.TP +.B -bpl \finbars\fP +Print nbars of music on every line followed by a backslash. +.TP +.B -bps \finbars\fP +When nbars have been printed (including those lines joined by +a backslash continuation) go to a new line (with no backslash). +.TP +.B -splitvoices +This parameter handles polyphonic chords by +splitting an entire voice into multiple voices. (A polyphonic +chord is a chord composed of notes that do not start +or end at the same time.) Normally, midi2abc joins the +longer notes to the notes in the following chord using ties. +Here is an example: [Bd-]d [Bd-]d|. This should +be separated into two voices ideally Bz Bz and d2 d2. However, +the separation is not unique. Bz d2 and d2 Bz are also ok. +.TP +.B -midigram +When this option appears, all other options are ignored and +no abc file is produced. Instead a list of all notes in the +MIDI file are printed in a fixed format. Each line represents +a pair of MIDI note on/off event. The line contains the +on/off time of the note, its track number, channel number, +midi pitch and midi velocity. The last record indicates +the duration of the MIDI file in MIDI pulse units. The +output is designed to go into a graphical user interface +which will produce a graphical representation (piano roll). +.TP +.B -mftext +When this option appears, all other options are ignored and +no abc file is produced. Instead a list of all the MIDI +commands are printed. The output is designed to go into +a graphical user interface provided by runabc.tcl. +.TP +.B -mftextpulses +Same as -mftext except the time units is in midi pulses. +.TP +.B -title \fistring\fP +Replaces the default title field following T: with +the given string. +.TP +.B -origin \fistring\fP +Adds an O: field with the given string. +.TP +.B -stats +Extracts the characteristics of the given midi file. They include +ntrks - the number of tracks, ppqn - pulses per quarter note, +timesig - time signature, keysig - key signature, program - mapping +between channel number and midi program, npulses - length of the +midi file in pulses, tempocmd - number of times the tempo has +been specified, pitchbends - number of pitchbends, pitchbendin - +number of pitchbends in each of the channels, programcmd - number of +times the midi program has been revised, progs and progsact - the +programs used and the number of pulses these programs used, drums - +the drum numbers that were used, drumhits - the number of times +each of those drums were hit, pitches - the number of times the +11 pitch classes (C C# etc...) were activated and a few other +complex variables. These characteristics are used in other +applications such as midiexplorer. More details are available +in the file midi2abc-stats.txt included in the doc/ folder +of the abcmidi distribution package. + + +.SS FEATURES +* The key is chosen so as to minimize the number of accidentals. +Alternatively, the user can specify the key numerically (a positive number +is the number of sharps, a negative number is minus the number of flats). +.PP +* Note length can be set by specifying the total number of bars or the +tempo of the piece. Alternatively the note length can be read from the file. +However, by default it is deduced in a heuristic manner from the inter-note +distances. This means that you do not have to use the MIDI clock as a +metronome when playing in a tune from a keyboard. +.PP +* Barlines are automatically inserted. The user specifies the number of +measures in the anacrusis before the first barline and the time signature. +.PP +* The program can guess how the length of the anacrusis, +either by looking for the first strong note or minimizing the number of +notes split by a tie across a barline. +.PP +* Where a note extends beyond a bar break, it is split into two tied notes. +.PP +* The output has 4 bars per line. +.PP +* Enough accidental signs are put in the music to ensure that no pitch +errors occur if a barline is added or deleted. +.PP +* The program attempts to group notes sensibly in each bar. +.PP +* Triplets and broken rhythm (a>b) are supported. +.PP +* Chords are identified. +.PP +* Text information from the original MIDI file is included as comments. +.PP +* The \-c option can be used to select only 1 MIDI channel. Events on +other channels are ignored. +.SS LIMITATIONS +midi2abc does not ... +.PP +* Supply tune title, composer or any other field apart from X: , K:, Q:, M: +and L: - these must be added by hand afterwards, though they may have been +included in the text of the MIDI file. +.PP +* Support duplets, quadruplets, other esoteric features. +.PP +* Support mid-tune key or time signature changes. +.PP +* Deduce repeats. The output is just the notes in the input file. +.PP +* Recover an abc tune as supplied to abc2midi. However, if you want to +do this, "midi2abc \-xa \-f file.mid" comes close. +.SH "SEE ALSO" +abc2ps(1), abc2midi(1), abc2abc(1) +.SH AUTHOR +James Allwright +.SH SUPPORTED +Seymour Shlien +.SH VERSION +This man page describes midi2abc version 2.91 from March 09 2008. +.SH COPYRIGHT +Copyright 1999 James Allwright +.PP +midi2abc does not work correctly if lyrics are embedded in +the same track as the notes. If you are producing the MIDI +file using abc2midi, use the \-STFW option to ensure that the +lyrics are put in a separate track. +.PP +midi2abc is supplied "as is" without any warranty. It +is free software and can be used, copied, modified and +distributed without fee under the terms of the GNU General +Public License. + diff --git a/doc/midicopy.1 b/doc/midicopy.1 new file mode 100644 index 0000000..460f854 --- /dev/null +++ b/doc/midicopy.1 @@ -0,0 +1,157 @@ +.TH MIDICOPY 1 +.SH NAME +midicopy \- Copy selected track, channel, time interval of a MIDI file to another MIDI file +.SH SYNOPSIS +\fBmidicopy\fP [\fB-ver\fP] [\fB-trks\fP \fIn1,n2,..\fP]\ + [\fB-xtrks\fP \fIn1,n2,..\fP]\ + [\fB-xchns\fP \fIn1,n2,..\fP]\ + [\fB-chans\fP \fIn1,n2,...\fP]\ + [\fB-from\fP \fIn (in midi ticks)\fP] [\fB-to\fP \fIn (in midi ticks)\fP]\ + [\fB-fromsec %f\fP \fIn (in seconds)\fP] [\fB-tosec\fP \fIn (in seconds)\fP]\ + [\fB-frombeat %f\fP \fIn (in beats)\fP] [\fB-tobeat\fP \fIn (in beats)\fP]\ + [\fB-replace\fP \fItrk,loc,val\fP] [\fB-tempo %n\fP] [\fB-speed %f\fP]\ + [\fB-drumfocus\fP \fIn \fIm\fP] [\fB-mutenodrum [%d]\fP]\ + [\fB-setdrumloudness\fP \fIn \fIm\fP]\ + [\fB-focusontrack\fP \fIn1,n2,... (from 1)\fP]\ + [\fB-focusonchannel\fP \fIn1,n2,... (from 1)\fP]\ + [\fB-attenuation\fP \fIn\fP]\ + [\fB-nobends\fP]\ + [\fB-indrums\fP \fIn1,n2,...\fP]\ + [\fB-xdrums\fP \fIn1,n2,...\fP]\ + [\fB-onlydrums\fP]\ + [\fB-nodrums\fP]\ + \fIinput.mid output.mid\fP +.SH "DESCRIPTION" +.PP +.B midicopy +is used to copy part of a MIDI file to another MIDI file. You can select +a particular time interval, particular channels, and particular tracks +or any combinations. If one or both of the run time parameters \-from or \-to +are included, the program returns the playing time in seconds of the +output file. Midicopy was developed by Seymour Shlien from the +midifilelib distribution available from +.IR http://www.harmony-central.com/MIDI/midifilelib.tar.gz . +.SH OPTIONS +.TP +.B -ver +prints version number and then exits +.TP +.B -trks n1,n2, etc +Selects the tracks to be copied where the track numbers start +from 1. If more than one track is specified, they should be separated by +commas. You should always copy track 1 since by convention it contains +information pertinent to all the other tracks. By default all tracks +are copied unless you specify particular tracks using this run time +parameter. +.TP +.B -xtrks n1,n2, etc +Lists the tracks to exclude from copying. All other tracks are copied. +This option does not work in combination with \-trks. +.TP +.B -xchns n1,n2, etc +Lists the channels to exclude from copying. All other channels are copied. +This option does not work in combination with \-chns. +.TP +.B -chns n +Like above, it specifies the MIDI channels to be copied. By default +all channels are copied. Channel numbers also start from 1. +.TP +.B -from n +The program will copy all MIDI commands starting from midi pulse +number n. By default it will start from time zero or the beginning +of the MIDI file. +.TP +.B -to n +Stops copying all events after midi pulse number n. By default +the file is copied to the end. +.TP +.B -frombeat n +The program will copy all MIDI commands starting from quarter beat +number n. By default it will start from time zero or the beginning +of the MIDI file. +.TP +.B -tobeat n +Stops copying all events after quarter beat number n. By default +the file is copied to the end. +.TP +.B -fromsec n +The program will copy all MIDI commands starting from time n +in seconds. +.TP +.B -tosec n +Stops copying all events after time n in seconds. These two +options (\-fromsec and \-tosec) do not work accurately if the +MIDI file has more than one tempo command. Only the first +one is used for converting seconds into MIDI pulse units. +It is therefore preferable to use the \-from and \-to options. +.TP +.B -replace trk,loc,val +This option should be used alone. Midicopy will copy the entire +file verbatim except it will replace a byte by val, where the +byte is located in the specified track (trk) and specified position +(loc). Commonly this function is used for changing a particular +MIDI program number (instrument) associated with a channel. +You need to know the byte count in the track of that parameter +in order to use this function, +.TP +.B -tempo quarter notes/minute +All tempo indications in the midi file will be replaced with +the above value. +.TP +.B -speed factor +All tempo indications in the midi file will be multiplied with +this factor. Values greater than 1.0 will speed up the music while +lower values slow the music. The factor is a floating point value. +.TP +.B -drumfocus drum-code excluded_drum_velocities +The selected drum line (specified by the drum-code pitch value) is +highlighted by reducing the loudness of all other drum lines to +the excluded_drum_velocities value. The drum-code value must +be in the range of 35 to 81 inclusive. +.TP +.B -mutenodrum [level] +All channels which are not 9 (drum channel) are attenuated to the +given level. If level is not specified, it is assumed to be zero. +.TP +.B -setdrumloudness n m +where n is between 35 to 81 inclusive and m is the loudness between +0 and 127. The loudness of all instances of drum n are changed +to m. +.TP +.B -focusontrack n1,n2,... +The velocities of notes in all tracks except n are attenuated. +.TP +.B -focusonchannel n1,n2,... +The velocities of notes in all channels except n are attenuated. +.TP +.B -attenuation n +Specifies the amount the note velocities are reduced by either +-focusontracks or -focusonchannels. Current default is 70. +.TP +.B -nobends +Suppresses all channel pitchbend commands. +.TP +.B -indrums n1,n2,... +Only allow percussions with codes n1,n2,... +.TP +.B -xdrums n1,n2,... +Exclude the percussions with codes n1,n2,... +.TP +.B -onlydrums +Only copy the percussion channel. +.TP +.B -nodrums +Copy all channels except the percussion channel. + +.SH EXAMPLE +.B midicopy.exe -trks 1,5 -from 2669 -to 8634 uzicko.mid fragment.mid +Midicopy will copy tracks 1 and 5 starting from midi pulse position +2669 and ending at MIDI pulse position 8634. + +.SH "SEE ALSO" +.PP +.IR abcmtex "(1), " abc2abc "(1), " abc2midi "(1), " midi2abc "(1) ", yaps "(1)" +.SH AUTHOR +This manual page was written by Seymour Shlien. +.SH VERSION +This man page describes midicopy version 1.33 from December 22 2019. diff --git a/doc/programming/abc2midi.txt b/doc/programming/abc2midi.txt new file mode 100644 index 0000000..15202c7 --- /dev/null +++ b/doc/programming/abc2midi.txt @@ -0,0 +1,420 @@ +Some Notes on the abc2midi Code +------------------------------- + written by Seymour Shlien + + +Abc2midi.txt - last updated 29 November 1999. + + +This file provides an algorithmic description of the program +abc2midi which converts an abc file into a midi file. + +The sources of abc2midi now comprising of 6700 lines of C code are +contained in the following five files. + +parseabc.c is the front end which scans the abc file and invokes + the appropriate event handler for each element it encounters + (eg. bar lines, notes, chords etc.) It happens to be the + front end for other programs such as abc2ps, yaps and + abc2abc. +store.c contains all the event handlers which are invoked from + parseabc. It converts the abc file into an internal + representation described later in this file. +genmidi.c converts this internal representation in an output midi + file. +queues.c are some utilities needed by genmidi. +midifile.c is a library of public domain routines to read and write + midifiles. + +In order to handle the multiple voices, parts, repeats and accompaniments +which occur in abc files, the program performs multiple passes. The +midi file stores the different voices, accompaniment and lyrics in +individual tracks, so it is necessary to separates these parts prior +to writing it to the midi file. If there are repeats in the music, +something which appears only once in the abc file may be invoked twice +when creating the output midi file. + +Parseabc.c +---------- + +The parser has been written so that it should be possible to write +your own utility to handle the interpreted abc and link it with +the parser code. This is very similar to the way that the midifilelib +utilities work. The parser is designed so that it can write out +almost exactly what it reads in. This means that in some cases +the level of parsing is fairly primitive and it may be necessary to make +use of routines in store.c which perform further processing on an item. + +In the first phase of parsing, the abc file is read and when, say, a note +is encountered, the routine event_note() is called. The code for event_note +is in the file store.c. Encountering an X in the abc generally causes a +routine called event_X() to be called. An internal representation of the tune +is built up and when the end of an abc tune is reached, a little bit of +processing is done on the internal representation before the routine +mywritetrack() is called to actually write out the MIDI file. + +The main program to abc2midi is contained in this file. Since this +main program is used to start other programs such as yaps, it is +fairly simple. It calls event_init defined in store.c which obtains +all the user parameters (eg. input filename) and then executes the +top level procedure, parsefile. + +The procedure parsefile (filename), opens the specified file (or stdin) +and processes it one character at a time. The characters fill a line +buffer which is passed to the procedure parseline whenever a linebreak +character (eg. linefeed) is encountered. By doing it in this fashion, +abc2midi is able to eliminate the extra carriage return which occurs +in DOS files. + +The procedure parseline first checks for blank lines and comments. A +blank line signals the end of the tune and the event_blankline is called +to initiate the next stage in processing. If it is neither a comment or +blank line, the procedure must decide whether the line is a a field line +(eg."X:2") or part of a music body (eg. "|:C>DGz|..."). This is decided +using the following rule. If the first letter begins with one of the field +letter commands and is immediately followed by a ":", then it is treated +as a field line and parsefield is called. Otherwise if a K: field line +was already encountered (variable inbody set to 1), then it is treated +as a line of music. If neither case is satisfied, then the line is +intepreted as plain text. + +The procedure parsefield identifies the particular field line type +and invokes the appropriate support function or event handler. If the +field command occurs after the first K: line, then only certain field +lines are legal. (For example it is illegal to place a T: (title) line +after the K: (key signature) line.) + +The procedure parsemusic is the most complex procedure in the file and +recognizes the musical notes, chords, guitar chord names, bar lines, +repeats, slurs, ties, graces etc. Appropriate event handlers and +support functions are called to complete the tasks of parsing the +information. The parsenote function, for example, must check for +decorations, accidentals, octave shifts as well as identifying the +note and its determining its duration. + +Unlike the other software modules, parseabc.c contains few global +variables. The global variables linenum, inhead, inbody, parsing, +slur, parserinchord indicate which lexical component of the abc +tune is being processed. + + + + +store.c +------- + +This is the most complex module consisting of almost 3000 lines +of source code. This module contains all of the event handlers which +may be invoked in the file parseabc.c. The main purpose of these +handlers are to build up an internal representation of the abc file +in the global memory arrays. This is a complete representation +which allows the regeneration of the abc file (eg. abc2abc) or +the creation of a midi file. The internal representation is used +by the genmidi.c software to create the midi file. + + +Global variables + +The internal representation is stored in global variables defined +at the beginning of the file. A description of the most important +variables is given here. + +The music is stored in the four arrays, feature, pitch, num, denom. +These arrays contains a list of the lexical components in the order +that they have been encountered or created. + +The array "feature" identifies the type of component which can be one +of the following enum features. + +SINGLE_BAR, DOUBLE_BAR, BAR_REP, REP_BAR, REP1, REP2, BAR1, +REP_BAR2, DOUBLE_REP, THICK_THIN, THIN_THICK, PART, TEMPO, +TIME, KEY, REST, TUPLE, NOTE, NONOTE, OLDTIE, TEXT, SLUR_ON, +SLUR_OFF, TIE, TITLE, CHANNEL, TRANSPOSE, RTRANSPOSE, GRACEON, +GRACEOFF, SETGRACE, SETC, GCHORD, GCHORDON, GCHORDOFF, VOICE, +CHORDON, CHORDOFF, SLUR_TIE, TNOTE, LT, GT, DYNAMIC, LINENUM, +MUSICLINE, MUSICSTOP, WORDLINE, WORDSTOP + +The array pitch[] mainly stores the pitch of a musical note, +represented in the same manner as in a midi file. Thus middle +C has a value of 60. The array has other uses, for example +in a LINENUM feature it stores the line number relative to +the X: reference command where the lexical feature has been +detected. The LINENUM feature is useful when reporting warnings +or errors in the input file. Duration of the notes are represented +as a fraction, where the standard unit is defined by the L: +command. If feature[n] is a NOTE, then num[n] and denom[n] +contain the numerator and denominator of this fraction. + +Here is an example of the contents of these arrays for the +following small file in the same order that they are stored in +these arrays. + +X: 1 +T: sample +M: 2/4 +L: 1/8 +K: G +|: C>D[EF]G |C4:| + + +Feature Pitch Num Denom +LINENUM 2 0 0 +TITLE 0 0 0 +LINENUM 3 0 0 +LINENUM 4 0 0 +LINENUM 5 0 0 +DOUBLE_BAR 0 0 0 +LINENUM 6 0 0 +MUSICLINE 0 0 0 +BAR_REP 0 0 0 +NOTE 60 2 3 +NOTE 62 1 3 +CHORDON 0 0 0 +NOTE 64 1 2 +NOTE 66 1 2 +CHORDOFF 0 1 2 +NOTE 67 1 2 +SINGLE_BAR 0 0 0 +NOTE 60 2 1 +REP_BAR 0 0 0 +MUSIC_STOP 0 0 0 +LINENUM 7 0 0 + + +In order to support multivoice abc files in the form +V:1 +| ...| ...|.... +V:2 +| ...| ...|.... +% +V:1 +| ...| ...|.... +V:2 +| ...| ...|.... +etc. + +abc2midi maintains a voicecontext structure for each voice. +This allows each voice to define its own key signature, default +note length using internal field commands. There is a head +voicecontext which is used when no voice field commands are +defined in the abc file. The v[] array maintains a set of +all voices active in the abc file and voicecount keeps track +of the number of voices. + +Similarly, abcmidi maintains a list of all the part stored +in the feature[], pitch[], num[] and denom[] arrays. + +All text items (eg. title and some other fields) are stored +in char atext[][] arrays, so that they can be included in +the midi output file. The textual information is repeated +in each track of the output midi file. + +Following the conventions in the midi file, the program uses +the quarter note as the standard unit of time instead of the +whole note. In contrast, the standard length in the abc file +is based on the whole note. For example in L:1/8, the fraction +refers to a whole note. In order to convert time units to +quarter notes, the numerator of the time specifications +for note lengths is multiplied by 4 when it is added to +the feature list. + +Table of contents of procedures in store.c + +getarg(option, argc, argv) - gets run time arguments. +newvoice(n) - creates a new voice context. +getvoicecontext() - finds or makes a voice context. +clearvoicecontexts() - frees up the memory of the voice context + +event_init() - called by main program +event_text(s) - called when a line of text is encountered. +event_reserved(p) - handles reserved character codes H-Z. +event_tex(s) - called whenever a TeX command is encountered. +event_linebreak() - called whenever a newline character is encountered. +event_startmusicline() - called for each new music line. +event_endmusicline() - called at the end of each music line. +event_eof() - end of abc file encountered. +event_fatal_error(s) - reports fatal error. +event_error(s) - reports an error. +event_warning(s) - reports a potential problem. +event_comment(s) - called whenever a comment is encountered. +event_specific(package, s) - recognizes %%package s. +event_startinline() - beginning of an in-music field command. +event_closeinline() - finishes an in-music field command. +event_field(k,f) - for R:, T: and any other unprocessed field commands. +event_words(p) - processes a w: field command. + +char_out(list,out,ch) - for building up a parts list in a P: command. +read_spec() - converts P:A(AB)3 to P:AABABAB etc. +event_part(s) - handles a P: field. + +char_break() - reports error for improper voice change. +event_voice(n,s) - processes a V: field. +event_length(n) - recognizes L: field +event_blankline - starts finishfile() procedure. +event_refno(n) - recognizes X: +event_tempo(n, a, b, rel) - recognizes Q: +event_timesig(n, m) - recognizes M: +event_key(sharps, s, minor, modmap, modmul) - recognizes K: +event_graceon() - start of grace notes, "{" encountered. +event_graceoff() - end of grace notes, "}" encountered. +event_rep1() - handles first repeat indicated by [1. +event_rep2() - handles second repeat indicated by [2. +event_slur(t) -called when s encountered in abc. +event_sluron(t) called when "(" is encountered in abc. +event_sluroff(t) called when ")" is encountered in abc. +slurtotie() - converts slur into tied notes. +event_tie() - handles tie indication "-". +event_rest(n,m) - processes rest indication Z or z. +event_bar(type) - processes various types of bar lines. +event_space() - space character encountered. Ignored here. +event_linend(ch,n) - handles line continuation at end of line (eg. \). +event_broken(type, mult) - handles >, <, >> etc. in abc. +event_tuple(n,q,r) - handles triplets and general tuplets. +event_chord() - called whenever + is encountered. +marknotestart() - remembers last few notes in voice context. +marknoteend() - this is used to process broken rhythms (eg. >). +marknote() - called for single note (as opposed to chord). +event_chordon() - called whenever [ is encountered. +event_chordoff() - called whenever ] is encountered. +splitstring(s,sep,handler) - splits string with separator sep. +event_instuction(s) - handles !...! event. +getchordnumber(s) - searches known chords for chord s. +addchordname(s, len, notes) - adds chord name to known chord list. +event_gchord(s) - handles guitar chords. +event_handle_gchord(s) - handler for guitar chords. +event_handle_instruction(s) - handles dynamic indications (eg. !ppp!). +event_finger(p) - handles 1,2,...5 in guitar chord field (does nothing). +hornp(num,denom) - modifies rhythm to hornpipe. +event_note(roll, staccato, updown, accidental, mult, note, octave, n, m) +doroll(note,octave,n,m,pitch) - applies roll to note. +dotrill(note,octave,n,m,pitch) - applies trill to note. +pitchof(note,accidental,mult,octave) -finds MIDI pitch value +setmap(sf,map,mult) - converts key signature to accidental map. +altermap(v,modmap,modmul) - modifies accidental map. +copymap(v) - sets up working accidental map at beginning of bar. + +addfeature(f,p,n,d) - places feature in internal tables. +autoextend(maxnotes) - increase memory limits for feature arrays. +textextend(maxstrings, stringarray) - resize array pointers to strings. +myputc(c) - workaround for problems with PCC compiler. +tiefix() - connect up tied notes. +dotie(j,xinchord) - called in preprocessing stage to handle ties. +addfrac(xnum,xdenom,a,b) - add a/b to the number of units in bar. +applybroken(place, type, n) - adjust length of broken notes. +brokenadjust() -adjust length of broken notes. +applygrace() - assign lengths to grace notes. +dograce() - assign lengths to grace notes. +lenmul(n, a, b) - multiply num(n),denom(n) by a/b. +zerobar() - start a new count of beats in the bar. +delendrep() - remove bogus repeat. +placeendrep(j) - patch up missing repeat. +placestartrep(j) - patch up missing repeat. +fixreps() - find and correct missing repeats in music. +startfile() - initialization performed after an event_refno. +tempounits(t_num, t_denom) - interprets Q: field. +setbeat() - sets default gchord command for time signature. +headerprocess() - called after the first K: field in tune. +finishfile() - starts next stage of processing when end of tune +is encountered. + +All the functions in this file respond to event calls from parseabc. +Once the internal representation of the abc file is completed, the +procedure finishfile is called to perform some clean up and create +the midi file. An internal representation of the midi file is +first created and then it is written onto the designated output file. +As finishfile provides the link to the next module, genmidi.c, here +is a brief description of what it does. + +proc finishfile performs several passes through the internal +representation to clean up the graces (dograce), the tied notes +(tiefix) and any unbalanced repeats. It then calls writetrack(i) +for each midi track to create the internal midi representation +and finally the midi representation is recorded in the output +file. + + + +genmidi.c +--------- +The procedure finishfile described above, creates each midi track +by calling the function writetrack which is defined here. To create +a track from the internal representation, the program must find all +the parts and put them in order with all the repeats. In addition, if +it contains karaoke text, this too must be placed in a separate track. +Any chordal accompaniment is generated from the guitar chord indications +and placed in another track. For multivoice and multipart music, a voice +may be missing in a particular part. If the voice is missing, the +procedure fillvoice ensures that all voices remain properly aligned when +the voice reappears in another part. + +Here is a simple road map to the important procedures included in this +file. + +dodeferred is here used to handle any dynamic indications (eg. !ppp!) +which may be contained in the file. The %%MIDI messages are stored +in a atext string which is pointed to by the contents of the pitch[] +array. + +checkbar is called each time a bar line is encountered and reports +a warning if the wrong number of beats occur. + +Transitions between parts are handled by the procedure partbreak. + +There are a number of procedures for handling karoake text -- +karaokestarttrack(), findwline(startline), getword(place,w), +write_syllable(place) and checksyllables(). + +For the first track, the meter, tempo and key signature are recorded +using the functions set_meter(n,m), write_meter(n,m), write_keysig(sf,mi). + +Chordal accompaniment is produced by the procedure dogchords(i). + + + +queues.c +-------- + +For each midi note, it is necessary to send a note-on and a note-off +instruction. When polyphonic music is played on the same track, keeping +track of the time to issue a note-off instruction may get complicated. +The procedures in this file are used to maintain a linked list for the +notes to be turned off. The notes are put into the list in the order +that they are encountered but the order in which to issue note-off +commands is maintained by the links. As many as 50 notes playing +simultaneously can be handled by the list. + + + + + +Addendum +-------- + +The following section contains clarifications on various components +of abc2midi. + +29 June 2003 + +Treatment of octave shifts. + +The key signature field command K: has provision for shifting +a note using either transpose= or octave= subcommands. Both +of these functions operate quite differently and deserve some +description especially for multivoiced tunes. + +The octave shift, is performed in event_note in store.c, using +the cached value v.octaveshift which is stored in the global +voicecontext structure, v. There is a structure for each voice +in the abc file. Whenever a new V: command is encountered, +event_voice (store.c) is invoked, which swaps the appropriate +voices structure into the global v array using the function +getvoicecontext(n). If getvoicecontext cannot find a cached +structure for that voice, then a new voice structure is created +and added to the linked list of voice structures. The v.octaveshift +variable is updated by event_octave which is called by event_key +(store.c) which is called by parsekey in parseabc.c +(Comment: it is not too clear how an octave switch is +handled in the middle of a repeat section. i.e. does the old +value get restored when repeating.) + +(Description of transpose shift is in CHANGES July 1 2003.) diff --git a/doc/programming/coding.txt b/doc/programming/coding.txt new file mode 100644 index 0000000..289ea2d --- /dev/null +++ b/doc/programming/coding.txt @@ -0,0 +1,426 @@ +Notes on the code +----------------- + +These notes are for anyone who wants to re-compile, re-write or re-use +bits of the code. Additional information is available by downloading +the file abcextra.zip. This includes : + +* man pages for abc2midi and midi2abc. +* A detailed description of the inner workings of abc2midi, written by + Seymour Shlien. + +Compilation +----------- + +The file midifile.c and the header file midifile.h are slightly changed from +the midifilelib distribution. To see the program dependencies, examine the +Makefile. + +The code is written in K&R style C and should be fairly easy to compile +on any system with a C compiler and a make utility. Makefiles are +provided for gcc/unix, DJGPP/DOS and PCC/DOS. There are also some notes +on using the GUI front-end to Pacific C/DOS. You may get warning +messages if your compiler prefers ANSI C style function prototypes. + +Choose the most suitable makefile; unix.mak, djgpp.mak or pcc.mak and +rename it as 'makefile'. If you are not using any of the above compilers, +you may have to edit the makefile so that it uses compilation flags +suitable for your compiler. + +To compile the code, type + +make all + +If the complete compilation does not work, you can try compiling the +individual programs separately : + +make midi2abc (or make midi2abc.exe) +make abc2midi (or make abc2midi.exe) +make abc2abc (or make abc2abc.exe) +make mftext (or make mftext.exe) +make yaps (or make yaps.exe) + +Note that the make utility on some systems (e.g. GNU make) may require the +Makefile to be a unix text file and not a DOS text file. The difference +is that unix uses newline to mark the end of each line while DOS uses +carriage return and newline. + +Note, if you have difficulty compiling the package because you do not have +snprintf see the note in doc/CHANGES dated January 08 2005 (and also +December 17 2004). + + +--------------------------------------------------------------------- +Calling abc2midi or midi2abc from a GUI. +---------------------------------------- + +The programs should now have an exit value of 0 for normal termination +and 1 for an error state. However, abc2midi will still exit with 0 if +it finds non-fatal errors in the code, so the user should always have +the option of looking at the program's text output (I don't want to +get blamed when useful diagnostic output turns into the ubiquitous +'OK' click-button). + +---------------------------------------------------------------------- +Man pages +--------- +Files: abc2midi.1 and midi2abc.1 + +Christoph Dalitz has written some man pages for abc2midi and +midi2abc. These should be installed in the sub-directory /man1 +of the directory given by the MANPATH environment variable. +(The man command is usually only found on Unix variants). + +The source distribution has been re-organized to contain only the +source and a few text files. If you want these man pages, you need +to download the file abcextra.zip. + +--------------------------------------------------------------------- +Code Layout and Indentation style +--------------------------------- +If you want to add your own code and make it fit in with the existing +coding style, you can use GNU indent. The following is a DOS batch file +to invoke indent with the appropriate options. + +indent -bad -bap -br -ce -cli0 -npcs -di1 -nbc -i2 -ts0 -psl -lp -ipo %1 +rem +rem options for GNU indent to achieve my personal style +rem +rem -bad blank line after declaration block +rem -bap blank line after procedure body +rem -br brace on same line after if, struct and enum +rem -ce cuddle else +rem -cli0 case at same identation as switch +rem -npcs no space between procedure name and following open bracket +rem -di1 one space between variable type and variable name +rem -nbc comma-separated variables on the same line +rem -i2 indent 2 spaces +rem -ts0 no tabs +rem -npsl function type on same line as function name +rem -lp continuations matched to left parenthesis +rem -ip0 no indention of variables in K&R function headers +rem -ncs no space after cast + +--------------------------------------------------------------------- + +Extensions to the abc Format +---------------------------- + +1. The parser recognizes +%%package +as some package-specific command and calls event_specific with the +package name and the string that follows it. + +2. The abc standard defines notation for 4 octaves : + +C, - B, +C - B +c - b +c' - b' + +The parser recognizes each additional comma as meaning "going down +an extra octave", giving + +C,, - B,, +C,,, - B,,, +and so on. + +Likewise, each additional prime symbols s interpreted as "go up an extra +octave" : + +c'' - b'' +c''' - b''' +and so on. + +---------------------------------------------------------------------- + +abc2midi +-------- +abc2midi consists of the following C source files: + +parseabc.c - parses the input text and calls a routine for + every parsed element encountered. +parser2.c - performs some additional parsing that may not be + required. +store.c - builds an internal representation of the abc tune. +genmidi.c - uses the internal representation to generate + the MIDI file, using calls to MIDI-specific routines + in midifile.c +queues.c - library of routines for handling 'queues', a data + structure used internally by genmidi.c +midifile.c - Thompson and Czeisperger's public domain library of + MIDI file manipulation routines. + +In the first phase of parsing, the abc file is read and when, say, a note +is encountered, the routine event_note() is called. The code for event_note +is in the file store.c. Encountering an X in the abc generally causes a +routine called event_X() to be called. abc2midi builds up an internal +representation of the tune. At the end of the abc tune, a little bit of +processing is done on the internal representation before the routine +writetrack() is called to actually write out the MIDI file. If there are +repeats in the music, something that appears only once in the abc may be +invoked twice by writetrack(). + +The internal representation uses the arrays feature[], pitch[], num[], +and denom[]. feature[] holds a description of an object while the other +arrays hold data relating to the object. The list of possible features +can be found in the file abc.h . The main features are NOTE, a note of +specified duration, REST, a pause of specified duration and TNOTE, a +note of specified duration with no interval between when it starts and +when the next item starts. This provides a simple way of representing +chords. Ties, broken rhythm signs and grace note brackets are all +deal with before writetrack() is called. + +To add your own special features, you could define a new feature type. +However, an easier option is to use the %%MIDI format. If the parser +encounters "%%MIDI command", where command is not recognized by the +routine event_specific(), the string following %%MIDI is stored away +and passed to the routine dodeferred() by writetrack() when the MIDI +file is being written. +---------------------------------------------------------------------- +abc2abc +------- +abc2abc shares the parser with abc2midi, but instead of storing the +abc code in an internal format, it is written almost straight out +again. The components of abc2abc are: + +parseabc.c - parser +toabc.c - generates output abc. +midifile.c - public domain MIDI library. + +---------------------------------------------------------------------- +YAPS +---- + +YAPS is written mainly using ANSI C style function headers and +compiled and tested using DJGPP (DOS/Windows port of gcc). + +The code is composed of the following files: + +parseabc.c - reads through the abc text file. When it recognizes an abc +"unit" it calls a routine such as event_note() or event_key(). + +yapstree.c - creates a data structure to represent a tune. +Generally, I have tried to use as small a number of passes through the +data structure as possible. This means that things like applying a +broken rhythm symbol > is done as the notes are read in, rather than +using a second pass. This results in a lot of variables being needed in +'struct voice' to keep track of what is going on as we read in the +current symbols. Different sets of these variables are used on different +passes through the data. + +drawtune.c - responsible for creating the PostScript file. When a whole +tune has been read in, this calculates the size of each individual +element, works out spacing within each line, decides how to place the beam +for a group of beamed notes, then finally generates the PostScript for +the tune. + +position.c - called by drawtune.c. This set of routines is responsible +for spacing each line correctly. Where the input abc is multi-voice, +elements played at the same time but in different voices are aligned. + +pslib.c - a single routine to print out the entire library of PostScript +functions used by yaps. + +debug.c - routines to print to screen the contents of a tune data +structure. + +abc.h - header file defining abc element types. + +structs.h - header file defining the data structures used by the program. +The voice structure holds a lot of cuurent context information, used by +the program as it does a pass through the voice. + +sizes.h - header file containing macros to define sizes in points for all +the graphic elements. + +Dynamic Memory Management +------------------------- +abc2midi uses a system of re-sizable arrays in order to handle arbitrary +size input. This scheme was a natural way to adapt the original fixed size +arrays, and is not as flexible as it might be. Yaps instead uses linked +lists. There is a tune data structure containing a linked list of voices +and the notes and other elements are stored in a linked list in each tune. +Some music elements contain their own linked lists; for example a note +may have a linked list of lyric syllables. Adding a new data item to an +element (e.g. a note) involves the following : + +1. find 'struct note' in structs.h and add the element. +2. Initialize it in newnote(). +3. If it is a pointer to a new data structure, make sure the new data + structure is de-allocated in freevoice(). + +---------------------------------------------------------------------- +The abc parser +-------------- +The parser (parseabc.c) has been written in such a way that it forms +an independent unit which must be linked with routines to handle +parsed units. This is very similar to the way that the +midifilelib utilities work. + +The abc is parsed line by line. Each line may be + +* A comment +* A package-specific command +* A field (which may have a trailing comment) +* A blank line +* A TeX command + +Having detected one of these, the parser calls an appropriate +routine. If it is none of these, then within the tune body it is + +* A line of music (which may have a trailing comment). + +Which is parsed and individual elements recognized. Outside the tune +body it is + +* A line of arbitrary text. + +and an appropriate routine is called. + +Routines called by the parser +----------------------------- +These may be a bit out of date - look in the file parseabc.c for the actual +interfaces. + +event_init(argc, argv, filename) +int argc; +char* argv[]; +char** filename; +- first routine called by the parser. Expects filename to be the name of the + abc file to parse on return. + +event_text(s) +char *s; +- called whenever a line of text is encountered. + +event_tex(s) +char *s; +- called whenever a TeX command is encountered. + +event_linebreak() +- called whenever a newline character is encountered. + +event_blankline() +- called whenever a blank line is encountered. + +event_eof() +- called when the end of file is reached. + +event_error(s) +char *s; +- called whenever an error condition is detected. Errors are + generally not fatal within the parser. + +event_warning(s) +char *s; +- called whenever a condition which is likely to be an error is + detected. + +event_comment(s) +char *s; +- called whenever a comment is encountered. + +The following are calls are invoked by fields in the abc : + +event_specific(package, s) +char *package, *s; +- recognizes %%package s + +event_length(n) +int n; +- recognizes L: + +event_refno(n) +int n; +- recognizes X: + +event_tempo(n, a, b, rel) +int n, a, b; +int relative; +- recognizes Q: + +event_timesig(n, m) +int n, m; +- recognizes M: + +event_key(sharps, s, minor) +int sharps; +char *s; +int minor; +- recognizes K: + +event_part(s) +char* s; +- recognizes P: + +When any other field is encountered in the abc : + +event_field(k, f) +char k; +char *f; + +If a line of music is encountered, the elements of that line each +trigger a call to one of the following events, provided that parsing +of music lines has been enabled : + +event_graceon() + +event_graceoff() + +event_rep1() + +event_rep2() + +event_slur(t) +int t; + +event_tie() + +event_rest(n,m) +int n, m; + +event_bar(type) +int type; + +event_space() + +event_lineend(ch, n) +char ch; +int n; + +event_broken(type, mult) +int type, n; + +event_tuple(p, q, r) +int p, q, r; +- general tuple: q and r are zero if not present + +event_chord() +- called whenever + is encountered. + +event_chordon() +- called whenever [ is encountered. + +event_chordoff() +- called whenever ] is encountered. + +event_gchord(s) +char* s; + +event_reserved(p) +char p; + +event_note(roll, staccato, updown, accidental, mult, note, octave, n, m) +int roll, staccato, mult; +char updown, accidental, note; +int octave, n, m; + +In addition, there are 2 other routines : + +int getline() - returns the line currently being parsed + +parseron() - enable parsing of music lines. + +parseroff() - disable parsing of music lines. + diff --git a/doc/programming/cvs/Entries b/doc/programming/cvs/Entries new file mode 100644 index 0000000..4255b04 --- /dev/null +++ b/doc/programming/cvs/Entries @@ -0,0 +1,6 @@ +/abc2midi.txt/1.1.1.1/Thu Sep 28 18:17:04 2006// +/coding.txt/1.1.1.1/Thu Sep 28 18:17:04 2006// +/midi2abc.txt/1.1.1.1/Thu Sep 28 18:17:04 2006// +/split.abc/1.1.1.1/Thu Sep 28 18:17:04 2006// +/yaps.txt/1.1.1.1/Thu Sep 28 18:17:04 2006// +D diff --git a/doc/programming/cvs/Repository b/doc/programming/cvs/Repository new file mode 100644 index 0000000..f07bcdc --- /dev/null +++ b/doc/programming/cvs/Repository @@ -0,0 +1 @@ +abcmidi/doc/programming diff --git a/doc/programming/cvs/Root b/doc/programming/cvs/Root new file mode 100644 index 0000000..2cc522d --- /dev/null +++ b/doc/programming/cvs/Root @@ -0,0 +1 @@ +/home/seymour/CVSREPOS diff --git a/doc/programming/midi2abc.txt b/doc/programming/midi2abc.txt new file mode 100644 index 0000000..f1eef2f --- /dev/null +++ b/doc/programming/midi2abc.txt @@ -0,0 +1,227 @@ +Notes on the midi2abc code +-------------------------- +written by Seymour Shlien + + +midi2abc.txt - last updated December 5 1999 + + +Introduction + +Midi2abc is a program for converting a midi files into an abc file. + +A midi file merely consists of a list of commands to turn on +and off a set of voices at specific times. The time units are +expressed in pulses where the number of pulses per second can +be deduced from the information in the midi file. Pitch is +specified in semitone units ranging from 0 to 127 where middle C +is assigned a value of 60. + +There are two types of midi in general use. In type 0, all the +voices are interleaved in time in one track. Each voice goes +to a specific channel which is mapped to a particular musical +instrument or program. There is a limit of 16 voices since only +4 bits are assigned to indicate the channel number. In type 2, +the voices are placed in separate tracks. This format allows +handling more than 16 voices. + +In order to create an abc file, midi2abc must determine the +length of a musical unit (for example an eighth note) in terms +of midi pulses, determine the key signature, and, finally map the +midi commands into musical notes. + +Though the midi file specifies the number of pulses per quarter note +(PPQN) in the Mthd header chunk, this is not necessarily an +accurate indication. It is primarily used together with the tempo +indication to determine the number of pulses per second. Unless +the midi file was created by a computer program, the actual length +of a quarter note in midi pulses can depart from the nominal indication. +Midi2abc tries to determine the length using its own heuristic +algorithm. + +The sources of the program are contained in two files: midi2abc.c and +midifile.c. This document does not try to describe completely how +this program works, but is more of a general road map to the software. + + +Algorithmic Description + +The conversion is done in multiple passes. In the first pass, the +midi file is read and an internal representation of the file is +created and stored in global dynamic memory. In each subsequent pass, +other information is added to the internal representation and finally +it is written to the output abc file. + +After parsing the input run parameters and performing various +initializations, the main program calls the procedure mfread +which is found in the midifile.c module. Mfread parses the different +midi components of the file and calls the appropriate functions +midi2abc to process these components. These functions begin with +the txt_ prefix, some of which are listed here. + +txt_header midi header chunk +txt_trackstart start of midi track +txt_trackend end of midi track +txt_noteon note on channel command +txt_noteoff note off channel command +txt_program midi program definition or change +txt_metatext midi textual information +txt_keysig midi key signature indication +txt_tempo midi tempo indication + +Many other functions such as txt_pressure and txt_parameter +corresponding to other midi commands, do nothing here. + +These functions build up an internal representation of the midi file +in a global structure referenced through the track[64] structure. +Up to 64 midi tracks can be stored in the internal representation. +Each track structure (atrack structure) contains single and double +linked lists of notes or text strings which are described below. +In addition there are other linked lists (referenced by playinghead +and chordhead), used for keeping track of notes currently playing +and musical chords. + +Each note is represented by an anote structure which stores various +parameters of the note. The anote structure is allocated dynamically +as the midi file is read. The first four entries of the structure +are filled in while the structures are being created by mfread. +These are entries are listed below. + +anote.pitch pitch in midi units +anote.chan midi channel number +anote.vel midi velocity (corresponding to loudness) +anote.time time in midi pulses. + +The other entries in the anote structure are determined in later passes. +The anote structures are linked together into a a listx structure which +is included in the atrack structure. The head and tail of the list are +contained in this structure to facilitate the construction of this list. +In addition there is tlistx structure for storing all the textual +information (for example words in a Karaoke midi file) which may be found +in the track. + +There is a doubly linked list structure of anotes (dlistx, +*playinghead) which is used as a work space for matching the note off +command with the corresponding note on command. This is needed in order +to determine the length of time the note was turned on (called anote.tplay). + +The internal representation is mainly constructed by the important +functions txt_noteon and txt_noteoff called by mfread. These functions +in turn call the functions addnote and notestop. The midi file contains +separate commands for turning a note on or off so that in order to +determine the length of time that a note has been on, it is necessary to +match a note-off command with the corresponding note-on command. +Every time a note is turned on, it is also added to the playhead (tail) +structure. The procedure notestop finds the corresponding note-on +command in the playhead structure, removes it, and records the +duration of the note which was turned on. + +At the end of the first pass, the number of tracks is counted and each +track is processed by the function postprocess which computes the entry +anote.dtnext for each anote structure. This entry contains the time +interval between the current and the next note in the linked list of +notes. + +The abc time unit length is either 1/8 or 1/16 depending on the time +signature. A time signature of 4/4 is assumed unless it is specified +by the run time parameters (-m or -xm). (If -xm is specified, then the +program uses the time signature given by the midi meta command if it +exists in the file.) + +The next step involves the quantization of the midi time units +expressed in pulse counts into abc time units. It is first necessary +to estimate the length of an abc time unit in terms of midi time +units. This either is estimated using a heuristic algorithm, +guesslength, or is determined from the run time parameters (-Q or -b). + +The function guesslength makes an initial guess by dividing the +total number of pulse counts in the track by the total number +of notes. It then tries 100 different lengths in the neighbourhood +of this initial guess and chooses the one which leads to the smallest +quantization error. The quantization error is determined by the function +quantizer which keeps track of the total deviation of the time +a note starts (in pulse counts) from the expected time the note +starts assuming the standard musical intervals. This deviation +can either drift positively or negatively with time. The total +error is determined by summing the absolute values of these +deviations for each bar. + +Once the unit length has been determined, all the notes in all +tracks are quantized by the function quantizer. This function +assigns values to the anote entries, anote.xnum, anote.playnum +and anote.denom. + +anote.xnum interval between the current note and following note + also called the gap. +anote.playnum note duration. +anote.denom always has the value of 2. + +A musical part does not necessarily begin at the start of a bar line, +but may have some leading notes. This is called anacrusis. +There are two methods to estimate the anacrusis. The function findana +searches for the first upbeat by examining the velocities (loudness) of +the notes. The function guessana, chooses the anacrusis which minimizes +the number of tied notes across a bar line which is determined by the +function testtrack. + +At this point the key signature of the tune must be determined. +The procedure findkey computes the frequency distribution of all the +notes in the piece and stores it in the local array n[]. The key +signature is determined by transposing the distribution by each +of the 12 keys and counting the number of sharp or flat notes. The +key signature is determined from the key which leads to the minimum +number of black keys on the piano. The mode of the scale (major, +minor, Dorian, etc.) is determined by looking at the final note of +the piece. + +Once the key signature is determined, the assumed flats or sharps +are determined by the procedure setupkey. The program is now ready +for its final pass where the musical parts (or voices) are printed +in the output abc file. + +The procedure printtrack processes the internal representation +of each midi track producing a separate voice for each track. +In order to handle chords which may be present in an individual +track, printtrack maintains a structure referenced by chordhead +by calling the support functions addchord(), advancechord(), +removechord() and printchord(). These functions handle single +notes as well as chords. Another function, dospecial(), handles +the triplets and broken rhythms (eg. dotted notes followed by +half sized note or vice versa) whenever they are detected. The +printchord() function is supported by the functions printfraction() +and printpitch(). + +After the track is printed, the memory allocated to the structures +for the internal representation of the tracks is freed. + +The option -splitvoice was introduced to handle polyphonic chords. +Without this option polyphonic chords appear in the abc file +like this. + +[DF-A-][FA-]Az| + +this will be represented by three voices + +V: split1A +D2 z6| +V: split1B +F4 z4| +V: split1C +A6 z2| + +This option is implemented by the function printtrack_split_voice(). +The function label_split_voices() is called to assign all the notes +in the track to their split voice. This assignment of each note is +stored in note->splitnum. This is a complex function since it needs +to try to match the onset and end of each note in the chord. If +it is unable to do this for a particular note, then the note is +assigned to a different split. At the end, nsplits were created. +The notes in each split are printed in a separate voice by the +function printtrack_split(). The function printtrack_split(splitnumber) +was derived from printtrack(); however, it only processes the +notes belonging to a particular splitnumber. + +It was necessary to determine and store the offset of the first +note in each split using the function set_first_gaps() prior +to calling printtrack_split(). + diff --git a/doc/programming/split.abc b/doc/programming/split.abc new file mode 100644 index 0000000..e6114b0 --- /dev/null +++ b/doc/programming/split.abc @@ -0,0 +1,131 @@ +X:1 +T: test split file 1 +M: 2/4 +L: 1/4 +K: G +G & E & C|D|GA & EF| + + +X:2 +T: test split file 2 +M: 1/4 +L: 1/4 +K: G +%%MIDI program 20 +D|G & E|C|F|G & E| + +X:3 +T: test split file 3 +M: 2/4 +L: 1/8 +Q: 50 +K: D +CD |EF AB & CD FG| G2 | BD D2 & GB B2| + +X:4 +T: test split file 4 +M: 1/4 +L: 1/4 +K: G +V:1 +|:G |[1 D & B:| +V:2 +|:g |[1 d & b:| +V:1 +[2 F & A| +V:2 +[2 f & a| + +X:5 +T: test split file 5 +M: 1/4 +L: 1/4 +K: G +G & E |D| + +X:6 +T: test split file 6 +M: 1/4 +L: 1/4 +K: G +D|G & E| + +X:7 +T: test split file 7 +M: 1/4 +L: 1/4 +K: G +D|G & E & C|F| + +X:8 +T: test split file 8 +M: 1/4 +L: 1/4 +K: G +G & E & C|D| + +X:9 +T: test split file 9 +M: 1/4 +L: 1/4 +K: G +G & E & C|D|F & A| + +X:10 +T: test split file 10 +M: 1/4 +L: 1/4 +K: G +V:1 +|:G |[1 D & B +V:2 +|:g |[1 d & b +V:1 +:|[2 F & A| +V:2 +:|[2 f & a| + +X:11 +T: test split file 11 +M: 1/4 +L: 1/4 +K: G +|:G & E :|D|F & A| + +X:12 +T: test split file 12 +M: 1/4 +L: 1/4 +K: G +|:G & E |D:|F & A| + +X:13 +T: test split file 13 +M: 1/4 +L: 1/4 +K: G +|:G & E |[1 D:|[2 F & A| + +X:14 +T: test split file 14 +M: 1/4 +L: 1/4 +K: G +|:G |[1 D & B:|[2 F & A| + +X:15 +T: splits with octave=1 +M: 4/4 +L: 1/4 +K: G octave=1 +G A B C & E F G A| + + +X:16 +T: test split file 13 +M: 1/4 +L: 1/4 +K: G +|:G & E |1 D:|2 F & A| + + diff --git a/doc/programming/yaps.txt b/doc/programming/yaps.txt new file mode 100644 index 0000000..6d18e08 --- /dev/null +++ b/doc/programming/yaps.txt @@ -0,0 +1,134 @@ +Some Notes on the yaps Code +------------------------------------------------------------- + written by Seymour Shlien November 21 2004 + +This file gives an algorithmic description of the +yaps program which converts an abc file to a PostScript file. + +The source consists of almost 10000 lines of C in the following +files. + +parseabc.c is the front end which scans the abc file and invokes + the appropriate event handler for each element it encounters + (eg. bar lines, notes, chords etc.) It happens to be the + front end for other programs such as abc2midi, and + abc2abc. More details are given in abc2midi.txt. + +yapstree.c contains all the event handlers called by the parser. + It produces a complex data structure called tune which + references many other structures. When the parser completes + processing the tune, event_blankline or event_eof calls + printtune (in drawtree.c) which processes the tune structure + producing a PostScript file. Unlike abc2midi, most of the + layout including the detailed beaming is done in the first + pass during the parsing stage. The information in this + structure is then processed by drawtune.c in two more + passes. An overview of these structures is provided here. + More details on the tune structure is provided in this + file. + +drawtune.c contains the function printtune which turns the tune + structure into an actual PostScript file. This is done + in two passes. Before writing the PostScript file it + is necessary to determine the boundingbox of the output + image since this information is recorded in the header + of the output file. This is determined in the first pass + where functions monospace() or spacevoices() (in position.c) + are called. During this pass the pixel positions + of each object are recorded in the associated structures. + In the second pass, the actual PostScript file is written. + The function calls printlib() (in pslib.c) outputs + all the PostScript boiler plate macro definitions required + by yaps. The information in the tune structure is used + to output the music notation in a PostScript file. + + +position.c contains functions for determining the amount of space + that is required for the different music objects drawn + in the PostScript file. + +parser2.c contains additional parsing functions missing in parseabc. + They handle more recent features added to the abcmidi package. + +pslib.c Definition of new PostScript commands (eg. notes, clefs, + stems, tails, ...) which are copied to the PostScript + file. + +debug.c Functions which support the -d option in yaps. It prints + some of the contents of the internal tune structure. + + +Data Structures +--------------- + +The data structures are defined in the include file structs.h. + +The top level structure, tune is instantiated by init_tune which +is called by event_init or event_refno. It stores all the +information in the abc field commands (X: ,M:, L:, C:, O: and etc.). +It contains a pointer to the voice structure and a list of voice +pointers where most of the body information is recorded. + +The voice structure is instantiated by the function newvoice +which is called by setvoice(n) whenever the voice context +switches in the abc file. Setvoice performs the voice switching +(which occurs in voice interleaved files) and either creates +a new voice or finds the matching voice structure already existing. +The voice structure contains the feature structure which +is somewhat similar in function to the one defined in store.c +(for abc2midi). + +The feature structure encodes all the detailed information in +the body, using the same typedef enum featuretype defined +in abc.h. Unlike store.c there is no num and denom arrays. Instead +the feature struct contains a void* pointer called item which +can point to anything and where additional information can be +stored. If the feature type is a NOTE then a "note" struct +is created which records a lot of detailed information related +to the placement and visual representation of the note. They +include: +tail_type which specifies whether the note appears in + isolation or is part of a beamed group +base_exp whole, half, quarter, ... notes +dots how many dots follow +stemlength, stemup, fliphead, pitch, octave, accidentals, accents,... +(see struct.h) +Most of the information except actual positioning is determined +by functions such as count_dots and beamitem in yapstree.c. +You can view this information by running yaps.exe with the -d +run time parameter. + +The handling of the note positioning is quite complex as +outlined below. It is therefore not easy to implement the +splitvoice feature into yaps. Here is a description. + +The positioning of notes is done by the function +spacemultiline() which calls advance() unless one is printing +the voices separately. The positioning is done on all the voices +at the same time to ensure that they are lined up properly. +Spacemultiline accesses all the active voices using the functions +firstitem() and nextitem() which are used for handling any lists +of objects. Each voice maintains its own pointer to the current +feature being scanned (v->place). Each voice also maintains its +own pointer to the relative time of the note being scanned +in the variable v->time. (v->time contains both a numerator +and denominator.) The advance() function updates v->place, +v->time and interprets the voice features determining the +amount of space that is needed to plot the next object (itemspace) +and the number of plotable objects (items). The position to +plot the next object (x) is maintained by spacemultiline and +passed to advance. Advance() updates v->place->x with the position +to plot the object based on its width. Spacemultiline() +maintains a mastertime variable for maintaining synchrony +between all voices. + +At least two passes are made through the voice features. +In the first pass provisional positions are computed for the +notes. The amount of space left over in the music lines is +computed and is used to determine the internote gaps. +In the second pass, the notes are repositioned to use up +the entire space in the staff line. + +Spacemultiline is called for each staff line whose end is +signaled by a linefeed feature in the voice. + diff --git a/doc/readme.txt b/doc/readme.txt new file mode 100644 index 0000000..903c306 --- /dev/null +++ b/doc/readme.txt @@ -0,0 +1,546 @@ +abcMIDI : abc <-> MIDI conversion utilities + +midi2abc version 3.46 June 22 2020 +abc2midi version 4.38 July 05 2020 +abc2abc version 2.08 June 04 2020 +yaps version 1.77 June 04 2020 +abcmatch version 1.73 June 04 2020 +midicopy version 1.36 June 04 2019 + +24th January 2002 + +Copyright James Allwright +J.R.Allwright@westminster.ac.uk +University of Westminster, +London, UK + +February 2020 + +Seymour Shlien +Ottawa, Canada +fy733@ncf.ca + +This is free software. You may copy and re-distribute it under the terms of +the GNU General Public License version 2 or later, which is available from +the Free Software Foundation (and elsewhere). + +This package is to be found on the web at + +http://abc.sourceforge.net/abcMIDI/ +(The latest versions for the time being is found on + ifdo.ca/~seymour/runabc/top.html.) + +Note, if you have difficulty compiling the package because you do not have +snprintf see the note in doc/CHANGES dated January 08 2005 (and also +December 17 2004). + +These programs make use of the 'midifilelib' public domain MIDI file utilities, +which was originally available from + +http://www.harmony-central.com/MIDI/midifilelib.tar.gz + +If you have the source distribution and intend to re-compile the code, +read the file coding.txt. +--------------------------------------------------------------------- +midi2abc - program to convert MIDI format files to abc notation. + +This program takes a MIDI format file and converts it to something as close +as possible to abc text format. The user then has to add text fields not +present in the MIDI header and possibly tidy up the abc note output. + +Features : + +* The key is chosen so as to minimize the number of accidentals. +Alternatively, the user can specify the key numerically (a positive number +is the number of sharps, a negative number is minus the number of flats). +* Note length can be set by specifying the total number of bars or the +tempo of the piece. Alternatively the note length can be read from the file. +However, by default it is deduced in a heuristic manner from the inter-note +distances. This means that you do not have to use the MIDI clock as a +metronome when playing in a tune from a keyboard. +* Barlines are automatically inserted. The user specifies the number of +measures in the anacrusis before the first barline and the time signature. +* The program can guess how many beats there should be in the anacrusis, +either by looking for the first strong note or minimizing the number of +notes split by a tie across a barline. +* Where a note extends beyond a bar break, it is split into two tied notes. +* The output has 4 bars per line. +* Enough accidental signs are put in the music to ensure that no pitch +errors occur if a barline is added or deleted. +* The program attempts to group notes sensibly in each bar. +* Triplets and broken rhythm (a>b) are supported. +* Chords are identified. +* Text information from the original MIDI file is included as comments. +* The -c option can be used to select only 1 MIDI channel. Events on +other channels are ignored. + +What midi2abc does not do : + +* Supply tune title, composer or any other field apart from X: , K:, Q:, M: +and L: - these must be added by hand afterwards, though they may have been +included in the text of the MIDI file. +* Support duplets, quadruplets, other esoteric features. +* Support mid-tune key or meter changes. +* Deduce repeats. The output is just the notes in the input file. +* Recover an abc tune as supplied to abc2midi. However, if you want to +do this, "midi2abc -xa -f file.mid" comes close. + +midi2abc + usage : +midi2abc + -a + -xa extract anacrusis from file (find first strong note) + -ga guess anacrusis (minimize ties across bars) + -gk guess key signature by minimizing accidentals + -gu guess the number of midi pulses per note from note + duration statistics in the MIDI file + -m