Compare commits

..

5 Commits

Author SHA1 Message Date
Seymour Shlien
504cbe93f7 2021.06.24 2021-06-24 14:37:48 -04:00
Seymour Shlien
1105ee0c8b 2021.05.25 2021-05-26 15:50:57 -04:00
Seymour Shlien
62506f6ac3 2021.05.24 2021-05-24 13:57:28 -04:00
Seymour Shlien
538896e1b9 2021.05.21 2021-05-23 10:03:30 -04:00
Seymour Shlien
dcfa5cc7ad 2021.05.19 2021-05-19 09:46:57 -04:00
10 changed files with 229 additions and 80 deletions

View File

@@ -1,2 +1,2 @@
2021 May 10 2021
2021 June 24 2021

View File

@@ -49,7 +49,7 @@ Matching:
#define VERSION "1.78 March 27 2021 abcmatch"
#define VERSION "1.79 May 25 2021 abcmatch"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

View File

@@ -14204,3 +14204,76 @@ argument is not a power of 2. Fix: changed the return
to -1. The program does not crash but the midi file
is not created correctly.
May 19 2020
abc2midi: the following file causes abc2midi to hang.
X:1
T: Hangs abc2midi
L:1/4
K:C
2c/2fac'/c'/c'/c'/c'///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
James Allwright intoduced a fix in readlen() in parseabc.c
May 22 2021
abc2midi: treble-8 not applied in K: or V: commands after October 19 2020
update. For example,
X:1
T: transposition
L:1/2
M:C
K:none clef=treble-8
V:1
cz
V:2
zc
The note c should be played with midi pitch 60 instead of 72.
James Allwright made minor fixes to parseabc.c and store.c, in order
to get these options working again.
May 25 2021
James Allwright added more security checks to stop the
parser from reading numbers beyond the largest integer. Changes
were made to parserabc.c and midi2abc.c
The abc2abc -s spacing function was modified to ignore certain
time signatures like M: none or M:7/8. The code for dealing with
3/2, 3/4, 3/8 ... time signatures was improved.
June 24 2021
abc2midi bug: in the following sample
X:1
T: octave
M: 2/4
L: 1/8
K: none octave=1
V:1
C4|
V:2
C4|
The octave=1 applies only to voice 1 and does not
act as global variable applying to both voices.
Analysis: event_octave either sets global.octaveshift or
v.octaveshift depending upon the variable pastheader. Pastheader
was set to 1 by headerprocess() in event_key() prior to calling
event_octave which prevented global.octaveshift from being set.
Fix: moved headerprocess(), getvoicecontext(), etc to after
calling event_octave().

View File

@@ -1,10 +1,11 @@
Guide to writing abc for abc2midi
---------------------------------
Guide to writing abc for abc2midi - minor revision [JA] 2021-05-24
--------------------------------------------------------------
Updated June 1 2017. %%MIDI program ranges from 0 to 127 not 1 to 128.
The defining document for abc is the abc version 1.6 specification which can
be found at http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt . This document
is a description of abc as interpreted by abc2midi.
The abc notation language is described by the version 1.6 specification
document and later modifications to this document referred to as
version 2.1 and version 2.2. These can be found at abcnotation.com .
An abc tune consists of a header followed by a body. Each line in the
header is a different field starting with a letter immediately followed
@@ -160,15 +161,43 @@ K:G clef=soprano octave=-1 transpose=-1
The clef is recognized by typesetting programs such as yaps and abc2mps
and in some situations it will cause abc2midi to transpose the notes
up or down by an octave. Recognized clefs are treble,
bass, baritone, tenor, alto, mezzo and soprano. There are also variants
of these clefs; treble-8, tenor-8, treble+8 covering ranges which are an
octave below and an octave above the normal treble clef. Other
variants are not recognized at this time. No transposition is
assumed for the bass clef since many abc files enter the notes
with all the commas.
bass, baritone, tenor, alto, mezzo and soprano.
The octave specifier is a convenience to make entering music easier.
It allows the user to avoid repeatedly entering commas or apostrophes
Clefs with +8, -8:
Sometimes, you will find written music where there is a treble clef (or
some other clef) with a small 8. The meaning is that every note is to
be played an octave higher than shown. Suppose you notate the abc note A
using a treble clef. This appears as a note between the second and third
lines from the bottom of the stave. Then with a treble+8 clef (which looks
exactly the same except that it has a small 8), a note at the same position
on the stave lines is now played as abc note a (which is normally put on
a line one line up from the top line of the stave). Similarly, the
treble-8 clef indicates that every note is to be played an octave lower
than shown, so note A would be played as A, .
The abc standard versions 2.1 and 2.2 support this idea, but the way
the abc notation is interpreted changes when you have clef=treble+8.
With clef=treble+8, every stave position is interpreted as being an
octave higher than if you had clef=treble e.g. the note that sounds as
a does in normal abc is written as A in abc with clef=treble+8.
The overall effect of this is that when you change a passage from
clef=treble to clef=treble+8, without editing any of the notes, every
note appears at exactly the same place on the stave lines as it did
before, but it is played an octave higher.
The benefit of this change in interpretation is that you can notate
very high or very low passages in abc without having to use lots of
' or , characters.
The octave specifier is a convenience to make entering music easier,
developed before the +8/-8 clef modifier and still supported. However,
to be compatible with other abc programs, it is recommended that you
use the clef modifier. The syntax
I:octave=<offset in octaves>
allows the user to avoid repeatedly entering commas or apostrophes
when entering a sequence of low or high notes. Both yaps and abc2midi
will transpose the notes by the specified number of octaves during
the parsing stage.
@@ -180,9 +209,10 @@ e.g. the passage B,,, C,, D,, E,, F,, could be written more compactly as
I:octave=0
Some instruments such as the Bb clarinet automatically transpose the
written music. For example in the case of the clarinet, the music is
written in the key of C but the instrument plays it in the key of Bb.
Some instruments such as the Bb clarinet are by classical convention
considered to transpose the written music. For example in the case of
the clarinet, the music is written in the key of C but the instrument
plays it in the key of Bb.
For multivoiced tunes, the %%MIDI transpose indication is not that useful
since it transposes all the voices by the specified amount. The
transpose=n subcommand in the K: field tells abc2midi to transpose

