mirror of
https://github.com/sshlien/abcmidi.git
synced 2025-12-06 15:05:07 +00:00
Compare commits
4 Commits
2022.12.27
...
2023.01.08
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d73b3682e1 | ||
|
|
c981535a2a | ||
|
|
7fae7302c3 | ||
|
|
166a28d182 |
79
doc/CHANGES
79
doc/CHANGES
@@ -14951,6 +14951,85 @@ an extra parameter, word, indicating the type of directive.
|
||||
It will issue a warning if it detects a '/' in the sound= or
|
||||
shift= directives.
|
||||
|
||||
December 30 2022
|
||||
|
||||
abcmidi: The instrument=*/c is a special directive that suppresses
|
||||
a transpose. For example:
|
||||
|
||||
X:2
|
||||
T: transpose using instrument=_B/c
|
||||
T: clarinet coded in concert pitch, displayed in Bb (as in player part)
|
||||
M: 4/4
|
||||
L: 1/4
|
||||
K: C
|
||||
V:1 nm="Flute"
|
||||
CDEF|GABc|cBAG|FEDC|
|
||||
V:2 instrument=_B/c nm="Clarinet\nin Bb"
|
||||
CDEF|GABc|cBAG|FEDC|
|
||||
|
||||
The notes in V:2 are displayed up using score=_Bc, but they are still
|
||||
played as written (sound=cc does nothing).
|
||||
Fix: the code in the block
|
||||
if (casecmp(word,"instrument") == 0 {
|
||||
...
|
||||
}
|
||||
in parsesound() (parseabc.c) was rewritten.
|
||||
|
||||
|
||||
January 05 2023
|
||||
|
||||
abc2midi: instrument =F/D transposes cdec up by 3 semitones instead of
|
||||
down by 10 semitones in the following example.
|
||||
|
||||
X:5
|
||||
T: wrong octave
|
||||
M: 4/4
|
||||
K:C
|
||||
V:1 instrument=F/D
|
||||
cdec z4
|
||||
V:2
|
||||
z4 c4
|
||||
|
||||
Fix: Hudson Lacerda supplied me with pseudo-code (doc/hudsonshift.txt)
|
||||
which describes how all the transpose directives should work.
|
||||
This code was implemented in parseSoundScore() which now replaces
|
||||
parseSound(). It also fixes yaps.
|
||||
|
||||
|
||||
January 06 2023
|
||||
|
||||
abcmidi ignores sound=cD in the following example.
|
||||
|
||||
X:2
|
||||
T: sound + score
|
||||
M: 4/4
|
||||
K:C
|
||||
V:1 sound=cD score=FD
|
||||
cdec z4
|
||||
V:2
|
||||
z4 c4
|
||||
|
||||
Analysis: *transpose is set to -10 by parseSoundScore when it
|
||||
processes sound=CD but when parseSoundScore is called again
|
||||
with score=FD it sets *transpose to 0, the initialized value
|
||||
of transp_sound. The last value of *transpose is used by
|
||||
event_voice.
|
||||
|
||||
Fix: if parseSoundScore is called by the abc2midi executable,
|
||||
then *transpose is not set to transp_sound when the score=
|
||||
directive is processed. There is a similar issue when
|
||||
parseSoundScore is called by yaps. We do not want to set
|
||||
*transpose to transp_score when the sound= is processed.
|
||||
|
||||
January 08 2023
|
||||
|
||||
abc2abc should replicate the score=, shift=, sound=, and instrument=
|
||||
directives but otherwise ignore them.
|
||||
|
||||
Fix: parseSoundScore() in parseabc.c does nothing if it is
|
||||
called from abc2abc and return 0. The function parseother(),
|
||||
which is called from parsevoice() or parsekey(), will output
|
||||
all other directives in the K: or V: command.
|
||||
|
||||
|
||||
|
||||
|
||||
57
doc/hudsonshift.txt
Executable file
57
doc/hudsonshift.txt
Executable file
@@ -0,0 +1,57 @@
|
||||
init:
|
||||
transp_sound = transp_score = 0;
|
||||
|
||||
ABC2MIDI: use transp_sound;
|
||||
YAPS: use transp_score;
|
||||
ABC2ABC: ignore and replicate instructions to output;
|
||||
|
||||
|
||||
/******************************************/
|
||||
|
||||
if (p1==0) error();
|
||||
|
||||
|
||||
sound:
|
||||
if (p2==0)
|
||||
error();
|
||||
transp_sound = p2-p1;
|
||||
/*
|
||||
sound=<note1><note2> transposes the playback according to the
|
||||
specified interval (the typeset score is not affected)
|
||||
*/
|
||||
|
||||
|
||||
score:
|
||||
if (p2==0)
|
||||
p2 = ( 72 );
|
||||
transp_score = p2-p1;
|
||||
/*
|
||||
score=<note1><note2> transposes the typeset score according to the
|
||||
specified interval (the playback is not affected); if the second note
|
||||
is omitted it is assumed to be a c (see writing abc code for
|
||||
transposing instruments)
|
||||
*/
|
||||
|
||||
|
||||
instrument:
|
||||
if (p2==0)
|
||||
p2 = p1;
|
||||
transp_score = p2-p1;
|
||||
transp_sound = p2-( 72 );
|
||||
/*
|
||||
instrument=<note1>/<note2> is defined as score=<note1><note2> sound=c<note2>
|
||||
*/
|
||||
|
||||
|
||||
shift:
|
||||
if (p2==0)
|
||||
error();
|
||||
transp_score = transp_sound = p2-p1;
|
||||
/*
|
||||
shift=<note1><note2> transposes the typeset score and the playback
|
||||
according to the specified interval
|
||||
*/
|
||||
|
||||
|
||||
/******************************************/
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
abcMIDI : abc <-> MIDI conversion utilities
|
||||
|
||||
midi2abc version 3.58 December 09 2022
|
||||
abc2midi version 4.78 December 27 2022
|
||||
abc2abc version 2.18 June 14 2022
|
||||
yaps version 1.90 June 14 2022
|
||||
abc2midi version 4.82 January 06 2023
|
||||
abc2abc version 2.19 January 08 2023
|
||||
yaps version 1.92 January 06 2023
|
||||
abcmatch version 1.82 June 14 2022
|
||||
midicopy version 1.38 May 06 2022
|
||||
midistats version 0.58 December 09 2022
|
||||
|
||||
137
parseabc.c
137
parseabc.c
@@ -942,7 +942,7 @@ int interpret_voice_label (char *s, int num, int *is_new)
|
||||
}
|
||||
|
||||
/* The following four functions parseclefs, parsetranspose,
|
||||
* parsesound, parseoctave are used to parse the K: field which not
|
||||
* parseSoundScore, 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.
|
||||
*
|
||||
@@ -1021,51 +1021,105 @@ 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 != '=')
|
||||
int parseSoundScore (char **s,
|
||||
char *word,
|
||||
int *gottranspose,
|
||||
int *transpose
|
||||
)
|
||||
/* parses sound, score, instrument, and shift
|
||||
* according to Hudson Lacerda's pseudo code file
|
||||
* doc/hudsonshift.txt.
|
||||
*/
|
||||
{
|
||||
int p1,p2;
|
||||
int transp_sound;
|
||||
int transp_score;
|
||||
|
||||
transp_sound = 0;
|
||||
transp_score = 0;
|
||||
|
||||
if (casecmp(word,"sound") != 0
|
||||
&& casecmp(word,"shift") != 0
|
||||
&& casecmp(word,"instrument") != 0
|
||||
&& casecmp(word,"score") != 0) return 0;
|
||||
|
||||
if ( fileprogram == ABC2ABC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
skipspace (s);
|
||||
if (**s != '=')
|
||||
{
|
||||
event_error ("sound must be followed by '='");
|
||||
event_error ("expecting '=' after sound, score, instrument or shift");
|
||||
return 0;
|
||||
} else {
|
||||
*s = *s + 1;
|
||||
skipspace (s);
|
||||
p1 = note2midi (s,word);
|
||||
/*printf("p1 midi note = %d\n",p1);*/
|
||||
p2 = note2midi (s,word);
|
||||
/*printf("p2 midi note = %d\n",p2);*/
|
||||
if (p1 == 0) {
|
||||
event_error ("<note1> missing. cannot do anything");
|
||||
}
|
||||
/* p2 = 0 implies that <note2> is not given */
|
||||
|
||||
if (p2 == p1) {
|
||||
p2 = 72; /* [SS] 2022.12.21 */
|
||||
}
|
||||
if (casecmp(word,"instrument") == 0) { /*2022.12.27 */
|
||||
*transpose = p1 - p2; /* [SS] 2022.02.18 2022.04.27 */
|
||||
} else {
|
||||
*transpose = p2 - p1; /* [SS] 2022.02.18 2022.04.27 */
|
||||
}
|
||||
*gottranspose = 1;
|
||||
if (casecmp(word,"sound") == 0) {
|
||||
if (p2 == 0) event_error("sound = requires <note2>");
|
||||
transp_sound = p2-p1;
|
||||
/*
|
||||
sound=<note1><note2> transposes the playback according to the
|
||||
specified interval (the typeset score is not affected)
|
||||
*/
|
||||
}
|
||||
|
||||
if (casecmp(word,"score") == 0) {
|
||||
if (p2 == 0) p2 = 72;
|
||||
transp_score = p2 - p1;
|
||||
/*
|
||||
score=<note1><note2> transposes the typeset score according to the
|
||||
specified interval (the playback is not affected); if the second note
|
||||
is omitted it is assumed to be a c (see writing abc code for
|
||||
transposing instruments)
|
||||
*/
|
||||
}
|
||||
|
||||
if (casecmp(word,"instrument") == 0) {
|
||||
if (p2 == 0) p2 = p1;
|
||||
transp_score = p2 - p1;
|
||||
transp_sound = p2 - 72;
|
||||
|
||||
/*
|
||||
instrument=<note1>/<note2> is defined as
|
||||
score=<note1><note2> sound=c<note2>
|
||||
*/
|
||||
}
|
||||
|
||||
if (casecmp(word,"shift") == 0) {
|
||||
if (p2 == 0) event_error("shift = requires <note2>");
|
||||
transp_score = p2 - p1;
|
||||
transp_sound = p2 - p1;
|
||||
/*
|
||||
shift=<note1><note2> transposes the typeset score and the playback
|
||||
according to the specified interval
|
||||
*/
|
||||
}
|
||||
|
||||
*gottranspose = 1;
|
||||
|
||||
if (fileprogram == ABC2MIDI) {
|
||||
/* [SS] 2023.01.06 */
|
||||
if (casecmp(word,"score") != 0) *transpose = transp_sound;
|
||||
}
|
||||
if (fileprogram == YAPS) {
|
||||
/* [SS] 2023.01.06 */
|
||||
if (casecmp(word,"sound") != 0) *transpose = transp_score;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
parseoctave (s, word, gotoctave, octave)
|
||||
@@ -1412,7 +1466,7 @@ parsekey (str)
|
||||
parsed = parseoctave (&s, word, &gotoctave, &octave);
|
||||
|
||||
if (!parsed)
|
||||
parsed = parsesound (&s, word, &gottranspose, &transpose);
|
||||
parsed = parseSoundScore (&s, word, &gottranspose, &transpose);
|
||||
|
||||
if ((parsed == 0) && (casecmp (word, "Hp") == 0))
|
||||
{
|
||||
@@ -1659,7 +1713,7 @@ parsevoice (s)
|
||||
if (!parsed)
|
||||
parsed = parseoctave (&s, word, &vparams.gotoctave, &vparams.octave);
|
||||
if (!parsed)
|
||||
parsed = parsesound (&s, word, &vparams.gottranspose, &vparams.transpose);
|
||||
parsed = parseSoundScore (&s, word, &vparams.gottranspose, &vparams.transpose);
|
||||
/* Code changed JA 20 May 2022 */
|
||||
if ((!parsed) && (strcasecmp (word, "name") == 0)) {
|
||||
parsed =
|
||||
@@ -2752,8 +2806,7 @@ return p;
|
||||
|
||||
|
||||
/* [SS] 2021-10-11 */
|
||||
int
|
||||
note2midi (char** s, char *word)
|
||||
int note2midi (char** s, char *word)
|
||||
{
|
||||
/* for implementing sound=, shift= and instrument= key signature options */
|
||||
|
||||
@@ -2865,7 +2918,7 @@ switch (**s)
|
||||
}
|
||||
if (note == ' ')
|
||||
{
|
||||
event_error ("Malformed note : expecting a-g or A-G");
|
||||
return 0;
|
||||
}
|
||||
pitch = pitch2midi(note, accidental, mult, octave);
|
||||
return pitch;
|
||||
|
||||
2
store.c
2
store.c
@@ -186,7 +186,7 @@ int main()
|
||||
|
||||
*/
|
||||
|
||||
#define VERSION "4.78 December 27 2022 abc2midi"
|
||||
#define VERSION "4.82 January 06 2023 abc2midi"
|
||||
|
||||
/* enables reading V: indication in header */
|
||||
#define XTEN1 1
|
||||
|
||||
2
toabc.c
2
toabc.c
@@ -21,7 +21,7 @@
|
||||
|
||||
/* back-end for outputting (possibly modified) abc */
|
||||
|
||||
#define VERSION "2.18 June 14 2022 abc2abc"
|
||||
#define VERSION "2.19 Jan 08 2022 abc2abc"
|
||||
|
||||
/* for Microsoft Visual C++ 6.0 or higher */
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/* yapstree.c - back-end for abc parser. */
|
||||
/* generates a data structure suitable for typeset music */
|
||||
|
||||
#define VERSION "1.90 June 14 2022 yaps"
|
||||
#define VERSION "1.92 January 06 2023 yaps"
|
||||
#include <stdio.h>
|
||||
#ifdef USE_INDEX
|
||||
#define strchr index
|
||||
|
||||
Reference in New Issue
Block a user