2020-07-26

This commit is contained in:
Seymour Shlien
2020-07-27 11:59:09 -04:00
parent 0e68274e42
commit 79b52cdfdc
4 changed files with 131 additions and 80 deletions

View File

@@ -1,2 +1,2 @@
2020 June 30 2020 2020 July 26 2020

View File

@@ -13754,3 +13754,34 @@ changed
lineno = (long)(ft->item); lineno = (long)(ft->item);
etc. etc.
July 17 2020
store.c: in order to improve the accuracy of the MIDI temperamentequal
and MIDI temperamentlinear representation, the calculations were
performed in floating point rather than integer arithmetic. The constant
SEMISIZE = 4096 was eliminated, and the global variables octave_size,
fifth_size, sharp_size, and microstep_size were turned into floating
point variables. A new function compute_fifth_size () was introduced,
which computes the perfect fifth interval quantized into the ndiv
comma units. The result is returned in units of cents where one
standard octave is 1200 cents. If you run abc2midi with -v 1
(verbose level 1), the size of the fifth interval and other variables
is printed.
This is a significant change affecting the code in the functions
event_midi() and pitchof_b().
July 24 2020
store.c Hudson Lacerda corrected the algorithm in compute_fifth_size()
and fixed a bug that I had introduced.

View File

@@ -1,7 +1,7 @@
abcMIDI : abc <-> MIDI conversion utilities abcMIDI : abc <-> MIDI conversion utilities
midi2abc version 3.46 June 22 2020 midi2abc version 3.46 June 22 2020
abc2midi version 4.38 July 05 2020 abc2midi version 4.39 July 24 2020
abc2abc version 2.08 June 04 2020 abc2abc version 2.08 June 04 2020
yaps version 1.78 June 14 2020 yaps version 1.78 June 14 2020
abcmatch version 1.73 June 04 2020 abcmatch version 1.73 June 04 2020

176
store.c
View File

