mirror of
https://github.com/sshlien/abcmidi.git
synced 2025-12-06 06:55:06 +00:00
2020-07-26
This commit is contained in:
31
doc/CHANGES
31
doc/CHANGES
@@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
176
store.c
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user