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