paulo@0: #include paulo@0: #include paulo@0: #include paulo@0: paulo@0: /* paulo@0: Pin Eight standard tuning defines middle C as 2093/8 Hz. paulo@0: It uses equal temperament: a semitone difference between two pitches paulo@0: is a factor of 2^(1/12) between their frequencies. paulo@0: Thus, MIDI 0 = 60, or 2093/256. paulo@0: */ paulo@0: #define C_IN_OCTAVE(octave) \ paulo@0: ((double)((long int)2093 << octave) / 256.0) paulo@0: #define TWELFTH_ROOT_OF_TWO 1.0594630943592952645618252949463 paulo@0: paulo@0: /* paulo@0: DS note frequencies for the tone generator at 8 samples per period paulo@0: are ((-0x1000000 / (n * 8))) paulo@0: */ paulo@0: #define FREQ_TO_PSG_PERIOD(freq) \ paulo@0: ((unsigned short)(-0x1000000 / (freq * 8))) paulo@0: paulo@0: paulo@0: int writePSG(FILE *fp) { paulo@0: paulo@0: // write header paulo@0: fputs(".section .rodata\n" paulo@0: ".balign 4\n" paulo@0: ".global midi2psgFreq\n" paulo@0: "midi2psgFreq:", fp); paulo@0: paulo@0: int octave = 0; paulo@0: paulo@0: for (; octave < 2; ++octave) { paulo@0: fprintf(fp, "\n@ unsupported octave %d\n.byte ", octave); paulo@0: for (int semitone = 0; semitone < 12; ++semitone) { paulo@0: if (semitone) { paulo@0: fputs(", ", fp); paulo@0: } paulo@0: fputs(" 0, 0", fp); paulo@0: } paulo@0: } paulo@0: for (; octave < 10; ++octave) { paulo@0: double freq = C_IN_OCTAVE(octave); paulo@0: fprintf(fp, "\n@ octave %d\n.byte ", octave); paulo@0: for (int semitone = 0; semitone < 12; ++semitone) { paulo@0: if (semitone) { paulo@0: fputs(", ", fp); paulo@0: freq *= TWELFTH_ROOT_OF_TWO; paulo@0: } paulo@0: unsigned int psgFreq = FREQ_TO_PSG_PERIOD(freq); paulo@0: printf("midi %2d = %.2f = psg %5d\n", paulo@0: octave * 12 + semitone, paulo@0: freq, paulo@0: psgFreq); paulo@0: fprintf(fp, "%3u,%3u", paulo@0: psgFreq & 0xFF, paulo@0: (psgFreq >> 8) & 0xFF); paulo@0: } paulo@0: } paulo@0: paulo@0: fputs("\n", fp); paulo@0: return 0; paulo@0: } paulo@0: paulo@0: /** paulo@0: * Writes lookup tables used by the ARM7 code. paulo@0: * Currently, these include the PSG pitch values. paulo@0: */ paulo@0: int writeARM7(const char *filename) { paulo@0: FILE *fp = fopen(filename, "wt"); paulo@0: if (!fp) { paulo@0: return -1; paulo@0: } paulo@0: if (writePSG(fp) < 0) { paulo@0: fclose(fp); paulo@0: return -1; paulo@0: } paulo@0: fclose(fp); paulo@0: return 0; paulo@0: } paulo@0: paulo@0: paulo@0: int main(void) { paulo@0: if (writeARM7("obj/ds/lookup_tables7.s") < 0) { paulo@0: return EXIT_FAILURE; paulo@0: } paulo@0: return EXIT_SUCCESS; paulo@0: }