@@ -183,9 +183,9 @@ int main()
*/ */
#define VERSION "4.38 July 05 2020 abc2midi" #define VERSION "4.39 July 19 2020 abc2midi"
/* enables reading V: indication in header */ /* enables reading V: indication in header */
#define XTEN1 1 #define XTEN1 1
@@ -272,15 +272,14 @@ extern int microtone;
extern int temperament; /* [SS] 2020-06-25 */ extern int temperament; /* [SS] 2020-06-25 */
/* [HL] 2020-07-03 */ /* [HL] 2020-07-03 */
float temperament_dt[12]={0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0}; float temperament_dt[12]={0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0};
#define SEMISIZE 4096
#define TEMPERDT -1 #define TEMPERDT -1
#define TEMPEREQ 1 #define TEMPEREQ 1
#define TEMPERLN 2 #define TEMPERLN 2
#define TEMPERNORMAL 0 #define TEMPERNORMAL 0
int octave_size = 12*SEMISIZE; float octave_size = 12.0; /* [SS] 2020-07-17 */
int fifth_size = 7*SEMISIZE; /* default to 12-edo */ float fifth_size = 7.0; /* default to 12-edo */
int sharp_size = SEMISIZE; /* [HL] 2015-05-15] */ float sharp_size = 1.0; /* [SS] 2020-07-17 */
int microstep_size = SEMISIZE; /* [HL] 2020-06-20 */ float microstep_size = 1.0; /* [SS] 2020-07-17 */
int started_parsing=0; int started_parsing=0;
int v1index= -1; int v1index= -1;
int ignore_fermata = 0; /* [SS] 2010-01-06 */ int ignore_fermata = 0; /* [SS] 2010-01-06 */
@@ -1889,6 +1888,28 @@ while (j > 0) {
} }
} }
/* [SS] 2020-07-17 ; [HL] 2020-07-24 */
float compute_fifth_size (octave_size, ndiv)
float octave_size; /* in cents */
int ndiv;
/* rather than compute the fifth_size in cents directly
* we subtract the octave from the third harmonic.
* We do it this way instead of the proportion 3/2 because the
* octave also can be tempered. When the octave is tempered, the factor 2
* in 3/2 might cause problems: mix of pure and tempered octaves!).
*/
{
double x, h3;
int n;
float w;
/* h3 (1901.955) is the 3rd harmonic (fifth+octave) represented in cents */
h3 = 1200.0 * log2 (3.0);
x = h3 - octave_size; /* fifth reduced by the tempered octave */
n = (int) (0.5 + x * ndiv / octave_size); /* fifth in integer steps */
w = n * octave_size / ndiv; /* fifth quantized according to temperament */
return w; /* in cents */
}
/* [SS] 2015-08-11 */ /* [SS] 2015-08-11 */
void event_midi(s) void event_midi(s)
@@ -2149,26 +2170,26 @@ char *s;
double octave_cents=0.0; double octave_cents=0.0;
double fifth_cents=0.0; double fifth_cents=0.0;
temperament = TEMPERLN; temperament = TEMPERLN;
middle_c = 60*SEMISIZE; middle_c = 60;
if (sscanf(p," %lf %lf ",&octave_cents,&fifth_cents) == 2) { if (sscanf(p," %lf %lf ",&octave_cents,&fifth_cents) == 2) {
octave_size = (int)(octave_cents*SEMISIZE/100+0.5); octave_size = octave_cents;
fifth_size = (int)(fifth_cents*SEMISIZE/100+0.5); fifth_size = fifth_cents;
sharp_size = 7*fifth_size - 4*octave_size; /* [HL] 2015-05-15] */ sharp_size = 7*fifth_size - 4*octave_size; /* [HL] 2015-05-15] */
microstep_size = sharp_size; /* [HL] 2020-06-20 */ microstep_size = sharp_size; /* [HL] 2020-06-20 */
if(verbose) { /* [HL] 2015-05-15] */ if(verbose) { /* [HL] 2015-05-15] */
printf("temperamentlinear:\n" printf("temperamentlinear:\n"
"\targs: %lf %lf\n",octave_cents, fifth_cents); "\targs: %lf %lf\n",octave_cents, fifth_cents);
printf("\toctave_size = %d (%.2lf cents)\n" printf("\toctave_size = %.3f (%.3lf cents)\n"
"\tfifth_size = %d (%.2lf cents)\n" "\tfifth_size = %.3f (%.3lf cents)\n"
"\twhole-tone size = %d (%.2lf cents)\n" "\twhole-tone size = %.3f (%.3lf cents)\n"
"\taccidental_size = %d (%.2lf cents)\n" "\taccidental_size = %.3f (%.3lf cents)\n"
, ,
octave_size, octave_size,
100.0*octave_size/SEMISIZE, octave_size,
fifth_size,100.0*fifth_size/SEMISIZE, fifth_size,fifth_size,
2*fifth_size - octave_size, 100.0*(2.0*fifth_size-octave_size)/SEMISIZE, 2*fifth_size - octave_size, 2.0*fifth_size-octave_size,
sharp_size,100.0*sharp_size/SEMISIZE sharp_size,sharp_size
); );
} }
@@ -2182,72 +2203,70 @@ char *s;
/* [HL] 2015-05-15 */ /* [HL] 2015-05-15 */
else if (strcmp(command, "temperamentequal") == 0) { else if (strcmp(command, "temperamentequal") == 0) {
double octave_cents; double octave_cents;
int acc_size = -1; /* [SDG] 2020-06-03 */ float acc_size = -1.0; /* [SDG] 2020-06-03 */
int narg, ndiv, fifth_index, sharp_steps; int narg, ndiv, fifth_index, sharp_steps;
narg = sscanf(p," %d %lf %d %d ",&ndiv, &octave_cents, &fifth_index, &sharp_steps); narg = sscanf(p," %d %lf %d %d ",&ndiv, &octave_cents, &fifth_index, &sharp_steps);
switch (narg) { switch (narg) {
case 1: case 1:
octave_size = (int)( 1200.0 *SEMISIZE/100.0 + 0.5); octave_size = 1200.0; /* [SS] 2020-07-17 */
fifth_size = (int)( 1901.95500086539 *SEMISIZE/100.0 + 0.5) - octave_size; fifth_size = compute_fifth_size (octave_size, ndiv);
/* [SS] 2015-10-08 extra parentheses after (int) */
fifth_size = (int) (((int) (1.0* ndiv *fifth_size/octave_size + 0.5)) * (1.0*octave_size/ndiv));
acc_size = 7*fifth_size - 4*octave_size; acc_size = 7*fifth_size - 4*octave_size;
break; break;
case 2: case 2:
octave_size = (int)(octave_cents * SEMISIZE/100.0 + 0.5); octave_size = octave_cents;
fifth_size = (int) (1901.95500086539 *SEMISIZE/100.0 + 0.5) - octave_size; fifth_size = compute_fifth_size (octave_size, ndiv);
/* [SS] 2015-10-08 extra parentheses after (int) */
fifth_size = (int) (((int)( 1.0 * fifth_size/octave_size*ndiv + 0.5 )) * (1.0*octave_size/ndiv));
acc_size = 7*fifth_size - 4*octave_size; acc_size = 7*fifth_size - 4*octave_size;
break; break;
case 3: case 3:
octave_size = (int)(octave_cents * SEMISIZE/100.0 + 0.5); octave_size = octave_cents;
if (fifth_index > 0) /* user-defined fifth size */ if (fifth_index > 0.0) /* user-defined fifth size */
fifth_size = (int) ( 1.0 * fifth_index * octave_size/ndiv + 0.5); fifth_size = 1.0 * fifth_index * octave_size/ndiv ;
else { /* automatically computed fifth size */ else { /* automatically computed fifth size */
fifth_size = ((int) (1901.95500086539 *SEMISIZE/100.0 + 0.5)) - octave_size; fifth_size = compute_fifth_size (octave_size, ndiv);
fifth_size = (int) (((int) ( 1.0 * fifth_size/octave_size*ndiv + 0.5 )) * (1.0*octave_size/ndiv)); }
}
acc_size = 7*fifth_size - 4*octave_size; acc_size = 7*fifth_size - 4*octave_size;
break; break;
case 4: case 4:
octave_size = (int)(octave_cents * SEMISIZE/100.0 + 0.5); octave_size = octave_cents;
if (fifth_index > 0) /* user-defined fifth size */ if (fifth_index > 0.0) /* user-defined fifth size */
fifth_size = (int) ( 1.0 * fifth_index * octave_size/ndiv + 0.5); fifth_size = 1.0 * fifth_index * octave_size/ndiv ;
else { /* automatically computed fifth size */ else { /* automatically computed fifth size */
fifth_size = (int) (1901.95500086539 *SEMISIZE/100.0 + 0.5) - octave_size; fifth_size = compute_fifth_size (octave_size, ndiv);
/* [SS] 2015-10-08 extra parentheses after (int) */
fifth_size = (int) (((int) ( 1.0 * fifth_size/octave_size*ndiv + 0.5 )) * (1.0*octave_size/ndiv));
} }
/* user-defined accidental size */ /* user-defined accidental size */
acc_size = (int) (1.0 * sharp_steps * octave_size/ndiv + 0.5); acc_size = sharp_steps * octave_size/ndiv ;
break; break;
default: default:
event_error("Bad format for temperamentequal command"); event_error("Bad format for temperamentequal command");
} }
microstep_size = (int) 1.0 * octave_size/ndiv + 0.5; /* [HL] 2020-06-20 */ microstep_size = octave_size/ndiv; /* [SS] 2020-07-17 */
sharp_size = acc_size; sharp_size = acc_size;
if(verbose) { if(verbose) {
printf("temperamentequal:\n" printf("temperamentequal:\n\targs (%d):",narg);
"\targs (%d): %d %lf %d %d\n",narg, ndiv, octave_cents, fifth_index, sharp_steps); if(narg>=1) printf(" %d",ndiv);
if(narg>=2) printf(" %.3lf",octave_cents);
if(narg>=3) printf(" %d",fifth_index);
if(narg>=4) printf(" %d",sharp_steps);
printf("\n");
printf("\tndiv = %d\n" printf("\tndiv = %d\n"
"\toctave_size = %d (%.2lf cents)\n" "\toctave_size = %.3lf cents\n"
"\tfifth_size = %d (%.2lf cents) (%d steps)\n" "\tfifth_size = %.3lf (%d steps)\n"
"\twhole-tone size = %d (%.2lf cents) (%d steps)\n" "\twhole-tone size = %.3lf (%d steps)\n"
"\taccidental_size = %d (%.2lf cents) (%d steps)\n" "\taccidental_size = %.3lf (%d steps)\n"
, ,
ndiv,octave_size, ndiv,
100.0*octave_size/SEMISIZE, octave_size,
fifth_size,100.0*fifth_size/SEMISIZE, fifth_size,
(int)(1.0*fifth_size/octave_size*ndiv+0.5), (int) ((fifth_size/octave_size*ndiv) + 0.5),
2*fifth_size - octave_size, 100.0*(2.0*fifth_size-octave_size)/SEMISIZE, 2.0*fifth_size-octave_size,
(int)(1.0*(2*fifth_size-octave_size)/octave_size*ndiv+0.5), (int) (((2*fifth_size-octave_size)*ndiv/octave_size) + 0.5),
acc_size,100.0*acc_size/SEMISIZE, acc_size,
(int)(1.0*acc_size/octave_size*ndiv+0.5) (int) ((acc_size*ndiv/octave_size) + 0.5)
); );
printf("\tmicrostep_size = %d (%.2lf cents)\n",microstep_size, 100.0*microstep_size/SEMISIZE); /* [HL] 2020-06-20*/ printf("\tmicrostep_size = %.3lf cents (1 step)\n",microstep_size); /* [HL] 2020-06-20*/
} }
@@ -2261,7 +2280,7 @@ char *s;
temperament = TEMPEREQ; temperament = TEMPEREQ;
middle_c = 60*SEMISIZE; middle_c = 60;
done = 1; done = 1;
} }
@@ -3677,23 +3696,24 @@ int *pitchbend;
int p; int p;
char acc; char acc;
int mul, noteno; int mul, noteno;
int pitch4096,pitch,bend; float pitchvalue;
int pitch,bend;
int a,b; int a,b;
int j; int j;
static int scale[7] = {0, 2, 4, 5, 7, 9, 11}; static int scale[7] = {0, 2, 4, 5, 7, 9, 11};
const int accidental_size = sharp_size; /* [HL] 2015-05-15 - for temperamentlinear and temperamentequal */ const float accidental_size = sharp_size/100.0; /* [HL] 2015-05-15 - for temperamentlinear and temperamentequal */
const int tscale[7] = { const float tscale[7] = {
0, 0,
2*fifth_size-octave_size, (2*fifth_size-octave_size),
4*fifth_size-2*octave_size, (4*fifth_size-2*octave_size),
-1*fifth_size+octave_size, (-1*fifth_size+octave_size),
fifth_size, fifth_size,
3*fifth_size-octave_size, (3*fifth_size-octave_size),
5*fifth_size-2*octave_size (5*fifth_size-2*octave_size) };
}; /* in units cents [SS] 2020-07-17 */
static const char *anoctave = "cdefgab";
static const char *anoctave = "cdefgab";
acc = accidental; acc = accidental;
mul = mult; mul = mult;
noteno = (int)note - 'a'; noteno = (int)note - 'a';
@@ -3730,29 +3750,29 @@ int *pitchbend;
/* [HL] 2020-07-03 */ /* [HL] 2020-07-03 */
if ((temperament==TEMPERLN) || (temperament==TEMPEREQ)) { if ((temperament==TEMPERLN) || (temperament==TEMPEREQ)) {
p = tscale[p]; pitchvalue = tscale[p]/100.0; /* cents to semitones */
if (acc == '^') p = p + mul*accidental_size; if (acc == '^') pitchvalue = pitchvalue + mul*accidental_size;
if (acc == '_') p = p - mul*accidental_size; if (acc == '_') pitchvalue = pitchvalue - mul*accidental_size;
pitch4096 = p + octave*octave_size + middle_c; pitchvalue = pitchvalue + octave*octave_size/100.0 + middle_c;
/* [HL] 2020-06-27 Adjust for A=440.0 with zero pitchbend */ /* [HL] 2020-06-27 Adjust for A=440.0 with zero pitchbend */
pitch4096 += (9*SEMISIZE) - (3*fifth_size-octave_size); pitchvalue += 9.0 - (3.0*fifth_size-octave_size)/100.0;
/* [HL] 2015-05-15 */ /* [HL] 2015-05-15 */
if (microtone) { if (microtone) {
if (setmicrotone.denom == 100) /* microtone in cents */ if (setmicrotone.denom == 100) /* microtone in cents */
pitch4096 += (int) (1.0 * setmicrotone.num / setmicrotone.denom * SEMISIZE); pitchvalue+= setmicrotone.num / setmicrotone.denom;
else if (setmicrotone.denom == 0) { /* [HL] 2020-06-20 / 2020-06-27 */ else if (setmicrotone.denom == 0) { /* [HL] 2020-06-20 / 2020-06-27 */
/* microstep_size is accidental_size for temperamentlinear, /* microstep_size is accidental_size for temperamentlinear,
* or * or
* microstep_size is the octave fraction for temperamentequal * microstep_size is the octave fraction for temperamentequal
* */ * */
pitch4096 += (int) (1.0 * setmicrotone.num * microstep_size); pitchvalue += setmicrotone.num * microstep_size/100.0;
} }
else /* microtone relative to sharp step in the current temperament */ else /* microtone relative to sharp step in the current temperament */
pitch4096 += (int) (1.0 * setmicrotone.num / setmicrotone.denom * accidental_size); pitchvalue += ((1.0 * setmicrotone.num) / setmicrotone.denom) * accidental_size;
/* needed? */ /* needed? */
microtone = 0; microtone = 0;
@@ -3760,8 +3780,8 @@ int *pitchbend;
active_pitchbend = 8192; active_pitchbend = 8192;
} }
pitch = (SEMISIZE*128+pitch4096+SEMISIZE/2)/SEMISIZE-128; pitch = (int) (pitchvalue + 0.5);
bend = 8192+4096*(pitch4096 - pitch*SEMISIZE)/SEMISIZE; bend = (int) (0.5 + 8192.0 + 4096.0 * (pitchvalue - (float) pitch));
bend = bend<0?0:(bend>16383?16383:bend); bend = bend<0?0:(bend>16383?16383:bend);
} else { /* TEMPERNORMAL / TEMPERDT */ } else { /* TEMPERNORMAL / TEMPERDT */
p = scale[p]; p = scale[p];
@@ -3770,7 +3790,7 @@ int *pitchbend;
pitch = p + 12*octave + middle_c; pitch = p + 12*octave + middle_c;
bend = 8192; /* corresponds to zero bend */ bend = 8192; /* corresponds to zero bend */
if (temperament == TEMPERDT) { /* [HL] 2020-07-03 */ if (temperament == TEMPERDT) { /* [HL] 2020-07-03 */
bend += (int) (SEMISIZE * temperament_dt[p] / 100.0); bend += (int) (0.5 + 40.96 * temperament_dt[p]);
bend = bend<0?0:(bend>16383?16383:bend); bend = bend<0?0:(bend>16383?16383:bend);
} }
} }