Compare commits

..

4 Commits

Author SHA1 Message Date
Seymour Shlien
fcae03ab71 2021.11.25 2021-11-25 13:00:06 -05:00
Seymour Shlien
e9c2aee88b 2021.10.11 2021-10-12 09:09:45 -04:00
Seymour Shlien
c9d2c0f33b 2021.09.15 2021-09-15 16:25:29 -04:00
Seymour Shlien
19fbb6b7e7 2021.06.27 2021-06-27 17:09:51 -04:00
8 changed files with 430 additions and 13 deletions

View File

@@ -1,2 +1,2 @@
2021 June 24 2021
2021 November 25 2021

View File

@@ -49,7 +49,7 @@ Matching:
#define VERSION "1.79 May 25 2021 abcmatch"
#define VERSION "1.80 Novemeber 25 2021 abcmatch"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
@@ -274,7 +274,7 @@ make_note_representation (int *nnotes, int *nbars, int maxnotes, int maxbars,
these bar line indications. Note bar numbering starts
from 0. [SS] 2013-11-17
*/
if (*nbars >0 && *nnotes > 0) { /* 2021-03-27 */
if (*nnotes > 0) { /* [SS] 2021-11-25 */
midipitch[*nnotes] = BAR;
notelength[*nnotes] = BAR;
(*nnotes)++;

View File

@@ -14277,3 +14277,217 @@ Fix: moved headerprocess(), getvoicecontext(), etc to after
calling event_octave().
June 27 2021
midi2abc: bug
For some midi files midi2abc returns something like this
X: 1
T: from gchordbreakdown1.mid
M: 4/4
L: 1/8
Q:1/4=120
K:C % 0 sharps
V:1
K:E % 16 sharps
=c=d e=g e4| \
Analysis, in the function handletext(), the local variable sf is
declared as an integer but not initialized. The function
sscanf(str,"%d %d",&sf,&mi);
attempts to read sf and mi from str, but str does not contain
any integers, and sf is not changed.
Temporary fix: initialized sf to 0.
June 27 2021
abc2midi: %%MIDI gchordoff produces garbage. In the following file
X:1
T: gchord breakdown
M: 4/4
L: 1/8
Q:1/4=120
K:C
%%MIDI gchord ghi2ihi2
%%MIDI gchordoff
"C" cd eg e4 |"Am" ag ag e4 |
%%MIDI gchordon
"Dm" defe d4 | "G7" g6z2 |
The output in track 2 as seen by midi2abc looks like this.
X: 1
T: from gchordbreakdown1.mid
M: 4/4
L: 1/8
Q:1/4=120
K:C % 0 sharps
V:1
cd eg e4| \
ag ag e4| \
de fe d4| \
g6
V:2
F,,,,F,,,, F,,,,2 F,,,,F,,,, F,,,,2| \
F,,,,F,,,, F,,,,2 F,,,,F,,,, F,,,,2| \
D,F, A,2 A,F, A,2| \
G,B, D2 DB, D2|
instead of
X: 1
T: from gchordbreakdown1.mid
M: 4/4
L: 1/8
Q:1/4=120
K:C % 0 sharps
V:1
cd eg e4| \
ag ag e4| \
de fe d4| \
g6
V:2
z8| \
z8| \
D,F, A,2 A,F, A,2| \
G,B, D2 DB, D2|
Analysis: abc2midi works correctly without the
%%MIDI gchord ghi2ihi2
declaration. The problem occurs in the function dogchords().
This function was expanded to handle alberti starting from May 1 2004.
Unfortunately, the fix introduced in 2016-01-03 introduced this
problem when %%MIDI gchordoff sets gchords to 0. The else branch
outputs gchordnotes[gchordnotes_size] when in fact, no note should
be queued out.
Fix: prefixed the switch(action) statement with the line
if (gchords) /* [SS] 2021-06-27 */
preventing any note output when gchords is 0.
In addition, the case 'b' was missing a break, allowing the switch statement
to continue to case 'c' and causing a different problem when
%%MIDI gchord ffbb
September 15 2021
abc2midi bug:
The last fix in June 27 2021 inserting a break introduced a new bug.
The chord associated with the 'b' gchord code was missing. b and f
codes were indistinguishable. Fix: removed the break in the switch
statement for case b:
October 11 2021
abc2midi new feature:
In compliance with the ABC draft standard 2.2, I introduced additional
K: and V: options for transposition. You can now indicate the number
of semitones to transpose by giving the original note and the
corresponding transposed note in the K: or V: field using either
shift = note1note2
sound = note1note2
instrument = note1/note2
The number of semitones is determined by the difference note2 - note1.
Abcm2ps and abc2svg recognize this command, but abc2abc, yaps, and
abcmatch ignore this new option.
http://abcnotation.com/wiki/abc:standard:v2.2#transposition
Here is a test sample:
X:1
T: standard 2.2 transposition
M: 4/4
L: 1/4
K: C
V:1
Bcde|Bcde|
V:2
Bcde|Bcde|
V:1 shift = Bc
Bcde|Bcde|
V:2
Bcde|Bcde|
V:1 sound = dc
Bcde|Bcde|
V:2
Bcde|Bcde|
V:1 instrument = c/^D
Bcde|Bcde|
V:2
Bcde|Bcde|
V:1 transpose = 0
Bcde|Bcde|
V:2 shift=DE,
Bcde|Bcde|
October 15 2021
Abc2abc -P bug
X:1
T: P bug
M:4/4
L:1/4
V:1 clef=treble
V:2 clef=bass
%%staves [1 2]
K:C
V:1
C2 D2 | C4 |
V:2
C,2 G,2 | C,4|
The command
abc2abc t.abc -t 3 -P 1
fails to transpose voice 1
This bug has been around since this option was introduced in June 7 2011.
Fortunately, it has not bothered anyone until recently.
If you add another K:c after the first V:1 command in the body as
shown below.
X:1
T: P bug
M:4/4
L:1/4
V:1 clef=treble
V:2 clef=bass
%%staves [1 2]
K:C
V:1
K:C
C2 D2 | C4 |
V:2
C,2 G,2 | C,4|
then voice 1 will be transposed correctly. Unfortunately, there is
no easy fix. When the -P option is present, abc2abc ignores the
first K: field command. (In toabc.c line 1643 event_key aborts
prior to setting up the arrays for a key transpose. Commenting
out this return statement introduces another problem.)
The main issue is that abc2abc only does one pass through the
input file. It does not know whether there is a K: field command
following V:1. If it assumes that there is none and forces a
call to event_key in event_voice, there may be another problem
when a different K: field command is found eventually. I have
decided to suspend support to the -P option because it would be
too complicated to fix this.
November 25 2021
abcmatch bug. The fix on 2021-03-27 made abcmatch non-operable. The
number of bars *nbars is never incremented. The line was replaced
with
if (*nnotes > 0) { /* [SS] 2021-11-25 */
in the function make_note_representation(...)

View File

@@ -1,10 +1,10 @@
abcMIDI : abc <-> MIDI conversion utilities
midi2abc version 3.47 May 25 2021
abc2midi version 4.58 June 24 2021
midi2abc version 3.48 June 27 2021
abc2midi version 4.61 October 11 2021
abc2abc version 2.15 May 25 2021
yaps version 1.87 May 25 2021
abcmatch version 1.79 May 25 2021
abcmatch version 1.80 November 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
June 2021
October 2021
Seymour Shlien
Ottawa, Canada

View File

@@ -2389,6 +2389,7 @@ int j;
if ((chordnum == -1) && (action == 'c')) {
action = 'f';
};
if (gchords) /* [SS] 2021-06-27 */
switch (action) {
case 'z':
@@ -2411,8 +2412,9 @@ int j;
save_note(g_num*len, g_denom, basepitch+fun.base, 8192, fun.chan, fun.vel);
else
save_note(g_num*len, g_denom, inversion+fun.base, 8192, fun.chan, fun.vel);
};
/* There is no break here so the switch statement continues into the next case 'c' */
}
/* break; * [SS] 2021-06-27 2021-09-15 */
/* There should not be a break here so the switch statement continues into the next case 'c' */
case 'c':
/* do chord with handling of any 'inversion' note */

View File

@@ -45,7 +45,7 @@
* based on public domain 'midifilelib' package.
*/
#define VERSION "3.48 May 25 2021 midi2abc"
#define VERSION "3.49 June 27 2021 midi2abc"
#include <limits.h>
/* Microsoft Visual C++ Version 6.0 or higher */
@@ -2739,6 +2739,8 @@ int trackno;
char ch;
int type,sf,mi,nn,denom,bb;
sf = 0; /* [SS] 2021-06-27 */
while (((*textplace) != NULL) && ((*textplace)->when <= t)) {
str = (*textplace)->text;
ch = *str;

View File

@@ -81,6 +81,7 @@ extern char *malloc ();
extern char *strchr ();
#endif
int note2midi (char** s);
int lineno;
int parsing_started = 0;
int parsing, slur;
@@ -939,8 +940,8 @@ int interpret_voice_label (char *s, int num, int *is_new)
return num_voices;
}
/* The following three functions parseclefs, parsetranspose,
* parseoctave are used to parse the K: field which not
/* The following four functions parseclefs, parsetranspose,
* parsesound, parseoctave are used to parse the K: field which not
* only specifies the key signature but also other descriptors
* used for producing a midi file or postscript file.
*
@@ -1019,6 +1020,49 @@ parsetranspose (s, word, gottranspose, transpose)
return 1;
};
/* [SS] 2021-10-11 */
int
parsesound (s, word, gottranspose, transpose)
/* parses string sound =
shift =
instrument = note1note2 or note1/note2
for parsekey() or parsevoice()
and returns the transpose value
*/
char **s;
char *word;
int *gottranspose;
int *transpose;
{
int p1,p2;
if (casecmp(word,"sound") != 0
&& casecmp(word,"shift") != 0
&& casecmp(word,"instrument") != 0
)
return 0;
skipspace (s);
if (**s != '=')
{
event_error ("sound must be followed by '='");
return 0;
} else {
*s = *s + 1;
skipspace (s);
p1 = note2midi (s);
/* printf("midi note = %d\n",p1); */
p2 = note2midi (s);
if (p2 == p1) {
*gottranspose = 0;
*transpose = 0;
} else {
/* printf("midi note = %d\n",p2); */
*transpose = p2 - p1;
/* printf("transpose = %d\n",*transpose); */
*gottranspose = 1;
}
}
return 1;
}
int
parseoctave (s, word, gotoctave, octave)
@@ -1382,6 +1426,9 @@ parsekey (str)
if (!parsed)
parsed = parseoctave (&s, word, &gotoctave, &octave);
if (!parsed)
parsed = parsesound (&s, word, &gottranspose, &transpose);
if ((parsed == 0) && (casecmp (word, "Hp") == 0))
{
sf = 2;
@@ -1623,6 +1670,8 @@ parsevoice (s)
&vparams.transpose);
if (!parsed)
parsed = parseoctave (&s, word, &vparams.gotoctave, &vparams.octave);
if (!parsed)
parsed = parsesound (&s, word, &vparams.gottranspose, &vparams.transpose);
if (!parsed)
parsed =
parsename (&s, word, &vparams.gotname, vparams.namestring,
@@ -2661,6 +2710,156 @@ static void check_and_call_bar(int bar_type, char *replist)
event_bar (bar_type, replist);
}
/* [SS] 2021-10-11 */
static int pitch2midi(note, accidental, mult, octave )
/* computes MIDI pitch for note.
*/
char note, accidental;
int mult, octave;
{
int p;
char acc;
int mul, noteno;
int pitch;
static int scale[7] = {0, 2, 4, 5, 7, 9, 11};
static const char *anoctave = "cdefgab";
acc = accidental;
mul = mult;
noteno = (int)note - 'a';
p = (int) ((long) strchr(anoctave, note) - (long) anoctave);
p = scale[p];
if (acc == '^') p = p + mul;
if (acc == '_') p = p - mul;
p = p + 12*octave + 60;
return p;
}
/* [SS] 2021-10-11 */
int
note2midi (char** s)
{
/* for implementing sound=, shift= and instrument= key signature options */
/* check for accidentals */
char note, accidental;
char msg[80];
int octave;
int mult;
int pitch;
/*printf("note2midi: %c\n",**s); */
if (**s == '\0') return 72;
mult = 1;
accidental = ' ';
switch (**s)
{
case '_':
accidental = **s;
*s = *s + 1;
if (**s == '_')
{
*s = *s + 1;
mult = 2;
};
break;
case '^':
accidental = **s;
*s = *s + 1;
if (**s == '^')
{
*s = *s + 1;
mult = 2;
};
break;
case '=':
accidental = **s;
*s = *s + 1;
break;
default:
break;
};
if ((**s >= 'a') && (**s <= 'g'))
{
note = **s;
octave = 1;
*s = *s + 1;
while ((**s == '\'') || (**s == ',') || (**s == '/'))
{
if (**s == '\'')
{
octave = octave + 1;
*s = *s + 1;
};
if (**s == ',')
{
sprintf (msg, "Bad pitch specifier , after note %c", note);
event_error (msg);
octave = octave - 1;
*s = *s + 1;
};
if (**s == '/')
{
/* skip / which occurs in instrument = command */
*s = *s + 1;
/* printf("note = %c accidental = %c mult = %d octave= %d \n",note,accidental,mult,octave); */
pitch = pitch2midi(note, accidental, mult, octave);
return pitch;
}
};
}
else
{
octave = 0;
if ((**s >= 'A') && (**s <= 'G'))
{
note = **s + 'a' - 'A';
*s = *s + 1;
while ((**s == '\'') || (**s == ',') || (**s == '/'))
{
if (**s == ',')
{
octave = octave - 1;
*s = *s + 1;
};
if (**s == '\'')
{
sprintf (msg, "Bad pitch specifier ' after note %c",
note + 'A' - 'a');
event_error (msg);
octave = octave + 1;
*s = *s + 1;
};
if (**s == '/')
{
/* skip / which occurs in instrument = command */
*s = *s + 1;
/* printf("note = %c accidental = %c mult = %d octave= %d \n",note,accidental,mult,octave); */
pitch = pitch2midi(note, accidental, mult, octave);
return pitch;
};
};
};
/* printf("note = %c accidental = %c mult = %d octave= %d \n",note,accidental,mult,octave); */
}
if (note == ' ')
{
event_error ("Malformed note : expecting a-g or A-G");
}
pitch = pitch2midi(note, accidental, mult, octave);
return pitch;
}
void
parsemusic (field)
char *field;

View File

@@ -186,7 +186,7 @@ int main()
*/
#define VERSION "4.58 June 24 2021 abc2midi"
#define VERSION "4.61 October 11 2021 abc2midi"
/* enables reading V: indication in header */
#define XTEN1 1