mirror of
https://github.com/sshlien/abcmidi.git
synced 2025-12-08 10:41:02 +00:00
Compare commits
5 Commits
2021.05.10
...
2021.06.24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
504cbe93f7 | ||
|
|
1105ee0c8b | ||
|
|
62506f6ac3 | ||
|
|
538896e1b9 | ||
|
|
dcfa5cc7ad |
@@ -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>
|
||||
|
||||
73
doc/CHANGES
73
doc/CHANGES
@@ -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().
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
13
midi2abc.c
13
midi2abc.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
76
parseabc.c
76
parseabc.c
@@ -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)
|
||||
{
|
||||
@@ -1261,7 +1271,17 @@ static void process_microtones (int *parsed, char word[],
|
||||
modmicrotone[j].denom = b;
|
||||
/* printf("%c microtone = %d/%d\n",modmap[j],modmicrotone[j].num,modmicrotone[j].denom); */
|
||||
}
|
||||
} /* finished ^ = _ */
|
||||
} /* finished ^ = _ */
|
||||
|
||||
static void set_voice_from_master(int voice_num)
|
||||
{
|
||||
voice_context_t *current_voice;
|
||||
|
||||
current_voice = &voicecode[voice_num - 1];
|
||||
copy_timesig(¤t_voice->timesig, &master_timesig);
|
||||
copy_clef(¤t_voice->clef, &master_clef);
|
||||
current_voice->unitlen = master_unitlen;
|
||||
}
|
||||
|
||||
int
|
||||
parsekey (str)
|
||||
@@ -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(¤t_voice->timesig, &master_timesig);
|
||||
copy_clef(¤t_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
21
store.c
@@ -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
26
toabc.c
@@ -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(
|
||||
¤t_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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user