rev |
line source |
paulo@0
|
1 #include <stdlib.h>
|
paulo@0
|
2 #include <stdio.h>
|
paulo@0
|
3 #include <math.h>
|
paulo@0
|
4
|
paulo@0
|
5 /*
|
paulo@0
|
6 Pin Eight standard tuning defines middle C as 2093/8 Hz.
|
paulo@0
|
7 It uses equal temperament: a semitone difference between two pitches
|
paulo@0
|
8 is a factor of 2^(1/12) between their frequencies.
|
paulo@0
|
9 Thus, MIDI 0 = 60, or 2093/256.
|
paulo@0
|
10 */
|
paulo@0
|
11 #define C_IN_OCTAVE(octave) \
|
paulo@0
|
12 ((double)((long int)2093 << octave) / 256.0)
|
paulo@0
|
13 #define TWELFTH_ROOT_OF_TWO 1.0594630943592952645618252949463
|
paulo@0
|
14
|
paulo@0
|
15 /*
|
paulo@0
|
16 DS note frequencies for the tone generator at 8 samples per period
|
paulo@0
|
17 are ((-0x1000000 / (n * 8)))
|
paulo@0
|
18 */
|
paulo@0
|
19 #define FREQ_TO_PSG_PERIOD(freq) \
|
paulo@0
|
20 ((unsigned short)(-0x1000000 / (freq * 8)))
|
paulo@0
|
21
|
paulo@0
|
22
|
paulo@0
|
23 int writePSG(FILE *fp) {
|
paulo@0
|
24
|
paulo@0
|
25 // write header
|
paulo@0
|
26 fputs(".section .rodata\n"
|
paulo@0
|
27 ".balign 4\n"
|
paulo@0
|
28 ".global midi2psgFreq\n"
|
paulo@0
|
29 "midi2psgFreq:", fp);
|
paulo@0
|
30
|
paulo@0
|
31 int octave = 0;
|
paulo@0
|
32
|
paulo@0
|
33 for (; octave < 2; ++octave) {
|
paulo@0
|
34 fprintf(fp, "\n@ unsupported octave %d\n.byte ", octave);
|
paulo@0
|
35 for (int semitone = 0; semitone < 12; ++semitone) {
|
paulo@0
|
36 if (semitone) {
|
paulo@0
|
37 fputs(", ", fp);
|
paulo@0
|
38 }
|
paulo@0
|
39 fputs(" 0, 0", fp);
|
paulo@0
|
40 }
|
paulo@0
|
41 }
|
paulo@0
|
42 for (; octave < 10; ++octave) {
|
paulo@0
|
43 double freq = C_IN_OCTAVE(octave);
|
paulo@0
|
44 fprintf(fp, "\n@ octave %d\n.byte ", octave);
|
paulo@0
|
45 for (int semitone = 0; semitone < 12; ++semitone) {
|
paulo@0
|
46 if (semitone) {
|
paulo@0
|
47 fputs(", ", fp);
|
paulo@0
|
48 freq *= TWELFTH_ROOT_OF_TWO;
|
paulo@0
|
49 }
|
paulo@0
|
50 unsigned int psgFreq = FREQ_TO_PSG_PERIOD(freq);
|
paulo@0
|
51 printf("midi %2d = %.2f = psg %5d\n",
|
paulo@0
|
52 octave * 12 + semitone,
|
paulo@0
|
53 freq,
|
paulo@0
|
54 psgFreq);
|
paulo@0
|
55 fprintf(fp, "%3u,%3u",
|
paulo@0
|
56 psgFreq & 0xFF,
|
paulo@0
|
57 (psgFreq >> 8) & 0xFF);
|
paulo@0
|
58 }
|
paulo@0
|
59 }
|
paulo@0
|
60
|
paulo@0
|
61 fputs("\n", fp);
|
paulo@0
|
62 return 0;
|
paulo@0
|
63 }
|
paulo@0
|
64
|
paulo@0
|
65 /**
|
paulo@0
|
66 * Writes lookup tables used by the ARM7 code.
|
paulo@0
|
67 * Currently, these include the PSG pitch values.
|
paulo@0
|
68 */
|
paulo@0
|
69 int writeARM7(const char *filename) {
|
paulo@0
|
70 FILE *fp = fopen(filename, "wt");
|
paulo@0
|
71 if (!fp) {
|
paulo@0
|
72 return -1;
|
paulo@0
|
73 }
|
paulo@0
|
74 if (writePSG(fp) < 0) {
|
paulo@0
|
75 fclose(fp);
|
paulo@0
|
76 return -1;
|
paulo@0
|
77 }
|
paulo@0
|
78 fclose(fp);
|
paulo@0
|
79 return 0;
|
paulo@0
|
80 }
|
paulo@0
|
81
|
paulo@0
|
82
|
paulo@0
|
83 int main(void) {
|
paulo@0
|
84 if (writeARM7("obj/ds/lookup_tables7.s") < 0) {
|
paulo@0
|
85 return EXIT_FAILURE;
|
paulo@0
|
86 }
|
paulo@0
|
87 return EXIT_SUCCESS;
|
paulo@0
|
88 }
|