1 /* ======================================================================== */
2 /* The routines and data in this file (notes.c) are dedicated to the */
3 /* public domain via the Creative Commons CC0 v1.0 license by its author, */
4 /* Joseph Zbiciak. */
5 /* */
6 /* https://creativecommons.org/publicdomain/zero/1.0/ */
7 /* ======================================================================== */
8
9 #include <stdio.h>
10 #include <math.h>
11
12 /* 0 = C1, 84 = C8 */
note_freq(int note)13 double note_freq(int note)
14 {
15 double freq;
16
17 note -= 45; /* Make A4 = 0. A4 is 440Hz */
18 freq = 440.0 * pow(2.0, (double)note / 12.0);
19
20 return freq;
21 }
22
ntsc_period(double freq)23 double ntsc_period(double freq)
24 {
25 return 3579545.0 / 32.0 / freq;
26 }
27
pal_period(double freq)28 double pal_period(double freq)
29 {
30 return 4000000.0 / 32.0 / freq;
31 }
32
33 const char *note_names[12] =
34 {
35 "C%d",
36 "C#%d / Db%d",
37 "D%d",
38 "D#%d / Eb%d",
39 "E%d",
40 "F%d",
41 "F#%d / Gb%d",
42 "G%d",
43 "G#%d / Ab%d",
44 "A%d",
45 "A#%d / Bb%d",
46 "B%d",
47 };
48
note_name(int note)49 const char *note_name(int note)
50 {
51 int octave;
52 static char buf[10];
53
54 if (note < 0)
55 {
56 buf[0] = 0;
57 return buf;
58 }
59
60 octave = 1 + note / 12;
61 note %= 12;
62
63 sprintf(buf, note_names[note], octave, octave);
64 return buf;
65 }
66
67 const char *note_labels[12][2] =
68 {
69 { "C%d", NULL },
70 { "Cs%d","Db%d" },
71 { "D%d", NULL },
72 { "Ds%d","Eb%d" },
73 { "E%d", NULL },
74 { "F%d", NULL },
75 { "Fs%d","Gb%d" },
76 { "G%d", NULL },
77 { "Gs%d","Ab%d" },
78 { "A%d", NULL },
79 { "As%d","Bb%d" },
80 { "B%d", NULL },
81 };
82
note_label(int note,int sf)83 const char *note_label(int note, int sf)
84 {
85 int octave;
86 static char buf[10];
87
88 if (note < 0 || sf < 0 || sf > 1)
89 return NULL;
90
91 octave = 1 + note / 12;
92 note %= 12;
93
94 if (note_labels[note][sf] == NULL)
95 return NULL;
96
97 sprintf(buf, note_labels[note][sf], octave);
98 return buf;
99 }
100
101
main(void)102 int main(void)
103 {
104 int i, pi;
105 double p, f, fr, err;
106 const char *lbl, *name;
107
108 printf(";; ======================================================"
109 "================== ;;\n");
110 printf(";; This file was autogenerated.\n");
111 printf(";;\n");
112 printf(";; The data in this file is dedicated to the public domain\n");
113 printf(";; via the Creative Commons CC0 v1.0 license by the author\n");
114 printf(";; of the program that generated this file.\n");
115 printf(";;\n");
116 printf(";; https://creativecommons.org/publicdomain/zero/1.0/\n");
117 printf(";;\n");
118 printf(";; You can compare the computed frequencies versus the ideal\n");
119 printf(";; values using this chart online:\n");
120 printf(";;\n");
121 printf(";; http://www.phy.mtu.edu/~suits/notefreqs.html\n");
122 printf(";; ======================================================"
123 "================== ;;\n");
124 printf("\n\n");
125
126 printf("NOTES.NTSC PROC\n");
127 for (i = 0; i < 85; i++)
128 {
129 p = ntsc_period(f = note_freq(i));
130 pi = (int)floor(p + 0.5);
131 fr = ntsc_period(pi);
132
133 err = 100.0 * ((fr / f) - 1.0); /* relative error */
134
135 if ((lbl = note_label(i, 1)) != NULL)
136 printf("@@%s\n", lbl);
137
138 lbl = note_label(i, 0);
139 name = note_name(i);
140
141 printf(
142 "@@%-4s DECLE $%.4X ; %-10s %7.2f Hz (%+1.3f%% err)\n",
143 lbl, pi, name, fr, err);
144 }
145 printf(" ENDP\n");
146
147 printf("\n\n");
148
149 printf("NOTES.PAL PROC\n");
150 for (i = 0; i < 85; i++)
151 {
152 p = pal_period(f = note_freq(i));
153 pi = (int)floor(p + 0.5);
154 fr = pal_period(pi);
155
156 err = 100.0 * ((fr / f) - 1.0); /* relative error */
157
158 if ((lbl = note_label(i, 1)) != NULL)
159 printf("@@%s\n", lbl);
160
161 lbl = note_label(i, 0);
162 name = note_name(i);
163
164 printf(
165 "@@%-4s DECLE $%.4X ; %-10s %7.2f Hz (%+1.3f%% err)\n",
166 lbl, pi, name, fr, err);
167 }
168 printf(" ENDP\n");
169
170 printf(";; End of note data\n");
171
172 return 0;
173 }
174