View File

@@ -1,10 +1,10 @@
abcMIDI : abc <-> MIDI conversion utilities
midi2abc version 3.47 November 01 2020
abc2midi version 4.54 May 10 2021
abc2abc version 2.13 May 08 2021
yaps version 1.86 December 10 2020
abcmatch version 1.78 March 27 2021
midi2abc version 3.47 May 25 2021
abc2midi version 4.58 June 24 2021
abc2abc version 2.15 May 25 2021
yaps version 1.87 May 25 2021
abcmatch version 1.79 May 25 2021
midicopy version 1.37 October 10 2020
24th January 2002
@@ -14,7 +14,7 @@ J.R.Allwright@westminster.ac.uk
University of Westminster,
London, UK
November 2020
June 2021
Seymour Shlien
Ottawa, Canada

View File

@@ -45,8 +45,9 @@
* based on public domain 'midifilelib' package.
*/
#define VERSION "3.47 November 01 2020 midi2abc"
#define VERSION "3.48 May 25 2021 midi2abc"
#include <limits.h>
/* Microsoft Visual C++ Version 6.0 or higher */
#ifdef _MSC_VER
#define snprintf _snprintf
@@ -3451,7 +3452,8 @@ char *num;
p = p + 1;
neg = -1;
};
while (((int)*p >= '0') && ((int)*p <= '9')) {
/* [JA] 2021-05-25 */
while (((int)*p >= '0') && ((int)*p <= '9') && (t < (INT_MAX-9)/10)) {
t = t * 10 + (int) *p - '0';
p = p + 1;
};
@@ -3467,10 +3469,15 @@ char **p;
int t;
t = 0;
while (((int)**p >= '0') && ((int)**p <= '9')) {
/* [JA] 2021-05-25 */
while (((int)**p >= '0') && ((int)**p <= '9') && (t < (INT_MAX-9)/10)) {
t = t * 10 + (int) **p - '0';
*p = *p + 1;
};
/* advance over any spurious extra digits */
while (isdigit(**p)) {
*p = *p + 1;
}
return t;
}

View File

@@ -37,6 +37,7 @@
#include <stdlib.h>
/* [JM] 2018-02-22 to handle strncasecmp() */
#include <string.h>
#include <limits.h>
/* #define SIZE_ABBREVIATIONS ('Z' - 'H' + 1) [SS] 2016-09-20 */
#define SIZE_ABBREVIATIONS 58
@@ -348,11 +349,15 @@ readnumf (num)
event_error ("Missing Number");
};
t = 0;
while (((int) *p >= '0') && ((int) *p <= '9'))
/* [JA] 2021-05-25 */
while (((int) *p >= '0') && ((int) *p <= '9') && (t < (INT_MAX-9)/10))
{
t = t * 10 + (int) *p - '0';
p = p + 1;
};
if (t >= (INT_MAX-9)/10) { /* [JA] 2021-05-25 */
event_error ("Number too big");
}
return (t);
}
@@ -384,11 +389,16 @@ readnump (p)
int t;
t = 0;
while (((int) **p >= '0') && ((int) **p <= '9'))
/* [JA] 2021-05-25 */
while (((int) **p >= '0') && ((int) **p <= '9') && (t < (INT_MAX-9)/10))
{
t = t * 10 + (int) **p - '0';
*p = *p + 1;
};
}
/* advance over any spurious extra digits [JA] 2021-05-25 */
while (isdigit(**p)) {
*p = *p + 1;
}
return (t);
}
@@ -543,37 +553,37 @@ void readsig (char **sig, timesig_details_t *timesig)
}
}
void
readlen (a, b, p)
int *a, *b;
char **p;
void readlen (int *a, int *b, char **p)
/* read length part of a note and advance character pointer */
{
int t;
*a = readnump (p);
if (*a == 0)
{
if (*a == 0) {
*a = 1;
};
}
*b = 1;
if (**p == '/')
{
if (**p == '/') {
*p = *p + 1;
*b = readnump (p);
if (*b == 0)
{
if (*b == 0) {
*b = 2;
while (**p == '/')
{
/* [JA] 2021-05-19 prevent infinite loop */
/* limit the number of '/'s we support */
while ((**p == '/') && (*b < 1024)) {
*b = *b * 2;
*p = *p + 1;
};
};
};
}
if (*b >= 1024) {
event_warning ("Exceeded maximum note denominator");
}
}
}
*b = check_power_of_two(*b);
}
/* [JA] 2020-12-10 */
static void read_L_unitlen(int *num, int *denom, char **place)
{
@@ -1263,6 +1273,16 @@ static void process_microtones (int *parsed, char word[],
}
} /* finished ^ = _ */
static void set_voice_from_master(int voice_num)
{
voice_context_t *current_voice;
current_voice = &voicecode[voice_num - 1];
copy_timesig(&current_voice->timesig, &master_timesig);
copy_clef(&current_voice->clef, &master_clef);
current_voice->unitlen = master_unitlen;
}
int
parsekey (str)
/* parse contents of K: field */
@@ -1345,7 +1365,7 @@ parsekey (str)
while (*s != '\0')
{
parsed = parseclef (&s, word, &gotclef, clefstr, &newclef, &cgotoctave, &coctave);
if (gotclef) {
if (parsed) { /* [JA] 2021-05-21 changed (gotclef) to (parsed) */
/* make clef an attribute of current voice */
if (inhead) {
copy_clef (&master_clef, &newclef);
@@ -1550,16 +1570,6 @@ parsekey (str)
return (gotkey);
}
static void set_voice_from_master(int voice_num)
{
voice_context_t *current_voice;
current_voice = &voicecode[voice_num - 1];
copy_timesig(&current_voice->timesig, &master_timesig);
copy_clef(&current_voice->clef, &master_clef);
current_voice->unitlen = master_unitlen;
}
void
parsevoice (s)
char *s;
@@ -2306,10 +2316,12 @@ parsefield (key, field)
* if L: fields was missing in the header.
*/
resolve_unitlen();
}
foundkey = parsekey (place); /* [JA] 2021.05.21 parsekey called before set_voice_from_master(1) */
if (inhead) {
/* set voice parameters using values from header */
set_voice_from_master(1);
}
foundkey = parsekey (place);
if (inhead || inbody) {
if (foundkey)
{

21
store.c
View File

@@ -186,7 +186,7 @@ int main()
*/
#define VERSION "4.54 May 10 2021 abc2midi"
#define VERSION "4.58 June 24 2021 abc2midi"
/* enables reading V: indication in header */
#define XTEN1 1
@@ -4300,7 +4300,11 @@ int xoctave, n, m;
event_fatal_error("Internal error - no voice allocated");
};
if (gracenotes && ignore_gracenotes) return; /* [SS] 2010-01-08 */
if (v->octaveshift == 0) { /* [JA] 2021-05-21 */
octave = xoctave + clef->octave_offset;
} else {
octave = xoctave + v->octaveshift;
}
num = n;
denom = m;
if (v->inchord) v->chordcount = v->chordcount + 1;
@@ -5953,11 +5957,13 @@ int explict;
copymap(&global);
sf = sharps;
mi = minor;
headerprocess();
v = getvoicecontext(1);
if (!inbody) v1index = notes; /* save position in case of split voice */
};
/* [SS] 2021-06-24
***headerprocess();
***v = getvoicecontext(1);
***if (!inbody) v1index = notes; /* save position in case of split voice */
if (gotclef)
{
event_octave(clef->octave_offset, 0);
@@ -5965,6 +5971,11 @@ int explict;
if (gotoctave) {
event_octave(octave,0);
};
/* [SS] 2021-06-24 */
headerprocess();
v = getvoicecontext(1);
if (!inbody) v1index = notes; /* save position in case of split voice */
};
};
}

