/
genfreqtab.c
122 lines (90 loc) · 3.04 KB
/
genfreqtab.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// ---------------------------------------------------------------------------
// Generate tuning tables -- by Ivo van Poorten (C)2020 - License: 0BSD
// output RFC4180 CSV table with header
// build with gcc -o genfreqtab genfreqtab.c -lm
// ---------------------------------------------------------------------------
#define TUNE_TO_A (440.0) // floating point in Hertz
//#define PRINT_CSV
#define PRINT_MADS_DTA
// ---------------------------------------------------------------------------
#include "stdio.h"
#include "math.h"
// ---------------------------------------------------------------------------
#define NUMBER_OF_OCTAVES 10
// semitone offsets
#define C0 (-57)
#define C1 (-45)
#define C2 (-33)
#define C3 (-21)
#define C4 (-9)
#define C5 (3)
#define C6 (15)
#define C7 (27)
#define C8 (39)
#define C9 (53)
#define C10 (63)
// Atari XL main clocks
#define SYSCLOCK_PAL 1773447.0
#define SYSCLOCK_NTSC 1789790.0
// Well-tempered tuning
//
// Fn = F0 * a^n
#define F0 (TUNE_TO_A)
#define a_100cents (pow(2.0,(1.0/12.0)))
#define FORMULA(n) ((F0) * (pow(a_100cents,(n))))
// Pokey 16-bit value to frequency relation
//
// f = sysclock/(v+7)/2
//
// so
//
// v = sysclock/(2*f)-7
#define FREQ_TO_VALUE(sysclock, freq) ((sysclock/(2*freq))-7)
#define VALUE_TO_FREQ(sysclock, value) (sysclock/(value+7)/2)
#define SIZE (NUMBER_OF_OCTAVES*12)
double equal_tempered_frequencies[SIZE], pal_frequencies[SIZE], \
ntsc_frequencies[SIZE];
int pal_values[SIZE], ntsc_values[SIZE];
int main(int argc, char **argv) {
int i, j;
double e;
#ifdef PRINT_CSV
printf("n, equal_tempered_frequency, PAL_hex, NTSC_hex, "
"PAL_frequency, NTSC_frequency\n");
#endif
for (i=0; i<(NUMBER_OF_OCTAVES*12); i++) {
e = equal_tempered_frequencies[i] = FORMULA(i+C0);
pal_values[i] = round(FREQ_TO_VALUE(SYSCLOCK_PAL, e));
ntsc_values[i] = round(FREQ_TO_VALUE(SYSCLOCK_NTSC, e));
pal_frequencies[i] = VALUE_TO_FREQ(SYSCLOCK_PAL, pal_values[i]);
ntsc_frequencies[i] = VALUE_TO_FREQ(SYSCLOCK_NTSC, ntsc_values[i]);
#ifdef PRINT_CSV
printf("%i, %0.2f, %04x, %04x, %0.2f, %0.2f\n",
i, equal_tempered_frequencies[i],
pal_values[i], ntsc_values[i],
pal_frequencies[i], ntsc_frequencies[i]);
#endif
}
#ifdef PRINT_MADS_DTA
printf("\npal_16bit_frequency_table\n");
for (i=0; i<NUMBER_OF_OCTAVES; i++) { // octaves
printf("; Octave %i\n", i);
printf(" dta a(");
for (j=0; j<11; j++) { // notes
printf("$%04x,", pal_values[i*12+j]);
}
printf("$%04x)\n", pal_values[i*12+j]);
}
// code duplication ;)
printf("\nntsc_16bit_frequency_table\n");
for (i=0; i<NUMBER_OF_OCTAVES; i++) { // octaves
printf("; Octave %i\n", i);
printf(" dta a(");
for (j=0; j<11; j++) { // notes
printf("$%04x,", ntsc_values[i*12+j]);
}
printf("$%04x)\n", ntsc_values[i*12+j]);
}
printf("\n");
#endif
}