2021.10.11

This commit is contained in:
Seymour Shlien
2021-10-12 09:09:45 -04:00
parent c9d2c0f33b
commit e9c2aee88b
5 changed files with 252 additions and 6 deletions

View File

@@ -1,2 +1,2 @@
2021 September 15 2021
2021 October 11 2021

View File

@@ -14379,3 +14379,50 @@ 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|

View File

@@ -1,7 +1,7 @@
abcMIDI : abc <-> MIDI conversion utilities
midi2abc version 3.48 June 27 2021
abc2midi version 4.60 September 15 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
@@ -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

@@ -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.60 September 15 2021 abc2midi"
#define VERSION "4.61 October 11 2021 abc2midi"
/* enables reading V: indication in header */
#define XTEN1 1