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 preceeded 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 preceeded 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 key 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 <pnum) || */, and triplets are now detected more consistently. This could have some impact somewhere else, but I do not know at this time. November 11 2003 More tuning for multiple key signatures (see October 26 2003). In printtrack, I moved the call to handletext after active_keysig, active_asig, and active_keysig were set. This fixed a problem in single track files, where the same key signature was printed twice. In the main function, header_keysig is set to keysig only if gotkeysig is equal to zero. Otherwise, header_keysig can be changed to the wrong (last value of keysig) value if multiple key signatures exist. November 12 2003 Midi2abc sometimes places a backslash line continuation after the last bar or note on a track. This confuses yaps. A check for remaining data in the track is made prior to sending a backslash. December 7 2003 Abcmidi does not handle triplets containing chords correctly. In the following example. X: 1 T: triplet chords M: 2/4 L: 1/8 K: C (3[CEG] [DFA] [ceg] G2| The second and third notes in the third chord [ceg] are not adjusted for a triplet. The problem occurs in event_note, in store.c. The function decrements the tuplecount counter for the first note in each chord. Therefore when it handles the last chord, tuplecount is already zero when it encounters notes e and g. The fix is not to decrement tuplecount inside a chord in event_note and event_rest. Instead tuplecount is decremented in the function event_chordoff. I am grateful to Jim Russell who identified this bug and found the fix. January 3 2004 Yaps does not handle triplets containing chords correctly. In the following example, X: 1 T: triplet chords M: 2/4 L: 1/8 K: C (3 [CEG] [DFA] [ceg] (3[CEG] [DFA] [ceg]|\ (3 [CEG] [DFA] [ceg] (3[CEG] [DFA] [ceg]|\ (3 [CEG] [DFA] [ceg] (3[CEG] [DFA] [ceg]| yaps fails to group the chords into triplets. Analysis: in printvoiceline (in drawtune.c) notes and chordnotes are distinguished and are processed differently. For notes, the function contains extra code to check for tuples and to process them; however, this is missing for chordnotes. Fix: the code for treating tuples (in the event that they may be present) was introduced after a chordoff signal was detected in printvoiceline. January 17 2004 Bagpipe music does not sound right without the continuous drone. It would be useful to introduce new MIDI extensions (similar to drum and gchord) for producing a drone accompaniment. The drone accompaniment would be placed in a separate track and turned on or off using the commands %%MIDI droneon and %%MIDI droneoff It is desirable that the new code supporting the drone extension would follow the same style for producing drum and gchord track. Since that code was quite convoluted a little description is appropriate here. Drum and gchord tracks are produced by the functions dogchord() and dodrums() which are defined in the file genmidi.c. These functions are called for each beat by the function progress_sequence(beatnumber). It is not obvious where progress_sequence is called so this is described here. Writetrack is called separately for creating the drum and gchord tracks. These tracks are not represented as a separate voices in the feature structure array. Instead there are special flags GCHORDON, GCHORDOFF, DRUMON and DRUMOFF which signal that the gchord accompaniment or drum accompaniment should be started (or stopped) at this point in the music. I therefore introduced two new feature types DRUMON and DRUMOFF (see abc.h). For each track, writetrack rescans the entire feature structure array. If the track is a gchordvoice or a drumvoice, the noteson flag is not set and case NOTE: is treated differently. Noteon and add2Q are not called to create "MIDI on" and "MIDI off" commands; however the delay() and addunits() are still called to keep track of the beat when the note is note inside a chord. (A chord is represented in an abc file as several notes inside square brackets eg. [CEG]). Delay() calls timestep() and its associated functions which can be found in the file queues.c. The function timestep() keeps track of the beat and calls progress_sequence() which calls dogchords or dodrums as mentioned above. The handling of drone does not require all this complexity since we do not need to keep track of the beat. Therefore, it is not necessary to place the drone controls in the progress_sequence() function. Instead it is sufficient to just turn it on or off using new functions start_drone() and stop_drone() which follow the switch case: conditions DRONEON and DRONEOFF. However, like the drum track and the gchord track, we want the NOTE: cases to only generate timestep() calls so we are able to determine the length (in MIDI time units) of the drone note. Fortunately, timestep() also updates the global variables tracklen and delta_time which are used by the functions start_drone and stop_drone(). Now there are a few details connecting all of this together. New global variables, dronevoice and dronetrack were introduced into the file store.c. In the function event_specific() (which handles the %%MIDI commands in the abc file), new key words, droneon and droneoff are introduced. They insert the DRONEON and DRONEOFF features into the feature array and set the dronevoice flag. In the function finishfile() (also in store.c), a dronetrack number is assigned if dronevoice has been set. The new global variables dronetrack and dronevoice in store.c are linked to genmidi.c as extern int(s). A new boolean int droneon is also added. A new struct, dronestruct is introduced. This structure contains the drone characteristics (eg. MIDI instrument, pitch, velocity, channel) for the drone. Two tones may be defined, customarily an octave apart and typically the note A in the lower octaves. In starttrack(), the drone struct is initialized to default values if the flag droneon is set and findchannel() assigns a midi channel for the drone track.. February 7 2004 Introduced a new %%MIDI command %%MIDI drone val1 val2 val3 val4 val5 It configures the drone. val1 to val5 should be numbers between 1 and 127. val1 specifies the instrument (MIDI program number) for the drone; val2 and val3 specify the MIDI pitches for the two drone notes which are played as a chord; and val4 and val5 specify the MIDI velocities for the two drone notes (played as a chord). A value of zero means do not change the setting for the current parameter. By default the drone parameters are drone.prog = 70 (bassoon) drone.pitch1 = 45 (A,) drone.pitch2 = 33 (A,,) drone.vel1 = 80; drone.vel2 = 80; If you specify a global transpose, the drone pitchws will also be transposed. The new code was added into the function dodeferred(s) in the file genmidi.c Modified the function parse_tempo in parseabc.c so that the syntax Q: 132 is equivalent to Q: 1/4=132 This change applies to abc2midi, yaps and abc2abc. Fixed a bug I had introduced in the function stop_drone (genmidi.c). The second call to midi_noteoff should have a delta of zero. 22 February 2004 The -u option in midi2abc.exe does not work. Problem: despite the fact that xunit was set by the user, midi2abc changes it when it encounters a time signature MIDI command. Fix: a new parameter xunit_set was introduced and is set to 1 if the user sets xunit using the -u option. The function setup_timesig does not alter xunit if xnit_set has been set to one. 7 March 2004 abc2abc incompatibility issue with abc2mps. In the event that voices are indicated by symbols rather than numerals, abc2abc converted them back to numerals so that a file X: 1 T: abc2mps incompatibility M: 2/4 L: 1/8 K: G %%staves [S A T] V: S cdcd|egeg| cdcd|egeg| cdcd|egeg| V: A AGAG|GBGB| AGAG|GBGB| AGAG|GBGB| V: T A,CA,C|FDFD| A,CA,C|FDFD| A,CA,C|FDFD| becomes X: 1 T: abc2mps incompatibility M: 2/4 L: 1/8 K: G %%staves [S A T] V: 1 cdcd|egeg| cdcd|egeg| cdcd|egeg| V: 2 AGAG|GBGB| AGAG|GBGB| AGAG|GBGB| V: 3 A,CA,C|FDFD| A,CA,C|FDFD| A,CA,C|FDFD| This causes a problem for abc2mps. Abc2abc was modified so that it will preserve the symbolic codes for the voices. External links extern int voicecodes; extern char voicecode[16][32]; were introduced into toabc.c and event_voice now checks voicecodes before emitting the voice command. Beware, the fix may not work correctly if there is a mixture of numeric and symbolic codes for voices. If you use symbols for voices, use them for all voices. 20 March 2004 Midi2abc fails to extract chords when the -sr (swallow short rests) option is selected. The problem occurs in the function quantize() in the file midi2abc. When the -sr option is specified, the note's length is determined more by its inter onset time interval rather (time between onset times of two adjacent notes) rather than the time between note off and note on. In the event of several notes played at the same time, the inter onset times will be zero for some notes. Because quantize() failed to test for this condition, the function assigned a note length of zero to those notes and they do not appear in the chord. The problem was fixed by also checking for zero inter onset time when the -sr option is active. Added a bagpipe tune to demo.abc to illustrate the use of the %%MIDI drone commands. 25 March 2004 When transposing guitar chords, abc2abc converts double accidentals to the note above or below. For example when abc2abc raises the guitar chord "Db7" in the C scale to "Ebb7" in the Db scale, it converts "Ebb7" to "D7". This is strictly not correct. Fix: event_handle_gchord in toabc.c was modified to not convert the double flat or sharp to the next pitch degree by default. A new option -nda (for no double accidentals) was introduced which preserves the old behaviour of abc2abc. (Note the -nda option is only active when you are transposing to another key.) This change involved introducing a new global variable nodouble_accidentals. See comments for 11 April 2004 for more details. (I am grateful to Atte Jensen for alerting me to this problem as well as the following three problems.) 27 March 2004 abc2midi fails to tie notes correctly when the tie crosses bar lines. In the following example X:1 T: Tie M: 2/4 L: 1/4 K: C E ^F-|F F | abc2midi reports an error Error in line 6: Could not find note to be tied. The problem is that F was sharpened by an accidental, but since the accidental did not apply to the next bar, the next F appears as a natural and the function dotie() fails to match the note with F#. As a result, the two notes are not tied. One could place an accidental on the second F, but strictly this is not musicly correct. "An accidental is valid for the rest of the bar (only the octave where it's written). Tied notes carry the accidental to the next bar until the note that ends the tie is released." The fix: store.c joins the tied notes in a second pass after all the notes have been scanned and parsed. Unfortunately, at this point there is no information that indicates whether the pitch of the note was modified by one or more accidentals. A new array pitchline[] was introduced to store the original pitch of the note before any accidentals are applied. The contents of the array are maintained by event_note. The function dotie now compares pitchline[place] with pitchline[tienote] rather than pitch[place] with pitch[tienote]. When it establishes a tie, it ensures pitch[place] = pitch[tienote]. 27 March 2004 abc2abc.exe fails to transfer the clef indication, clef=F to the output abc file. For example, V: 1 clef=F becomes V: 1 Analysis: the function isclef() in parseabc.c recognizes only the following clef indications: bass, treble, treble+8, treble-8, baritone, tenor, tenor-8, alto, mezzo, soprano. When it encounters clef=F, it fails to recognize F and assumes there is no proper clef indication. Since K: G treble+8 is interpreted as K: G clef=treble+8 the function isclef() must have a fixed repertoire. Fix: (1) indications clef= F or clef=f have been added to the function isclef. (2) Since there may be other indications that have not been built into isclef and it is desirable that abc2abc copies these indications, I have added a new flag, int strict, to the function isclef. The flag strict is 1 when no clef= was found and isclef is interpreting the given word. The flag strict is 0 when the given word is preceeded by clef=. When strict is 0, the function isclef will assume that the word is something meaningful even though it does not recognize it and pass a warning message. If strict is 1, isclef will not return words that it does not recognize. Unfortunately, this change introduced another conflict. See comments for April 11 2004. April 3 2004 When an abc file is missing a meter M: indication, abc2abc.exe attempts to correct this situation by adding it to the output file. Unfortunately it does not do it correctly as seen in the following example. X:1 T: Missing M: L: 1/8 K: C CDEF GABC| CDEF GABC| output X: 1 T:Missing M: L:1/8 K:CM:4/4 CDEF GABC| CDEF GABC| Analysis: The function event_refno in toabc.c which is called whenever an X: command occurs, initializes barlen.num to zero. The function start_tune() in toabc.c checks whether barlen.num is still zero, which indicates that a M: indication is missing. If it is zero, it calls event_timesig to set it to the default time signature of 4/4. Unfortunately, it places a linebreak after calling event_timesig instead of before. Fix: the function event_linebreak was moved before calling event_timesig. April 11 2004 The patch dealing with transposing guitar chords in toabc.c (refer to March 25 2004 note), did not work correctly so it was necessary to take a different approach. Apparently, the code in event_handle_gchord works correctly for all diatonic guitar chords. The algorithm finds the chord's pitch ignoring all following accidentals using the offset[] table. It adds the transpose interval to the pitch and then shifts it by +1 or -1 in event that the chord is followed by sharp or flat accidental. For nondiatonic chords (i.e. contains notes not present in the key signature), the transpose algorithm yields the correct chord but represents it incorrectly for the key signature. For example, suppose the nondiatonic chord in the C key signature is Dbm which is a degree 2 minor triad. When it is transposed one semitone to the Db key signature, the chord should now be Ebbm. However, event_handle_gchord changes it to Dm chord which has the identical notes but has the wrong representation (it was changed to a degree 1 minor triad). To fix this problem, it was necessary to compute the triad degree in the original key signature and compare it with the degree of the transposed triad in the new key signature. If they are identical, everything is fine. If they are different by one degree, then an adjustment is needed. The degree actually also depends upon the mode of the key signature (major/minor/dorian/lydian ....), however for simplification we shall assume it is the major key signature. (The toabc.c file is not passed the key signature but the number of sharps or flats in the key signature.) The following changes were made. New global variables orig_key_number and new_key_number were introduced which represents the tonic (ignoring accidentals) of the original and new key signature (assuming major scale). They are represented by numbers where A is zero, B is 1, etc. These variables are set by event_key which handles the K: field command. In the function event_handle_gchord, the triad degree (old_triad_number) is computed by subtracting orig_key_number from the key_number. Something similar is done for the transposed triad, yielding new_triad_number. If the degrees are not identical, the tranposed triad is shifted back and a sharp appended or else shifted forward and a flat appended. Otherwise nothing is done. (The correction is disabled if the flag nodouble_accidentals was set by the -nda run time parameter.) April 11 2004 Key signature K:F no longer processed correctly. eg. X:1 T: key signature problem M: 2/4 L: 1/4 K: F G A|B D|F2| This problem occurs in abc2midi, abc2abc and yaps since they all share the same parser. This was caused by introducing F and f as an option in the isclef(..) function in parseabc. (See March 27 2004 report.) As a result the F is first interpreted as a clef indication and ignored as a key indication. Fix: if F or f is used to specify the clef then it must be preceded by clef=. This is not true for other indications like soprano+8. To fix this I inserted the condition strict==0 in the test for F or f in isclef(). April 16 2004 Abc2abc: demoted "No repeat expected" from an error to a warning in toabc.c April 21 2004 Introduced a new gchord code b (both) which produces a fundamental and chord in the same beat. Thus b behaves like a combination of f and c. For example: %%MIDI gchord fbfc the second beat would be the fundamental and chord played together. The new code was introduced in dogchords() and set_gchords() in genmidi.c. April 22 2004 Abc2midi: Guitar chord inversions do not work consistently. For the tune X:1 T: gchords M: 4/4 L: 1/1 K: C "G" z|"G/B" z|"G/D" z| "G/B" specifies the first inversion of the G major guitar chord and "G/D" specifies the second inversion of the G major guitar chord. Running midi2abc on the output midi file we discover that the second inversion was not produced. %"G" G,,z [DB,G,]z G,,z [DB,G,]z| %"G/B" G,,z [GDB,]z G,,z [GDB,]z| %"G/D" G,,z [DB,G,]z G,,z [DB,G,] # second inversion not produced. Inversions are detected by the procedure event_handle_gchords in the file store.c. It passes the inversion flag to genmidi.c through the array num[], which is extracted by writetrack for the GCHORD feature. The function dogchords in genmidi, generates the notes of the gchord. The value of inversion refers to the pitch of the note after the slash relative to the base note of the gchord. One problem was traced to the statements for (j=0; j<chordlen[chordnum]; j++) { if (basepitch + chordnotes[chordnum][j] % 12 == inversion % 12) { in dogchords. Parentheses are required in the if statement so that the modulo 12 acts on the sum of basepitch and chordnotes. Thus the statement was changed to if ((basepitch + chordnotes[chordnum][j]) % 12 == inversion % 12) { The actual inversion (shifting up of a note in a gchord by one octave) is done in the statements which occurs in the last for loop prior to the break. if (inchord) { note = inversion + ((note + 12 - inversion) % 12); }; I could not understand the logic in this statement and found that it does not perform the inversion consistently. I therefore made the following changes to the inversion algorithm. The local variable inchord now stores the position of the lowest note in the inverted chord. Thus for inverted chord G/B, inchord would be 1 because B is at index position 1 in the chord GBE. For G/E inchord would be 2. G/G does not represent an inverted chord so inchord set t0 0 which indicates to do nothing and is consistent with the logic. The last for loop before the break was replaced with. for (j=0; j<chordlen[chordnum]; j++) { note = basepitch + chordnotes[chordnum][j]; if (j < inchord) note += 12; save_note(g_num*len, g_denom, gchord.base + note, gchord.chan, gchord.vel); }; I tested the new code with the file X:1 T: gchords M: 4/4 L: 1/1 K: C "G" z|"G/B" z|"G/D" z| "Am" z|"Am/C" z|"Am/E"z| "Bdim" z|"Bdim/D" z| "Bdim/F" z| The inversions now appear to be done correctly. April 23 2004 Abc2abc does not place linebreaks on comments prior to X: For example for the file % comment 1 % comment 2 X: 1 T: Precomments have no linebreaks M: 4/4 L: 1/1 K: C D|E|F| The ouput is % comment 1% comment 2X: 1 T:Precomments have no linebreaks M:4/4 L:1/1 K:C D|E|F| Analysis: the problem was introduced by the changes I made on 2003 May 4 as described above. Linebreaks were suppressed to prevent the production of many blank lines for abc files with missing reference number (no X: field). This unfortunately introduced another problem which was discovered recently. The X: reference number is absorbed by one of the comments appearing prior. Fix: An event_linebreak is executed after parse_precomment in parseline (parseabc.c) in event that the parsing flag is not set. Hopefully this has no impact on yaps and abc2midi. May 1 2004 A new gchord feature introduced in abc2midi. It is now possible to arpeggiate the guitar chords. New gchord codes g,h,i,j,G,H,I,J were introduced. They reference the individual notes in the guitar chord. g is the lowest note and j is the highest. For example for the G major chord, g references G, h references B and i references D. The upper case letters are the same notes one octave lower. If you specify a gchord, %%MIDI gchord ghighi Then abc2midi would fit the notes GBDGBD in each bar. Same rules for length of notes apply as before. Implementation: All the changes were made in the genmidi.c file. A new global array gchordnotes[] and global variable gchordnotes_size was introduced. The function set_gchords was extended to recognize the new codes hijk. A new function configure_gchord() was created from part of the body of dogchords() dealing with case 'c'. The function loads the gchordnotes array based on the global variables, basepitch,chordnum and inversion. The function is called by writetrack for the GCHORD feature (whenever a guitar chord name is detected). The dogchords() function was modified to process the new gchord codes and to use the gchordnotes[] list. The demo.abc file was extended with another example. May 7 2004 The -Wtraditional flag was removed from the makefile, since it posed some problems with the lastest gcc compiler. The following midi2abc problems were reported by Werner V. Hoersten with suggested fixes. The -m option for setting the time signature in midi2abc.exe causes the program to crash with a floating point exception. (This is a bug that I probably around October 2003.) Analyis: when the time signature is provided in the run time parameters, midi2abc set the flag tsig so that txt_timesig ignores any time signature metatext commands in the midi file. Therefore header_asig and header_bsig are still initialized to zero and a division by zero occurs when the main function attempts to compute barsize. Fix: prior to computing barsize, the main function checks whether tsig was set. If it was set, header_asig and header_bsig are assigned values specified in the run time parameters. I made some minor changes to midi2abc.c to reduce some of the warning messages. (1) the function testtrack() is declared at the beginning of the file so that guessana knows what parameter it returns. (2) setup_timesig function is declared as returning void. (3) the function txt_timesig was placed after the definition of setup_timesig. (4) The static declaration for ttype[] in txt_metatext() was removed. (It was necessary for -Wtraditional for the gcc compiler.) May 8 2004 Midi2abc fails to identify triplets in midi files with 3/4, 3/8 or any multiple of 3 beats per measure time signature. For example if you convert the following file X:1 T: triplets M: 3/4 L: 1/8 K: C (3C/D/c/ (3C/D/c/ (3FAc (3FAc |\ (3C/D/c/ (3C/D/c/ (3FAc (3FAc | to a MIDI file using abc2midi and then back to a abc file using midi2abc, you get X: 1 T: from /home/seymour/abc/triplets31.mid M: 3/4 L: 1/8 Q:1/4=120 K:C % 0 sharps %%triplets C/2[c/2D/2]C/2[c/2D/2]F/2A/2 z/2c/2F/2A/2z/2c/2| \ C/2[c/2D/2]C/2[c/2D/2]F/2A/2 z/2c/2F/2A/2z/2c/2| which is far from what one expect. (Note the chords [c/2D/2]). Analysis: for some unknown reason the function dospecial() in midi2abc checks the time signature of the input and does nothing if the number of beats in the key signature is a multiple 3 or if the number of beats is not a multiple of 2. Fix: these conditions were commented out and triplets are now detected. Midi2abc cannot identify triplets composed of chords. For example for input X:1 T: triplets M: 3/4 L: 1/8 K: C (3[CE][DF][ce] FADC |(3[CE][DF][ce] FADC | converted to a midi file, midi2abc produces X: 1 T: from /home/seymour/abc/triplets41.mid M: 3/4 L: 1/8 Q:1/4=120 K:C % 0 sharps %%triplets [E/2C/2][F/2D/2]z/2[e/2c/2]F ADC| \ [E/2C/2][F/2D/2]z/2[e/2c/2]F ADC| Analysis, the function dospecial() was not designed to handle chords. The problem is unresolved. You will have to edit the output file manually. Midiabc cannot identify triplets tied to a previous note. For example, X: 1 T: tied triplet M: 4/4 L: 1/8 K: C G2- (3GBd E2 (3FGA|G2- (3GBd E2 (3FGA| The MIDI file created from the above converts to X: 1 T: from triplet51.mid M: 4/4 L: 1/8 Q:1/4=120 K:C % 0 sharps %%tied triplet G2- G/2B/2z/2d/2 E2 (3FGA| \ G2- G/2B/2z/2d/2 E2 (3FGA| This is also beyond the capabilities the function dospecial(). The problem has not been resolved. Improvements in appearance of output. The function printtrack() in midi2abc places a blank (space) before the beginning of a triplet. May 9 2004 Midi2abc cannot resolve 32nd notes played in 4/4 time. For example, in the last bar of the MIDI file produced from the abc file X: 1 T: no thirty-second notes M: 4/4 L: 1/8 K: G CDEF C/E/D/F/ G/A/B/C/ | (3CDE (3DEF (3EFG (3FGA| C/4E/4D/4F/4 C/4D/4E/4F/4 G/A/B/C/ z4| there are a series of 32nd notes. The output from midi2abc is X: 1 T: from precis1.mid M: 4/4 L: 1/8 Q:1/4=120 K:G % 1 sharps %%no thirty-second notes CD EF C/2E/2D/2F/2 G/2A/2B/2C/2| \ (3CDE (3DEF (3EFG (3FGA| \ z/2z/2z/2z/2 G/2A/2B/2C/2 The series of 32nd were replaced by rests. Analysis: the temporal resolution of midi2abc was set to half of the abc unit length specified by L: field command. Thus for L:1/8, the smallest note produced is a 1/16 th note. Midi2abc automatically chooses the L: value based on the time signature. For time signatures less than 3/4 the L: value is set to 1/16. For other time signatures it is 1/8. The purpose of limiting the resolution is to avoid unusual note lengths such as C2-C//2 which should not occur in music notation. The L: value is set by the function setup_timesig(). The number of parts per L: time unit, is unfortunately not explicitly expressed in the midi2abc code. Fix: a new global variable, parts_per_unitlen, was added to the file midi2abc.c and set to the default value of 2. If you search for this variable, you can see the places where the splitting of the time unit into 2 parts was built in. A new run time parameter, -ppu allows you to change this value. For example if use -ppu 4, midi2abc should be able to handle the 1/32nd notes. This establishes the basic quantum unit that midi2abc uses. A new run time parameter -aul which allows you to set the L: abc unit length was introduced. Checks were introduced to ensure that the -ppu parameter and the -aul are powers of two. May 10 2004 Midi2abc like other abcmidi applications requires that the run time parameters be place before the parameter list. This is different from most Unix/Linux applications. However, in many cases midi2abc is forgiving and is still able to fine the input filename. This is not true for the -u parameter. For example, midi2abc.exe -u 100 precis1.mid will result in Error - Cannot open file 100. Fix: the character u was added to the "ambQkco" string in the function huntfilename() in midi2abc.c May 15 2004 Midi2abc/abc2midi incompatibility in the handling of accidentals. When abc2midi converts the following file to a MIDI file: X: 1 T: accidentals M: 4/4 L: 1/8 K: G FGB^D gdef | FGBD gdef | FGB^D g=def| FGBD gdef | the sharp accidental (^) applied to the D also acts on all other D's in that bar including d which is shifted by an octave (bar zero). To prevent the sharp applied on the second (shifted D), it is necessary to place a natural (=). Midi2abc does not comply with this convention so it produces the following output from the MIDI file. X: 1 T: from accid1.mid M: 4/4 L: 1/8 Q:1/4=120 K:G % 1 sharps %%accidentals FG B^D g^d ef| \ FG B=D g=d ef| \ FG B^D gd ef| \ FG B=D gd ef| Note that in the second bar (starting from zero), no natural was placed in front of d, resulting in a different note. (This only occurs when the two notes differ by one or more octaves.) Fix (as suggested by Werner Hoersten): in the function printpitch(), replace back[trans[i]] = i; with for (i=p % 12; i<256; i+=12) back[trans[i]] = i; Now midi2abc and abc2midi are consistent with each other. May 15 2004 The -gk option in midi2abc.c is working again. June 12 2004 Improved the handling of grace notes. The size of the grace notes is no longer determined by a fixed ratio. Instead the grace notes are of constant length specified by a new %%MIDI gracedivider command. The old method is still supported. June 25 2004 store.c (abc2midi): Commented out compilation flag INFO_OCTAVE_DISABLED 1 now allowing the handling of [I: octave=1]. (It was disabled in July 19 2003. The instruction field command I: is parts of the proposed abc standard 2.0. so I have decided to enable it.) June 25 2004 abc2midi.c: For the -sr option to swallow rests, you can specify the size of the rest in quantum units. Quantum unit is defined in readme.txt updated today. July 3 2004 midifile.c: added new global Mf_bytesread (number of bytes read in track). July 4 2004 midi2abc: added new runtime option -Midigram. If it is selected, all other options are ignored and no abc file is created. Instead, a new function midigram() is called and the program lists all the notes occurring in the file where each line represents a note on/note off event. The line is in the following format. on_time off_time track channel midi_pitch midi_vol. The on/off time is given in quarter beat units (ie. midipulses/ppqn where ppqn is pulses per quarter note specified in the MIDI header). The last record indicates the duration of the MIDI file in MIDI pulse units. Though in theory, this feature should be put into a separate program, it was felt there were enough programs in the abcmidi package. The code to convert the midi file to an abc file in main() was stuffed into a new function called midi2abc. New functions (no_op0,,no_op5, print_txt_noteon, print_txt_noteoff, init_notechan, open_note, close_note and initfunc_for_midinotes were created. July 11 2004 abc2midi, yaps, abc2abc, midi2abc. Introduced a new parameter -ver which prints out the current version number of the program. Added a new program, midicopy to the abcmidi package. (Documentation put in midicopy.1 and readme.txt.) All the makefiles were updated, however I am unable to check out the ones in the makefile subdirectory. July 17 2004 abc2midi (store.c), yaps (yapstree.c), abc2abc (toabc.c), midi2abc (midi2abc.c) midicopy (midicopy.c) for -ver parameter changed exit(1) to exit(0) after printing out version number. August 21 2004 A lot of abc files indicate ornamentations using the tilde operator ~. Abc2midi has been substituting a roll for the ornamentation. Guido Gonzato has suggested that it should be replaced with an acciaccatura for all notes except dotted quarter notes. The dotted quarter note should be replaced with three eight notes where the second note is preceded with an acciacatura and the third note is preceded with an appoggiatura. Two new procedures were introduced in store.c. Doornament applies the action when decorator[ORNAMENTATION] is encountered. The function doornament calls the new function makecut which inserts a grace note. (Unfortunately the length of the grace notes cannot be adjusted using the %%MIDI gracedivider as described on June 12 2004 since the %%MIDI commands are processed later.) The procedure event_note was modified to call doornament instead of doroll when an ornament is encountered. September 05 2005 A new feature was introduced in the abcmidi package. Abc2abc: a new run time parameter, -nokey was introduced. It will suppress the key signature and place all the necessary accidentals. Abc2midi, abc2abc, yaps understand the key signature K: none. For such key signature, no sharps or flats will be assumed. The -t (transpose) function in abc2abc should work with K: none. Changes were made to parsekey in parseabc.c and to event_key and event_note in toabc.c (search for nokey) to recognize K: none. When K: none is encountered, abc2midi, yaps and abc2abc assumes no key signature is supplied. September 06 2005 Yaps does not display the note length correctly when no L: is declared in the abc header. Fix: in start_body (yastree.c) replace setfract(&thetune.unitlen, 1, 16); with event_length(16); etc. September 12 2005 More work was needed to the -nokey option working correctly. In order to ensure that toabc.c works the same way without the new feature, event_note was divided into two functions event_note1 and event_note2. Event_note1 is an exact copy of the original event_note and is called when nokey is not set. Event_note2 contains all the new code for transposing notes when nokey is set. When event_note is called it either calls event_note1 or event_note2 depending upon the status of the flag nokey. Event_note2 performs the transposition in a different fashion. The note is converted to a midi representation. The number of semitones is added to the midi representation and the midi representation is converted back to the note representation. Code for converting to the midi representation was borrowed from store.c and code for converting the midi representation back to the note representation was borrowed from midi2abc. There was a small incompatiblity between setmap representation (character versus numeric representation) which had to be fixed. The -nokey option was split into two options. -nokeys will use sharps. -nokeyf will use flats. September 13 2004 Added gchord default for 12/8 time (fzcfzcfzcfzc). September 17 2004 Cleaned up all source code to reduce the number of compiler warnings reported by Microsoft Visual C++. ANSILIBS is now defined when compiling with Visual C++. September 19 2004 Many abc tunes do not specify the tempo with the Q: command. By default abc2midi uses a tempo of 120 quarters notes per minute. For many tunes, this is too slow. A new run time parameter -Q was introduced into abc2midi, allowing you to specify the default tempo in the event that no tempo was specified. If the tempo is specified in the abc file, this parameter is ignored. A new global default_tempo (initialized to 120) was introduced in store.c. This parameter can be changed using the -Q run time option added to event_init. September 20 2004 Fixed bug in applygrace_new which causes floating point exception (divide by zero) for some abc files. September 26 2004 abc2abc does not recognize the parameter name="some string" eg. in the multivoice command. For example, V: 1 name="alto 1" instructs abcm2ps to print "alto 1" on the staff. Unfortunately, abc2abc does not show this parameter in the output file. This is part of the proposed abc 2 standard. Fix, parsevoice in parseabc.c now extracts the name= parameter in the V: command. The event_voice command (which appears in store.c, yapstree.c and toabc.c) now has two extra parameters for passing the name string. In toabc.c, event_voice prints out the name string when it is found in the voice command. I introduced a new function parsename, which processes the "name= ..." parameter. In addition I fixed a bug which causes V: transpose=1 to produce a segmentation error. October 2 2004 As mentioned above on August 21 the new implementation of dooranment did not allow configuring the length of the grace note using the %%MIDI gracedivider command. This was fixed by replacing the implementation of the procedure makecut. Initially gracedivider was alway 4 (the default when it is not specified). October 8 2004 The abcguide.txt and proposed abc standard 2 includes the use of multirepeats (i.e |: ..|[1,3 .. :|[2,4.. :| ). Though yaps and abc2abc can handle this syntax, abc2midi fails to handle it despite some earlier effort to introduce it. For example, some of the code added to in genmidi.c to handle multirepeats includes (eg. inlist(j, passnum)). Furthermore, the old feature codes REP1 and REP2 was replaced with PLAY_ON_REP. Nevertheless, the code does not process correctly multirepeats. For reference the parser (parseabc.c) maps the repeat symbols into the features in the following manner. |: BAR_REP :| REP_BAR :: DOUBLE_REP [1, [2 etc PLAY_ON_REP and places the count in pitch[] or a text string. The problems occur in two places: (1) writetrack in genmidi.c and (2) fixreps in store.c. Writetrack needs to keep track of the number of times the section has been repeated using the variable "pass" so that it knows which bars to play. However, for both case REP_BAR: and case DOUBLE_BAR: the pass variable is allowed to assume only values of 1 and 2. Therefore, it cannot handle |[3 or whatever. If more than one :| (REP_BAR) is associated with a |: (BAR_REP) this causes an event_error. To make things more confusing there is another variable 'additive' which refers to an undocumented feature in the P: command where the symbol + and - indicates whether repeat marks in a part section are to be processed or ignored. I don't beleive this feature has ever been used. I have therefore removed this feature to make the code easier to support. From now on additive is always assumed. In other words if a repeat section occurs in a PART it is always repeated. There is now no way to ignore the repeat command. Fixreps was primarily designed to insert a BAR_REP (|:) when it is missing in the beginning of the tune. However, it tries to do much more. It checks for syntactical errors such as two or more closing repeats associated with an opening repeat as an error. If it finds an extra closing repeat, it attempts to insert a matching opening repeat (which is not desirable for multirepeats). If it finds two opening repeats a row, it attempts to correct the situation by changing the second opening repeat into a double repeat ::. Unfortunately, these checks get in the way when you have multirepeats. The multirepeats syntax appears to allow the use of either a :| or || for separating sections. This does not seem to be built into the writetrack code. This seems to more than a weekend project. October 15 2004 In order to handle multirepeats, several changes were introduced into the writetrack code in genmidi.c First a new variable, maxpass, which specifies the maximum number of repeats was introduced. It is initialized to 2 and reset to 2 any time a left repeat symbol is encountered. The code for the switch block REP_BAR (:|) was changed so that the variable pass can be incremented until it reaches maxpass. A check for whether a right repeat was expected (i.e. a left repeat was found), is only made on the first pass. (The flag expect_repeat is cleared after the first pass.) More changes were made to the switch block code for PLAY_ON_REP which handles any of the indications such as |1 , |[1, |[1,3 etc. The code ... parts !=-1) { passnum = partrepno = 1; was removed since it was a remnant of the undocumented additivity feature. The error "Cannot find :| || [1 ..." is not invoked when encountering PLAY_ON_REP while skipping a variant ending. When a variant ending is found maxpass is set to pass+1 in case this is not the last variant ending. The fixreps code in store.c also required changes. The code mainly inserts a |: in the beginning of the tune in case it is needed. Unfortunately, the code can make other unexpected changes and does not understand multiple repeats. For example, if it encounters two left repeats (|:) without intervening right repeats, i.e. |: some stuff |: some stuff etc. then it assumes the second left repeat was a mistake and changes it to a double repeat :: without any warning. If fixreps finds two right repeats (:|) in a sequence, then it returns a message that a spurious right repeat was found and inserts a new left repeat at a previous bar line. For the case PLAY_ON_REP, fixreps identifies two situations, denom[j] == 1 corresponding to [1 and denom[j] == 2 corresponding to [2. For the second case, it was assumed that no more REP_BAR (i.e :|) would be encountered so the flags expect_repeat was cleared. This is not correct for multirepeats, so those lines were commented. Furthermore, when a [1,3 or something similar is encountered, denom[j] is now 0 and the code falls into the next case statement BAR_REP2 which should never happen. Another break statement was added to prevent this from occurring. Major changes were made to fixreps. Now it only checks for missing |: before [1 :| or ::. It also checks for two |: |: in a row. If you use multirepeats, i.e. more than 1, be sure to end last variant with a double bar line. Other related changes to store.c: got rid of the obsolete functions event_rep1 and event_rep2. They are no longer used. Corrected abcguide.txt on the handling variant endings. Added protection for file runaway in eputc in midifile.c. abc2midi.exe will abort if it attempts to create a midifile larger than 500000 bytes. October 24 2004 More work was needed to correct problems with the abc2abc -nokeys option. Propogation of accidentals across bars was not working. Fix for toabc.c: the pitchof() function was changed. The function setupkey() was eliminated and printpitch() was rewritten. It now handles propogation of accidentals across bar lines but not between bar lines in event of a tied note. The latter case would involve considerable more development since no code for linking tied notes is present in toabc.c. (Store.c, for abc2midi, does the linking in a separate pass -- dotie, but toabc.c does everything in a single pass. The code can get quite hairy if we have interleaved voices.) October 29 2004 For K:none, abc2abc uses flats or sharps depending upon the variable useflats in the function printpitch (toabc.c). The variable useflats is set by the run time parameter -nokeyf. For some music, one might want to have the variable useflats be adaptive to the type of guitar chords (gchords) transposed by abc2abc. I introduced as an experiment the option of adapting useflats to the presence of flats or sharps in the guitar chord. When the variable adapt_useflats_to_gchords is set, some adaption is done after the guitar chord is processed. In general for K:none, abc2abc tends to use sharps in the guitar chords for any transpositions unless flats have been written into the guitar chords. November 4 2004 also see June 13 2005 Chord syntax extension: it is convenient to express a chord as [CEG]3 instead of [C3E3G3] which is part of the proposed abc standard version 2. Presently the abcmidi parser will consider the 3 after the ] as a stray number however other software such as abcm2ps allows this extension. Current practice: the parser run differently in each application (abc2midi, abc2abc, and yaps) so each has to be examined separately. abcmidi: writetrack in genmidi.c checks whether a note is inside a chord. If it is in a chord, a midi_noteon is sent to the MIDI file and a midi_noteoff based on the feature/num/denom information is sent to the queue. The delay time is not advanced, so that all remaining notes in the chord will start at the same time. When the end of chord marker is encountered, the delay time is advanced by the amount in the feature/num/denom arrays so that the next note will start at the right time. at the right time. This amount recorded with feature CHORDOFF is (modified) by tiefix to be the last note length encountered in the chord. Fix: Parseabc.c was modified to pick up the chord length placed after the closing bracket "]". If it is not indicated, it gets 1/1. The chord length is passed to event_chordoff via new parameters chord_n and chord_m. abc2midi: In store.c, the event_chordoff handler checks the chord_n,chord_m values. If they are 1,1 then addfeature sends a CHORDOFF feature and everything runs the same; otherwise addfeature sends a CHORDOFFEX and chord_n*4,chord_m*v->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 preceeded 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 propogate 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 instuction 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 propogate 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 propogate 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 propogates 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 propogate 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 compatability 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 controled 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 lieing 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 propogate 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 propogates 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 propogate 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 <stdlib.h> 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 propogate 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 frome 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 (Rarified) 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 (Rarified) 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:<tonic> exp <accidentals> 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 compatiblity. 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 transfered 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;j<parts;j++). parts is 1 and not 2 since it starts from -1. There part_start[1] was not incremented to 25 by missing_repeats. The fix was to add an = after < in the for loop. for(j=0;j<=parts;j++) June 7 2011 Abc2abc: a new feature has been added to abc2abc to support multivoiced tunes. Using the -P X option, where X is the voice number, abc2abc will act on only voice X and leave all the other voices untouched. For example, if the input file t.abc is X:1 T: Example 1 T:Solo instrument plays the same as the upper voice of the piano M:3/4 L:1/8 V:1 clef=treble sname="violin" V:2 clef=treble sname="piano" V:3 clef=treble V:4 clef=bass %%staves 1 {(2 3) 4} K:G V:1 K:G G2 D2 GA | B6 |] V:2 G2 D2 GA | B6 |] V:3 B,2 C2 B,C | D6 |] V:4 G,2 F,2 E,D, | G,,6 |] and we wish to transpose voice 1 up a tone for a Bb clarinet. We run abc2abc t.abc -P 1 -t 2. The output will now look like. X:1 T:Example 1 T:Solo instrument plays the same as the upper voice of the piano M:3/4 L:1/8 V:1 clef=treble sname="violin" " V:2 clef=treble sname="piano" V:3 clef=treble V:4 clef=bass %%staves 1 {(2 3) 4} K:G V:1 K:Amaj A2 E2 AB | c6 |] V:2 G2 D2 GA | B6 |] V:3 B,2 C2 B,C | D6 |] V:4 G,2 F,2 E,D, | G,,6 |] Please note in order for the key signature K:Amaj to appear in voice V:1, it was necessary to place K:G after V:1 in the input file. I have not tested this feature with other options. It is important that you know how this feature is implemented as discussed below. The implementation introduces a new command which is a slight variation of the -V X command that is used to extract a particular voice from the abc tune. The -V command merely suppresses output when the particular voice does not match the requested voice. The program still continues to process the voices so hence error messages from other voices can be present). The -P command acts in a similar fashion, however instead of just suppressing the output for the other voices it replaces it with the the unprocessed input lines. Here is how the feature was implemented. In parseabc.c, a new function print_inputline() was introduced. This function prints a line in the input file verbatim. A new flag, passthru was added in toabc.c and initialized to 0. If the -P X option appears in the runtime sequence, then the selected_voice (the same variable used by -V X) is set to the voice number X and the flag passthru is set to 1. The flag output_on is automatically set when ever the voice number is selected_voice (X). (This is part of the -V X code.) One more addition in toabc.c, completes the implementation. In the beginning of the function event_linebreak() (in toabc.), I added. if (!output_on && passthru) print_inputline(); /* [SS] 2011-06-07*/ As a final comment: The toabc.c code is quite difficult to understand -- in particular the function newabctext(). The trick used here, was least invasive. June 10 2011 Abc2abc bug. The -V option sometimes suppresses vital field command information. For the following file voicehead.abc. %%barnumbers 1 X:1 V:1 clef=treble V:2 clef=bass %%staves [1 2] T: Lost field commands M:6/4 L:1/16 K:E V:1 [K:E] e8 e4- e4 d4 e2d2| c8 c4- c4 B4 c2B2| A8 B4 F8 G4-|-G8 A4B12 |] V:2 [K:E] G,4 B,2A,2 G,4 F,12 | E,4 G,2F,2 E,4 D,12 | C,12 A,,12| B,,8 F,,4 B,,12|] abc2abc ../Desktop/voicehead.abc -V 1 produces %%barnumbers 1 X:1 V:1 clef=treble V:1 [K:E] e8 e4- e4 d4 e2d2| c8 c4- c4 B4 c2B2| A8 B4 F8 G4-|-G8 A4B12 |] The field commands, T:, L:, M: and K: are lost. Analysis: This bug was probably around for a long time. Since voice 1 was requested, the V:2 command in the header suppresses output by setting output_on = 0 when it is first encountered. The resulting output is no longer a correct abc file. Fix: in event_voice, output_on is set to 0 only if xinbody is nonzero. June 10 2011, abc2abc bug -P option. For the voicehead.abc file (immediately above) abc2abc ../Desktop/voicehead.abc -P 2 -t 2 %%barnumbers 1 X:1 V:1 clef=treble V:2 clef=bass %%staves [1 2] M:6/4 L:1/16 K:F#maj V:1 [K:E] e8 e4- e4 d4 e2d2| c8 c4- c4 B4 c2B2| A8 B4 F8 G4-|-G8 A4B12 |] V:2 [K:F#maj] A,4 C2B,2 A,4 G,12 | F,4 A,2G,2 F,4 E,12 | D,12 B,,12| C,8 G,,4 C,12|] The program should not change the key signature of the first K: field declaration since it applies to all voices. Fortunately, the key signature to voice 1 was already declared; otherwise F#maj would have been assumed. Analysis: if we are extracting a single voice and transposing it using the -V 2 -t 2 command, this behaviour would be desirable. (If the key signatures were not declared in the individual voices, we would require that the K: field be changed to F#maj.) However, for the -P option this could lead to a problem. Fix: this is not an elegant fix since it could cause problems elsewhere. The passthru flag is used to indicate that the -P option was used. Normally the source of the output is controlled by the event_linebreak() function. However, it was not easy to figure out how to intercept the K: output so it was necessary to try a different approach. The event_key function was modified to do nothing except print the original K: command if this K: command does not occur in the body. A new function print_inputline_nolinefeed() was needed in parseabc.c. July 4 2011 -- also see August 17 2011 Abc2midi new feature. The Phil Taylor stress algorithm has been implemented in abc2midi on an experimental basis. This algorithm stresses notes by varying their loudness and duration based on their position in the bar. Note durations are shortened by lengthening the inter-note silences so that there is no affect on the tempo. This model runs in opposition to the standard model in abc2midi, so that regular commands for affecting dynamics such as !p!, %%MIDI beat, %%MIDI beatstring, are ineffective. Also the %%MIDI trim x/y command is also turned off by the stress model. To turn on Phil Taylor's stress model, load one of his stress models using the MIDI command %%MIDI ptstress hornpipe.txt where hornpipe.txt is some file resembling 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 To switch back to the regular or standard beat model use: %%MIDI beataccents The stress model file is formatted as follows. The first value in the file is the number of segments -- here it is 8. This is followed by eight lines specifying the velocity (volume) and duration associated with each segment. The model adjusts the loudness and duration of the note based on which segment it falls into. Its duration is scaled by the second factor. Since we can only shorten notes, the duration is actually scaled by the ratio of the specified duration over the maximum duration which is here 1.4. When a note overlaps several segments the parameters are averaged over those segments. There is no constraint on the number of segments other than it should be less that 31, the amount of allocated space in the program. For some irregular rhythms, such as 7/8 time, one may use an odd number of segments. A few sample stress files can be found in the pt folder. Here is a sample tune you can test. X:1 T: stress test M: 4/4 L: 1/8 K: G Q:1/4=160 %%MIDI program 73 flute %%MIDI ptstress pt/hornpipe.txt "G"dd2d d2d2|"Em"dd2d d2d2|"D7"dd2d d2d2|"G"G2A2 B2c2| Implementation: New global variables were introduced in genmidi.c int beatmodel = 0; /* a flag selecting either the standard model or Phil Taylor's model */ int nseg; /* the number of segments in Phil Taylor's model */ int ngain[32]; /* gain factors for each possible segment */ float fdur[32];/* duration modifiers for each possible segment */ float maxdur; /* maximum duration modifier */ int segnum,segden; /* segnum/segden is the size of the segment. It is computed from nseg and the time signature */ The function noteon(n) was split into two functions, noteon() and note_beat(n,&vel). A new function stress_factors(n,&vel) implements Phil Taylor's model. The function noteon(n) either calls note_beat() for the standard model or stress_factors() depending on the state of the variable beatmodel. The function note_beat() contains the original contents of noteon(). The function stress_factors() affects the note duration in an indirect manner by modifying the trim_num/ trim_denom variables which are already used for articulating the notes using %%MIDI trim x/y command. Another function, readstressfile() was written to load one of the Phil Taylor's stress models. The beatmodel flag is reset to 0 when a MIDI beat or trim command is encountered. In dodeferred(), a new command, ptstress is introduced which loads the selected model. July 18 2011 Abc2midi: support for EasyABC (http://www.nilsliberg.se/ksp/easyabc/) To allow EasyABC to follow the score while the MIDI file is playing additional positional information needs to be embedded into the MIDI file. This is done by placing the line and character position of each note in the MIDI file. If abc2midi is started with the -EA run time parameter, this information is included. Implementation: this is a joint effort with Nils Liberg. parseabc.c -- added two new global variables char *linestart and int lineposition. lineposition stores the position of the current token (usually a note) in the music line being parsed. The variable lineposition is passed to store.c as an external. abc.h -- a new featuretype META is added store.c -- a new flag int easyabcmode is introduced. It is set to 1 when the -EA run time parameter is included. addfeature(META,... inserts the line number and line position into the feature, num, denom,... structure whenever a chord or note is started. (Seach for easyabcmode in the source code store.c). genmidi.c -- in the switch control structure in writetrack() a new branch case META: was added. Presently, it merely prints the line number and character position. Nils Liberg will replace this print statement with the appropriate MIDI output statements. August 3 2011 Abc2midi bug. Abc2midi does not play part C in the following example. X:1 T: part bug M: 2/4 L: 1/8 P:C K: C P:A EDBc|B2 C2:| P:B DEFG|ABc2| P:C GABc|c4| This is another instance of the bug reported in June 6 2011. Unfortunately, the variable parts refers to the number of parts to be played. For example if the header specifies P: (AB)2 then readspec() expands this to P: ABAB and parts is set to 3 (since it starts from -1) indicating that there are 4 parts to be played. There is no variable indicating the number of parts occurring in the body, but we do not need it. In add_missing_repeats we change for (j=0;j<=parts;j++) { /* [SS] 2011-06-06 */ to for (j=0;j<26;j++) { /* [SS] 2011-08-03 */ part_start[i] is initialized to -1 so it will be less than add_leftrepeat_at[i] if the part was not defined. The index of part_start[i] is set to [(int)*p - (int)'A']] where *p is the part code between A and Z. August 07 2011 new build system Note if everything has been working fine, you can continue using the usual method for compiling the code. Nils Liberg has introduced an autoconf build system similar to what is used in abcm2ps. The files config.h.in, configure, configure.ac, install-sh, and Makefile.in were added to the distribution. To use this system, delete or rename the current makefile called 'makefile'. Make the file configure executable, (on linux or unix, chmod 764 configure). Run the script configure and then make. Thus, mv makefile makefile.bak chmod 764 configure ./configure ./make Note the script configure has various options. To see them, ./configure --help For example, ./configure --enable-debug will compile the code with the -g flag. August 09 2011 The address of the Free Software Foundation was changed from 59 Temple Place, Suite 330, Boston, MA 02111-1307 to 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 in the sources drawtune.c, genmidi.c, matchsup.c, midi2abc.c parseabc.c, position.c, pslib.c, queues.c, store.c, toabc.c and yapstree.c August 17 2011 to August 27 2011 More work was done on the Phil Taylor stress models during this period of time and there are now two versions of the model. To use these models you must include the -BF runtime parameter in the execution string. For example, abc2midi myfile.abc -BF You may follow -BF with either the numerals 1 or 2 which specifies the stress model version to use. Model 2 is more similar to the one used in Barfly and is the current default. Alternatively you may include the MIDI directive. %%MIDI stressmodel 1 Nevertheless, you must still include the -BF runtime parameter in the execution string for either model to be effective. The stress model descriptors corresponding to the different rhythm designators, (eg. Reel, jig, hornpipe, and etc.) are built into the code, so there is no need to reference an external file; however, this is still permitted using the %%MIDI ptstress directive described in July 4 2011. Implementation: More code was added in the files store.c, genmidi.c and a new file stresspat.c. The implementations of the two models are very different. Model 2, requires a separate pass to be performed through the internal abc representation (feature, num, denom,...) prior to writing the MIDI file. This pass is is performed by a new function called apply_bf_stress_factors() in store.c which is called after other passes such as scan_for_missing_repeats(), tiefix(), and dograce(). During this pass, the note durations in the num[] and denom[] arrays are modified by means of a new function in genmidi.c called beat_modifier(). The functions changes these values for NOTE, TNOTE and REST features. Beat_modifier() is called whenever a bar line is encountered. It scans all the notes and rests up to the next bar line and changes their durations. A new global array fdursum[] derived from fdur[] was introduced in order to modify the note durations. The functions readstressfile_simple() and readstressfile() were modified to initialize fdursum as well as other new globals segnum/segden which specifies the size of a segment. (The function readstressfile() was based on original format of Phil Taylor's stress file and is not used. It may be removed in future versions of the software.) Conversions of the note durations is done in beat_modifier() by first computing the actual positions of the notes in the bar based on all the offsets stored in the num[],denom[] arrays. The positions are remapped into the new space and the note offsets in the num[] and denom arrays are replaced. Special care was required to handle chords (notes enclosed by CHORDON, CHORDOFF, and CHORDOFFEX features) and tied notes (TNOTES). (Note that it is possible for a tied note to extend across a bar line.) (For reference tied notes are initially represented as NOTE TIE NOTE etc. The function tiefix() changes this representation, to TNOTE REST REST. (It was desirable not to change the durations of the two following REST features for some reason.) (I do not know what will happen when tied notes occur inside chords and I do not want to have to find out.) The implementation was also complicated by the fact that all durations are represented by fractions rather than decimal numbers. Thus all arithmetic was done using fractions. Note velocities are recorded at the time that the notes are written to the MIDI file (see noteon()) through the intermediary function stress_factors() in genmidi.c. In order to pass the stress modulated note velocity it was necessary to introduce another global array handled like feature[], pitch[], etc. which is called stressvelocity[]. The function beat_modifier puts the segment number based velocity, into stressvelocity[] which is pulled out at a later time by stress_factors() for beatmodel == 2. The original function stress_factors() was renamed to articulated_stress_factors() which now handles beatmodel == 1. If you run the abc2midi with runtime parameter -v (for verbosity), you can see how the program operates. Implementation: to avoid any problems with finding and opening files in different operating systems, the BarFly stress model descriptors for the different rhythms are stored internally in array structs stresspat[]. These arrays are defined in a new C file called stresspat.c which is now linked with abc2midi. The file defines two functions, init_stresspat() and load_stress_parameters(). Init_stresspat() initializes the stresspat[] arrays. Load_stress_parameters() identifies the appropriate stress pattern from the rhythm designator and meter, and places the required information in the external variables segnum, segden, nseg, ngain, maxdur, fdursum and beatmodel. Parseabc.c was modified to save the contents of the M: command as a char timesigstring[] which is passed to stresspat.c as an external. This allows handling time signatures such as C|. A new flag, barflymode which is set by the -BF runtime parameter was introduced in store.c. A new global char rhythmdesignator[32] was added in store.c which is set in event_field when the R: field is processed. If barflymode is set, event_field() in store.c will not set the hornpipe flag which converts sequences of eighth notes into broken notes. The Makefile.in and makefile were modified to include stresspat.c. i.e. OBJECTS_ABC2MIDI=parseabc.o store.o genmidi.o midifile.o queues.o parser2.o stresspat.o and stresspat.o : stresspat.c August 26 2011 Abc2midi: the -v option (verbose) accepts a number indicating the level of verbosity. If a number does not follow, the verbosity is set to 1. Abc2midi: the -BF option (barflymode) accepts a number which indicates the stress model to use. If none is supplied, it uses model 2. September 06 2011 Abc2midi bug: for the following tune, X: 2 T:test2 M:4/4 L:1/4 %R:hornpipe K:G %%MIDI ptstress hornpipe.txt V:1 c B A G| c/B/A/B/ A G| V:2 z/C,/ z/C,/ z/C,/ z/C,/ | z/C,/ z/C,/ z/C,/ z/C,/ | when the file is run without the -BF run time parameter the MIDI file created is silent. All the notes are assigned a velocity (loudness) of 0. Analysis: the %%MIDI ptstress directive sets the beatmodel control variable to 2 indicating that stress adjustments should be made. Because the -BF was not present, the %%MIDI ptstress directive is processed too late and the function apply_bf_stress_factors() was not run prior to writetrack. However, stress_factors () is still called to adjust the note velocities using the information in stressvelocity array. But the stressvelocity array contains only zero's. Fix: in the function noteon in genmidi.c, we call note_beat() in case stress_factors() returns a zero velocity. Note: that if the file is executed with the -BF flag, the notes in the first bar still have a zero loudness because the first bar does not begin with a bar line and beat_modifier was never called for that bar. However, the above file exposes another bug. Abc2midi bug: for the preceding tune, when abc2midi is called with the -BF parameter, the first G in voice 1 is held too long causing a loss of synchronization with the second voice. Analysis: the function fdursum_at_segment returns the wrong values for val_num/val_den because the value of fdursum[nseg] was incorrect. Fix: in readstressfile_simple() I replaced the lines if (fdursum[nseg] != (float) nseg) fdursum[nseg] = (float) nseg; with lastsegvalue = (float) nseg * (float) qnoteden / (float) qnotenum; /* ensure fdursum[nseg] = lastsegvalue [SS] 2011-09-06 */ if (fdursum[nseg] != lastsegvalue) fdursum[nseg] = lastsegvalue; September 07 2011 Abc2midi no feature: The %%MIDI ptstress directive now also accepts the ptstress directly. For example, %%MIDI ptstress 4 100 1.3 60 0.7 100 1.3 60 0.7 instead of %%MIDI ptstress test.txt where test.txt is 4 100 1.3 60 0.7 100 1.3 60 0.7 You can still, pass a path to a file. If it cannot parse the MIDI command as stress parameters then it will assume a file name is being passed. September 13 2011 Abc2midi fails to tie notes separated by a double bar line. For example: X:1 T: tie test M: 2/4 L: 1/8 K: G d2 g[_c_e]/-||[c2e2] g2| the message was returned Error in line 6 : Could not find note to be tied Error in line 6 : Could not find note to be tied Fix: In dotie() in store.c a new condition was added to the switch structure, switch (feature[place]) { case SINGLE_BAR: case BAR_REP: case REP_BAR: case DOUBLE_BAR: /* [SS] 2011-09-13 */ October 19 2011 Abc2midi new feature: sustain pedal. One of the pedals on the piano sustains a note after the piano key is released. Two new instructions +ped+ and +ped-end+ or !ped! and !ped-end! using the old instruction notation were introduced. In the following example, X:1 T:Ped in pianomusic M:C L:1/8 K:C treble K: clef=bass Q:1/4=60 %%MIDI program 70 +ped+G,A,B,C+ped-end+DE| the notes, G,A,B,C were sustained. Though the bassoon does not have a sustain pedal, the scale is played on that instrument to make the effect more obvious. Implementation: the sustain is accomplished using the MIDI controller 64. The ped and ped-end instructions are detected in event_handle_instructions() in store.c. They in insert PEDAL_ON and PEDAL_OFF in the feature() array. Two new functions pedal_on() and pedal_off() which handle the PEDAL_ON and PEDAL_OFF features are introduced in genmidi.c. abc.h was updated to included the PEDAL_ON and PEDAL_OFF features. October 21 2011 Abc2midi bug: %%MIDI control command after a rest causes loss of synchronization. In the following example X:1 T: Synchronization Loss after rest (z2) V:1 V:2 M: 4/4 K:F#dor V:1 |: A,G, | F,G,F,G, A,B,A,G, | F,4-F,2 :| V:2 %%MIDI program 65 |:\ %%MIDI control 7 40 de| f4 z2 %%MIDI control 7 80 GA| f4-f2\ :| The control command is used to modulate the loudness of the alto saxophone in voice 2. The second control command which attenuates the saxophone to velocity 80 introduces another delay of z2 causing the following notes G and A to be played one beat late (into the next bar). Analysis: The second control command introduces a beat delay because delta_time is not zero when the function write_event is called. (Delta_time is not zero after a rest so that the following note will be delayed.) Fix: write_event should not introduce any delay, so that delta_time was replaced by 0 in the function call mf_write_midi_event(..). The function write_event is also called to turn on (off) portamento, to handle pitch_bend, pedal on and pedal off MIDI commands. (Hopefully, this change does not introduce a bug in the other functions.) November 18 2011 Abcmidi new feature. The MIDI commands, chordprog and bassprog have been extended to allow for an octave offset. In the following example X:1 T: octave test M: 2/4 L: 1/8 K: C Q:1/4 =96 %%MIDI program 74 Recorder %%MIDI chordprog 0 %%MIDI bassprog 0 "C"C4|C4|C4|C4| %%MIDI chordprog 0 octave=2 %%MIDI bassprog 0 octave=2 "C"C4|C4|C4|C4| The piano bass chordal accompaniment is shifted up two octaves from its usual position. The amount of shift is limited to + or - two octaves. To reset to the default position put, %%MIDI chordprog 0 octave=0 %%MIDI bassprog 0 octave=0 Implementation, in dodeferred() in genmidi.c, I added a few lines of code beginning with p = strstr(p,"octave="). For bassprog and chordprog declarations, the function searches for string "octave=" anywhere in the command line and then grabs the value following the equal sign and puts it in the temporary variable octave. gchord.base and fun.base are reset by if (found == 1 && octave > -3 && octave < 3) gchord.base = 48 + 12*octave; if (found == 1 && octave > -3 && octave < 3) fun.base = 36 + 12*octave; gchord.base is used in configure_gchord() and fun.base is used in dogchords(), both in genmidi.c. November 30 2011 Abc2midi slurring bug. In the following example, X:1 T:Slur Bug M:C| L:1/4 %%MIDI trim 1/2 K:C %%MIDI program 70 (cde)c | (cdec) | (cd)(ec) | (e/d/c) Gc/e/ | d2ed | c4 || The last note of every slur complex is not separated from the next note which is not in the complex. Analysis: writetrack() in genmidi.c looks turns off slurring when it sees a SLUR_OFF one unit away from the note it is processing. Unfortunately, there is always a SLUR_TIE there and writetrack should be looking two units away. (SLUR_TIE is used in yaps.) Fixing this situation introduces another problem; when SLUR_OFF is finally encountered writetrack discovers that slurring was already turned off and sends a warning. To fix this problem, a new global was_slurring is introduced and is used to detect the situation where slurring was turned off recently. December 8 2011 Abc2midi: fermata bug. When a rest is preceded by a fermata symbol H, abc2midi fails to recognize the rest. For example, X:1 T: Malformed note M:4/4 L:1/8 K:C E2 DG +fermata+z2 FG | E2 DG Hz2 FG | AGFD HE2 FG | ABdg e4 | The first fermata is expressed correctly, but the fermata in the following bar causes abc2midi to issue the following message. Error in line 6 : Malformed note : expecting a-g or A-G Analysis: parsemusic() in parseabc.c expects decorations to be always followed by a note and calls parsenote(). while(*p != '\0') { lineposition = p - linestart; /* [SS] 2011-07-18 */ if (((*p >= 'a') && (*p <= 'g')) || ((*p >= 'A') && (*p <= 'G')) || (strchr("_^=", *p) != NULL) || (strchr(decorations, *p) != NULL)) { parsenote(&p); } else { Parsenote() does not see a note since the decorations is followed by a rest. The rest is not processed. If the fermata is indicated using the instruction !fermata! or the more modern notation +fermata+, then cases 'x' and 'z' in parsemusic() process the rest getting the decorations from decorators_passback[] and everything works well. Fix: the easiest fix is to add a check for rests in parsenote(). New code was added. /* [SS] 2011-12-08 to catch fermata H followed by a rest */ if (**s == 'z') { *s = *s + 1; readlen(&n, &m, s); event_rest(decorators,n, m, 0); return; } if (**s == 'x') { *s = *s + 1; readlen(&n, &m, s); event_rest(decorators,n, m, 1); return; } Prior to looking for accidentals in the note. December 11 2011 Abc2midi: lyrics bug with inline voices. When abc2midi is applied to the following tune, X:1 T:Lyrics bug M:4/4 L:1/8 Q:80 V:1 clef=treble %%MIDI program 73 % General-MIDI "Flute" V:2 clef=treble %%MIDI program 26 % General-MIDI "Electric Jazz Guitar" K:C [V:1] ABcd e2 dc | ABcd e2 dc | w: This is just a test. Just a | quick-ie lit-tle test To see | [V:2] ABcd e2 dc | ABcd e2 dc | % [V:1] ABcd e2 dc | C8 | w: what is go-ing on With lyr- | ics | [V:2] ABcd e2 dc | c8 | % It returns the following errors and warnings. Warning in line 7 : Line of music without lyrics Error in line 11 : Verse 1 mismatch; 8 syllables in music 7 in lyrics Furthermore, the lyric information in the ouput karaoke MIDI file is mangled. The first line "This is just ..." is not associated with the individual notes and the second line "what is go-ing..." is missing. However, if we eliminate all the inline voice fields, X:1 T:Lyrics bug M:4/4 L:1/8 Q:80 V:1 clef=treble %%MIDI program 73 % General-MIDI "Flute" V:2 clef=treble %%MIDI program 26 % General-MIDI "Electric Jazz Guitar" K:C V:1 ABcd e2 dc | ABcd e2 dc | w: This is just a test. Just a | quick-ie lit-tle test To see | V:2 ABcd e2 dc | ABcd e2 dc | % V:1 ABcd e2 dc | C8 | w: what is go-ing on With lyr- | ics | V:2 ABcd e2 dc | c8 | % There are no errors or warnings and the resulting MIDI file is correct. Analysis: when abc2midi detects lyrics in the w: field, it calls event_words (in store.c) which saves the entire line in one of the entries of the global array words[]. It indicates the particular entry location in the words[] using the WORDLINE feature. During the final pass, writetrack() calls write_syllable() each time it encounters a NOTE, TNOTE (tied note), CHORDOFF (end of chord). At the end of line of notes signaled by MUSICSTOP, checksyllables() is called which merely verifies that it had sucessfully matched the notes with the line of lyrics. For this to work properly, findwline() must associate the line of music with the line of lyrics stored in the words[] array. Given a starting location in the feature[] which matches a particular music line in the tune, findwline searches the feature[] array for the next WORDLINE feature where it will get the address of the lyrics in the words[] array. This seach is aborted if findwline() encounters a WORDSTOP, PART, VOICE, or MUSICLINE prior to WORDLINE. The starting location for this search is given in the global variable thismline which gives the location of the last MUSICLINE that was processed. Writetrack() updates thismline each time it encounters another MUSICLINE feature. The source of the bug is that inline voice commands are not immediately followed by a MUSICLINE feature as would occur when the V: command is on a separate line. As a result, the variable thismline has not been updated to reflect the current music line. findwline() starts searching from the beginning of the feature[] array and aborts as soon as it encounters a VOICE or MUSICLINE feature. The function write_syllable, assumes it does not have any lyrics for that line. More confusion occurs when the next music line with lyrics is processed. Fix: now include /* [SS] 2011-12-11 inline voice commands are not followed by MUSICLINE where we would normally get thismline */ if (wordson) { thismline = j+1; nowordline = 0; }; in writetrack() after processing the VOICE feature. As an added comment, when genmidi.c is processing a voice with lyrics it assumes that every line of music for that voice has a line of lyrics. checksyllables() puts out annoying messages when a line of lyrics is missing. I do not completely understand the code in checksyllables(). December 19 2011 Abc2midi clef-octave bug. In the following example, the clef=treble declaration does not restore the octave setting to zero. X:1 T:Octave-Shifting Syntax Test M:6/8 L:1/8 K:G [V:1 clef=treble] GAB c2d | efg eBG || % in correct, notated octave [V:1 clef=treble+8] GAB c2d | efg eBG || % an octave higher, as requested [V:1 clef=treble] GAB c2d | efg eBG || % should be original octave, but isn't [V:1 clef=treble-8] GAB c2d | efg eBG || % octave below ABC notation, correctly [V:1 clef=treble] GAB c2d | efg eBG || % should be original octave, but isn't Fix: Added to the function isclef() in parseabc.c after if (strncmp(s, "treble", 6) == 0) { gotclef= 1; *gotoctave=1; /* [SS] 2011-12-19 */ *octave=0; if (fileprogram == ABC2MIDI && *gotoctave != 1 && *octave !=1) event_warning("clef= is overriding octave= setting"); }; January 29 2012 Abc2midi: extended %%MIDI chordname command to handle up to 10 notes (instead of 6). March 08 2012 Abc2midi: grace bug with voice overlay. Abc2midi loses synchronization when voice overlays and gracenotes present. In the following example X: 1 T: Grace Bug M:C| L:1/8 Q:1/2=80 K:G |{ABcB}c2B2B2A2|d2f2 g4 &D2F2 G4| the overlay D2F2 G4 appears two quarter notes late. When the grace notes are removed the voice overlay is in sync. Analysis: the problem is in the code sync_voice in store.c. Sync_voice determines the delay for the voice overlay; unfortunately, it does not distinguish regular notes from grace notes which should not have any time value in the calculation. Fix: added two new cases to switch (feature[j]), GRACEON and GRACEOFF to detect grace notes and to control the gracenotes flag. For case NOTE: check that gracenotes is not set before addfract(). March 22 2012 Abc2midi repeat error message: for the following file X:1 T:Mary Had a Little Lamb 1 C:Folk Song M:C L:1/4 K:Cmaj %%score {RH|LH} V:RH clef=treble V:LH clef=treble % [V:RH] e3/2 d/ c d | e e e2 | d d d2 | e g g2 | [V:LH] [CEG]4 | [CEG]4 | [B,DG]4 | [CEG]4 | [V:RH] e3/2 d/ c d | e e e2 | d d/d/ e d | c4 :| [V:LH] [CEG]4 | [CEG]4 | [B,DG]4 | [CEG]4 :| X:2 T:Mary Had a Little Lamb 2 C:Folk Song M:C L:1/4 K:Cmaj %%score {RH|LH} V:RH clef=treble V:LH clef=treble % [V:RH] e3/2 d/ c d | e e e2 | d d d2 | e g g2 | [V:LH] [CEG]4 | [CEG]4 | [B,DG]4 | [CEG]4 | [V:RH] e3/2 d/ c d | e e e2 | d d/d/ e d | c4 :| [V:LH] [CEG]4 | [CEG]4 | [B,DG]4 | [CEG]4 :| abc2midi runs without error messages if the tunes are processed individually eg. abc2midi lamb.abc 1 abc2midi lamb.abc 2 However, if abc2midi process the whole file, the program returns error messages. seymour@corsair:~/abc$ abc2midi lamb.abc voice mapping: RH 1 LH 2 writing MIDI file lamb1.mid voice mapping: RH 1 LH 2 writing MIDI file lamb2.mid Error in line 28 : Found unexpected :| Error in line 28 : Found unexpected :| Error in line 29 : Found unexpected :| Analysis: the messages are returned by writetrack() in genmidi.c as it is creating the midi file lamb2.mid. In most cases the position of the missing left repeat |: can be inferred, (in particular if it is at the beginning of the tune). However, in some cases the missing repeat is put at the wrong place or abc2midi fails to apply the repeat. In July 23 2009 new code was introduced to address this problem since it is proper for the left repeat to be omitted when it should occur at the beginning of the tune. The new functions scan_for_missing_repeats(), add_missing_repeats(), and clear_voice_repeat_arrays() were added to store.c. (See this file.) Unfortunately, the array bar_rep_found[] was not cleared between songs and the function scan_for_missing_repeats did not operate correctly. Fix: added the function call clear_voice_repeat_arrays() at the beginning of scan_for_missing_repeats() in store.c March 26 2012 Abc2midi fermata bug: in the following example X:1 T: Another fermata bug M: 2/4 L: 1/4 K: G %%MIDI program 68 oboe C2 H[CEG]2|C2 H[C2E2G2]| The first fermata is not held but the second one is held. Analysis: when the length of the chord is set outside the chord, the function fix_enclosed_note_lengths() in store.c is called to readjust the length of each note comprising the chord. The function did not take into account that the chord was being held longer. Fix: a new global flag, apply_fermata_to_chord, was introduced and used by the fix_enclosed_note_lengths to determine whether the notes in the chord should be lengthened. The flag is set in event_chordon by the variable chorddecorators[FERMATA]. It is reset to zero by fix_enclosed_note_lengths. March 29 2012 Abc2midi bug: abc2midi applies fermatas to all chords in which the length is set outside the chord. Analysis: 3721 if (apply_fermata_to_chord && !ignore_fermata) ; /* [SS] 2012-03-26 There should no semicolon ending this statement. Fix: removed the semicolon March 30 2012 Abc2midi bug: more bugs when fermata is applied to a chord. In the following example: X:1 T: Another fermata bug M: 2/4 L: 1/8 K: G +fermata+[C2G2] z2|+fermata+[CG2] z2| only the first note in the chord is held. Analysis: +fermata+ is one of the many instructions which is treated quite differently. Most of the instructions are not note decorations eg. +pp+ and are handled inside store.c. Unfortunately, +fermata+ is different since it is treated as a note decoration which is passed to event_note from parseabc.c. For this reason it was necessary to introduce a new array decorators_passback[] which is shared with parseabc.c (as well as toabc.c and yapstree.c) (See 2003 May 11 in this file.) The method worked well for single notes, however it has never worked for chords. The array decorators_passback[] is cleared to zero in parsenote() in parseabc.c as soon as it is used to transfer information to the decorator[] array. As a result, the second note in the chord is not held. Fix: it was still preferred to reset decorators_passback[] in parseabc.c rather than in all the files sharing this variable. Unfortunately, parseabc.c does not know whether a given note is inside a chord or not. A new flag, inchordflag, shared between parseabc.c and store.c was introduced. This flag is managed by event_chordon() and event_chordoff() in store.c. Now parsenote() does not zero the decorators_passback[] array if the note is inside a chord. A different fermata bug was exposed in the following example: X:1 T: Yet another fermata bug M: 2/4 L: 1/4 K: G %%MIDI program 68 C2 +fermata+ [CEG]2|C2 +fermata+ [C2E2G2]| The first fermata is never applied to [CEG]2. Analysis: the new function fix_enclosed_note_lengths does not apply the fermata because the flag apply_fermata_to_chord was not set. This flag was not set because chorddecorators[FERMATA] was not set in event_chordon(). In this case event_chordon() was called inside the function parsemusic() rather than parsenote(). Fix: It was necessary to update chorddecorators with information in both decorators[] and decorators_passback[] prior to calling event_chordon(). It was also discovered that the local array decorators() was not initialized inside the function parsemusic(). April 1 2012 Abc2midi: new feature. Introduced a new option (-TT) to tune the key of A above or below 440.0 Hz but less than a semitone. The output MIDI file will re-tune to that frequency. The purpose of this feature is to accommodate some instruments like the accordian which are not tune exactly to 440.0 Hz. Implementation: in store.c introduced two new globals retuning and bend which will be shared with genmidi.c. Also added code in event_init() in store.c to handle the -TT option. Abc2midi now needs to link to the math library so all the makefiles need to include -lm as well as Makefile.in which is used by configure. If the user inputs a valid frequency for the -TT option, the flag retuning is set and the integer bend contains the amount of pitch shift for all notes. In genmidi.c created a new function midi_re_tune() which sends the control RPN commands and the control data entry commands for changing the master coarse and master fine tuning. This function is called at the beginning of the track if the flag retuning is set and the track either contains notes, chordal accompaniment, or bagpipe drone. April 03 2012 Abc2midi -tuning. Changed to the lower frequency limit to 414.9 to permit A=415 Hz, a common tuning for Baroque music. The bend variable is still limited between 0 and 16383. April 15 2012 Abc2midi - lyrics. The function checksyllables() in genmidi.c emits warnings even when there do not seem to be any errors in the placement of the lyrics. I do not know how to fix this problem, or even whether a fix exists. Furthermore, the warnings do not appear useful as they are not very specific. Users can easily check the placement of the syllables by viewing the score produced by abcm2ps. The error message in checksyllables() is now suppressed except when running abc2midi in verbose mode. May 28 2012 Abc2midi - added a missing break command following the META: case in in writetrack() in genmidi.c May 29 2012 Abc2midi - bug. When running in -EA mode (easyabc), the META command carries the pitchbend value but the NOTE command has the wrong pitchbend value (usually garbage depending on the compiler). Analysis: in event_note() bentpitch[notes] was set before the META command rather than the NOTE command. Fix: moved the line setting bentpitch so it occurs before addfeature(NOTE...). May 31 2012 Abc2abc bug: abc2abc returns a bar count error when processing bars with split voices. For example for tune, X:1 T:Test L:1/8 M:2/4 K:Cmaj G | c4 & E2C2 || abc2abc produces X:1 T:Test L:1/8 M:2/4 K:Cmaj G | c4 & E2C2 %Error : Bar 1 is 1/1 not 2/4 || Analysis: abc2abc adds the length of every note in the measure, regardless of the &-split voice. Fix provided by Frank Meisshaert: the code for event_split_voice() was replaced by event_split_voice () { char msg[40]; emit_string("&"); if ((count.num*barlen.denom != barlen.num*count.denom) && (count.num != 0) && (barno != 0) && (barcheck)) { sprintf(msg, "Bar %d is %d/%d not %d/%d", barno, count.num, count.denom, barlen.num, barlen.denom ); event_error(msg); }; count.num = 0; count.denom = 1; } The code resets checks the length of the bar and resets count.num, count.denom when a & is encountered. June 4 2012 Abc2abc error messages: the following is musically correct. X:1 T: abc2abc errors M: 2/4 L: 1/8 K: Am G|ABcd|[1efg:|[2f|edcB| However, processing it through abc2abc returns many error messages. X:1 T:abc2abc errors M:2/4 L:1/8 K:Am G|ABcd| [1efg %Warning : No repeat expected, found :| %Error : Bar 2 is 3/8 not 2/4 :| [2f %Error : Bar 3 is 1/8 not 2/4 |edcB| First abc2abc complains that an opening repeat |: is missing at the beginning. Next it complains that bar 2 and 3 [1efg:|[2f| are incomplete measures. Fix: Jef Moine has contributed a ingenious fixes in toabc.c. In start_tune() the flag expect_repeat is set to -1 instead of 0 to signal the start of tune. In event_bar, there is a check that expect_repeat is greater than zero. Finally, if the number of beats in the bar does not match the time signature, the error message is suppressed for if the bar ends with :|, |:, |[1, :|[2 or :: and bar length is not reset to 0 so that it contributes to the next bar. June 04 2012 Abc2abc compliance with 2.1 standard: the abc music standard 2.0 recommended changing the syntax for decorations from !...! to +...+. Thus a mezzoforte indication should be indicated as +mf+ instead of !mf!. Abc2abc was modified on April 17 2011 to be compliant with this change. This recommendation was revoked in the 2.1 music standard, (Dec 2011) http://abcnotation.com/wiki/abc:standard:v2.1 Fix: the option to output decorations using the +...+ syntax has been removed and the default is now !...!. Any decorations using the +...+ syntax are automatically changed to !...! syntax. The flag noplus is now initialized to 1 instead of 0. The redundant runtime parameter -noplus was removed. July 03 2012 Abc2midi trill and roll problem: an attempt was made to fix the problem reported on September 11 2006. For multivoiced tunes, this can cause a loss of synchronization between the voices as illustrated in the following example. X:1 T: broken trill L:1/8 M:3/4 K:G [V:1] G>D 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 <byjang61@gmail.com>. 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.