26
toabc.c
View File

@@ -21,7 +21,7 @@
/* back-end for outputting (possibly modified) abc */
#define VERSION "2.14 May 09 2021 abc2abc"
#define VERSION "2.15 May 25 2021 abc2abc"
/* for Microsoft Visual C++ 6.0 or higher */
#ifdef _MSC_VER
@@ -84,6 +84,7 @@ struct fract breakpoint; /* used to break bar into beamed sets of notes */
complex_barpoint_t master_bar_break;
int barno; /* number of bar within tune */
int newspacing; /* was -s option selected ? */
int have_spacing_scheme; /* do we support spacing for time signature ? [JA] */
int barcheck; /* indicate -b and -r options selected */
int echeck; /* was error-checking turned off ? (-e option) */
int newbreaks; /* was -n option selected ? */
@@ -575,6 +576,7 @@ char** filename;
} else {
newspacing = 1;
};
have_spacing_scheme = 0; /* [JA] 2021-05-25 */
narg = getarg("-X", argc, argv);
if (narg == -1) {
newrefnos = 0;
@@ -1414,6 +1416,7 @@ static void set_complex_barpoint(timesig_details_t *timesig,
void event_timesig (timesig)
timesig_details_t *timesig;
{
have_spacing_scheme = 0; /* default to no new spacing */
emit_string ( "M:");
switch (timesig->type) {
default:
@@ -1459,6 +1462,7 @@ void event_timesig (timesig)
set_complex_barpoint(
&current_voice->timesig, &toabc_voice->bar_break);
}
have_spacing_scheme = 1; /* [JA] 2021-05-25 */
}
break;
}
@@ -1470,16 +1474,28 @@ void event_timesig (timesig)
breakpoint.num = timesig->num;
breakpoint.denom = timesig->denom;
if (timesig->num == 3) { /* [JA] 2021-05-25 */
/* handles 3/2, 3/4, 3/8 */
breakpoint.num = timesig->num / 3;
breakpoint.denom = timesig->denom;
have_spacing_scheme = 1;
}
if ((timesig->num == 9) || (timesig->num == 6)) {
breakpoint.num = 3;
breakpoint.denom = barlen.denom;
have_spacing_scheme = 1;
};
if (timesig->num % 2 == 0) {
breakpoint.num = barlen.num / 2;
breakpoint.denom = barlen.denom;
have_spacing_scheme = 1;
};
barend = timesig->num / breakpoint.num;
}
if (newspacing && !have_spacing_scheme) {
/* [JA] 2021-05-25 */
event_warning ("Do not know how to group notes in this time signature");
}
inmusic = 0;
}
@@ -1874,7 +1890,7 @@ char* replist;
void event_space()
{
if (!newspacing) {
if (!(newspacing && have_spacing_scheme)) {
emit_string(" ");
};
}
@@ -1929,7 +1945,7 @@ int n, q, r;
if (tuplenotes != 0) {
event_error("tuple within tuple not allowed");
};
if (newspacing) {
if (newspacing && have_spacing_scheme) {
emit_char(' ');
}
emit_int_sprintf("(%d", n);
@@ -2504,7 +2520,7 @@ int xoctave, n, m;
if ((!ingrace) && (!inchord)) {
addunits(n, m);
};
if (newspacing) {
if (newspacing && have_spacing_scheme) {
consider_break_after_note(prev_tuplenotes);
};
}
@@ -2594,7 +2610,7 @@ int xoctave, n, m;
if ((!ingrace) && (!inchord)) {
addunits(n, m);
};
if (newspacing) {
if (newspacing && have_spacing_scheme) {
barpoint.num = count.num * breakpoint.denom;
barpoint.denom = breakpoint.num * count.denom;
reduce(&barpoint.num, &barpoint.denom);

View File

@@ -22,7 +22,7 @@
/* yapstree.c - back-end for abc parser. */
/* generates a data structure suitable for typeset music */
#define VERSION "1.86 December 10 2020 yaps"
#define VERSION "1.87 May 25 2021 yaps"
#include <stdio.h>
#ifdef USE_INDEX
#define strchr index