Codice fonte pertine a iste explanation. Anque disponibile pro discargar.

```/*
Written 16 May 1993, Ruud Harmsen

Examine musical intervals made by frequency ratios between the
first natural numbers, and from 12-, 24-, 31-, and 53-tone
equidistant tuning systems.

3 October 2020:
Added Pythagorean intervals like 81/64, 32/27, 256/243 etc., by
permuting factors 2 and 3.

4 October 2020:
More reliable algorithm, no longer assuming qsort will leave
equal entries in the original order. A sequence number now
guarantees that later entries (e.g. 6:4, 12:8) appear later
than the basic ratio (e.g. 3:2), and so can easily and reliably
be removed afterwards.

4 October 2020:
Published source and outputs to https://rudhar.com/musica/intonat/ .

5 October 2020:
Used realloc() instead of a fixed size array.

6 October 2020:
More identical code in a function, and add ratios 135:128,
64:45 and 45:32.

16 October 2020:
Can now also generate C code (option -g), for use elsewhere
in a display function (showintv.c). Also added some more
intervals.

24 October 2020:
Added some more intervals, after examination of shifted Zarlino
and Pythagoras scales.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define MAXFACT 25
/* Added 3 October 2020 */
#define MAXPYTH 13

struct interval
{
int    seqnum;
double cents;
char   text;
};
struct interval *interv = NULL;

/* Number of filled rows, how many are already in the table. */
int fild_rows = 0;

static int cmp (const void *, const void *);
static void fill_octave_division (int div);
static void fill_pythagorean_ratios (void);
static void fill_pythagorean_ratios_2_3 (int factorA, int factorB);
int fild_rows_arg,
int numerator, int denominator,
struct interval **pp_interv);
int fild_rows_arg,
struct interval *p_newrow,
struct interval **pp_interv);

static void write_C_array (void);

int main (int argc, char **argv)
{
int i, j;
int only_53 = 0;
int generate_C = 0;

while (argc > 1)
{
if (strcmp(argv, "-53") == 0)
only_53 = 1;
else if (strcmp(argv, "-g") == 0)
generate_C = 1;
argc--, argv++;
}

for (i = 1;     i <= MAXFACT; i++)
for (j = i + 1; j <= MAXFACT; j++)
{
fild_rows = addratio(fild_rows, j, i, &interv);
}

fill_octave_division(12);
fill_octave_division(24);
if (!only_53)
{
fill_octave_division(19);
fill_octave_division(31);
fill_octave_division(43);
}
fill_octave_division(53);

fill_pythagorean_ratios();

/* Some extra ratios, not covered by previous algorithms */
fild_rows = addratio(fild_rows,    135,    128, &interv);
fild_rows = addratio(fild_rows,     64,     45, &interv);
fild_rows = addratio(fild_rows,     45,     32, &interv);
fild_rows = addratio(fild_rows,     36,     25, &interv);

https://en.wikipedia.org/wiki/Interval_(music)#Size_of_intervals_used_in_different_tuning_systems
https://en.wikipedia.org/wiki/Five-limit_tuning#The_just_ratios
https://en.wikipedia.org/wiki/Pythagorean_interval
https://nl.wikipedia.org/wiki/Didymisch_komma
https://en.wikipedia.org/wiki/Syntonic_comma
etc. */
fild_rows = addratio(fild_rows,     27,     25, &interv);
fild_rows = addratio(fild_rows,     27,     20, &interv);
fild_rows = addratio(fild_rows,     40,     27, &interv);
fild_rows = addratio(fild_rows,     50,     27, &interv);
fild_rows = addratio(fild_rows,     81,     80, &interv);

/* Some additions after analysis of shifted Zarlino and
Pythagoras scales, from self-written program zarlino.c */
fild_rows = addratio(fild_rows,     32,     25, &interv);
fild_rows = addratio(fild_rows,     75,     64, &interv);
fild_rows = addratio(fild_rows,    225,    128, &interv);
fild_rows = addratio(fild_rows,    256,    225, &interv);
fild_rows = addratio(fild_rows,    256,    243, &interv);
fild_rows = addratio(fild_rows,    512,    405, &interv);
fild_rows = addratio(fild_rows,    675,    512, &interv);
fild_rows = addratio(fild_rows,   2187,   2048, &interv);
fild_rows = addratio(fild_rows,   6561,   4096, &interv);
fild_rows = addratio(fild_rows,   8192,   6561, &interv);
fild_rows = addratio(fild_rows,  19683,  16384, &interv);
fild_rows = addratio(fild_rows,  59049,  32768, &interv);
fild_rows = addratio(fild_rows,  65536,  59049, &interv);
fild_rows = addratio(fild_rows, 177147, 131072, &interv);
fild_rows = addratio(fild_rows, 262144, 177147, &interv);

/* Sort the raw table on ascending number of cents,
and sequence number */
qsort((void *)interv, fild_rows, sizeof interv, cmp);

/* Remove doublets, e.g. 3/2 and 6/4 both are a fifth,
only the first one needs to be kept. */
for (i = 1, j = 0; i < fild_rows; i++)
{
/* Round difference to 5 decimals, so spurious last bits
cannot determine the sorting order. */
long int centsdiff = 0.5 + (interv[i].cents - interv[j].cents) * 100000L;

if (centsdiff == 0)
/* Mark as doublet (first row is kept alive */
interv[i].text = '\0';
else
j = i;
}

/* Write the results to standard output */
if (generate_C)
write_C_array();
else for (i = 0; i < fild_rows; i++)
{
/* Skip marked doublets, write everything else */
if (interv[i].text)
{
fprintf(stdout, "%8.6f %8.3f %s\n",
pow(2.0, interv[i].cents / 1200.0),
interv[i].cents,
interv[i].text);
}
}

free(interv);

return 0;
}

static int cmp (const void *a, const void *b)
{
const struct interval *aa = (const struct interval *)a;
const struct interval *bb = (const struct interval *)b;
/* Round difference to 5 decimals, so spurious last bits
cannot determine the sorting order. */
long int centsdiff = 0.5 + (aa->cents - bb->cents) * 100000L;

if (centsdiff)
{
if (aa->cents > bb->cents) return 1;
if (aa->cents < bb->cents) return -1;
}
/* Equal intervals should remain in the original order
of entry, so all but the first can be wiped. */
return aa->seqnum - bb->seqnum;
}

static void fill_octave_division (int div)
{
int i;

for (i = 0; i <= div; i++)
{
struct interval newrow;

newrow.cents = 1200.0 * i / (double)div;
sprintf(newrow.text, "%6d/%-6d octave", i, div);
/* Set sequence number, to guarantee that later additions
stay after earlier ones, even after sorting. */
newrow.seqnum = fild_rows;
}
}

/* Added the extra Pythagorean ratios on 3 October 2020. Yes,
that's more than 27 years later, and still by the same
programmer. I am Ruud Harmsen. */
static void fill_pythagorean_ratios (void)
{
fill_pythagorean_ratios_2_3(3, 2);
fill_pythagorean_ratios_2_3(2, 3);
}

static void fill_pythagorean_ratios_2_3 (int factorA, int factorB)
{
int i , j;
int numerator, denominator;
double ratio;

/* This adds things like 32/27, 256/243 etc. which would otherwise
not be included, as the maximum factor MAXFACT is 25. */
for (i = 1; i <= MAXPYTH; i++)
for (j = 1; j <= MAXPYTH; j++)
{
struct interval newrow;

numerator   = pow(factorA, i);
denominator = pow(factorB, j);

fild_rows = addratio(fild_rows, numerator, denominator, &interv);
}
}

int fild_rows_arg,
int numerator, int denominator,
struct interval **pp_interv)
{
double ratio = (double)numerator / (double)denominator;
struct interval newrow;

if (ratio < 1.0 || ratio > 2.0)
return fild_rows;

newrow.cents = log(ratio) / log(2.0) * 1200;
sprintf(newrow.text, "%6d:%-6d ratio ", numerator, denominator);
/* Set sequence number, to guarantee that later additions
stay after earlier ones, even after sorting. */
newrow.seqnum = fild_rows;

return fild_rows_arg = addrow(fild_rows, &newrow, pp_interv);
}

int fild_rows_arg,
struct interval *p_newrow,
struct interval **pp_interv)
{
struct interval *realloked =
realloc(*pp_interv, (fild_rows_arg + 1) * sizeof (struct interval));

if (realloked)
{
*pp_interv = realloked;
/* Structure assign */
(*pp_interv)[fild_rows_arg++] = *p_newrow;
}
else
{
/* Realloc failed. Silently ignore. Just don't put in
that new row, and keep pointer and counter unchanged.
Failure is so unlikely in practice, having only a few
hundred entries, that error handling would be overkill.
*/ ;
}
return fild_rows_arg;
}

static void write_C_array (void)
{
int i;

fprintf(stdout, "/* Generated from intonat.c */\n");
fprintf(stdout, "struct interv_struct\n");
fprintf(stdout, "{\n");
fprintf(stdout, "   double ratio;\n");
fprintf(stdout, "   double cents;\n");
fprintf(stdout, "   char   text;\n");
fprintf(stdout, "} interv[] = {\n");

for (i = 0; i < fild_rows; i++)
{
/* Skip marked doublets, write everything else */
if (interv[i].text)
{
fprintf(stdout, "   { %8.6f, %11.6f, \"%s\" },\n",
pow(2.0, interv[i].cents / 1200.0),
interv[i].cents,
interv[i].text);
}
}
fprintf(stdout, "};\n");
fprintf(stdout, "/* End of generated code from intonat.c */\n\n");
}
```