aboutsummaryrefslogtreecommitdiff
path: root/fmdriver/fmdriver_common.c
blob: b919c3a20f402a2de1e830e0fbfcd03f3193b996 (plain)
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
#include "fmdriver/fmdriver_common.h"

uint8_t fmdriver_fm_freq2key(uint16_t freq) {
  int block = freq >> (8+3);
  int f_num = freq & ((1<<(8+3))-1);
  if (!f_num) return 0x00;
  while (!(f_num & (1<<(8+3-1)))) {
    f_num <<= 1;
    block--;
  }
  static const uint16_t freqtab[0xc] = {
    0x042e, // < 9 (a)
    0x046e,
    0x04b1,
    0x04f9,
    0x0544,
    0x0595,
    0x05ea,
    0x0644,
    0x06a3,
    0x0708,
    0x0773,
    0x07e4,
  };
  int note = 0;
  for (; note < 12; note++) {
    if (f_num < freqtab[note]) break;
  }
  note += 9;
  block += (note/12);
  note %= 12;

  if (block < 0) return 0x00;
  if (block > 8) return 0x8b;
  return (block << 4) | note;
}

uint8_t fmdriver_ssg_freq2key(uint16_t freq) {
  if (!freq) return 0x00;
  int octave = -5;
  while (!(freq & 0x8000)) {
    freq <<= 1;
    octave++;
  }
  // 7987200.0 / (64*440*(2**((i+2+0.5)/12))/(1<<8))
  static const uint16_t freqtab[0xc] = {
    0xf57f, // > 0 (c)
    0xe7b8,
    0xdab7,
    0xce70,
    0xc2da,
    0xb7ea,
    0xad98,
    0xa3da,
    0x9aa7,
    0x91f9,
    0x89c8,
    0x820c,
  };
  int note = 0;
  for (; note < 12; note++) {
    if (freq > freqtab[note]) break;
  }
  note += 11;
  octave += (note/12);
  note %= 12;

  if (octave < 0) return 0x00;
  if (octave > 8) return 0x8b;
  return (octave << 4) | note;
}

uint8_t fmdriver_ppz8_freq2key(uint32_t freq) {
  if (!freq) return 0x00;
  int octave = 16+4;
  while (!(freq & 0x80000000u)) {
    freq <<= 1;
    octave--;
  }
  if (octave < 0) return 0x00;
  if (octave > 8) return 0x8b;
  // round(0x8000*(2**((i+0.5)/12)))
  static const uint16_t freqtab[0xc] = {
    0x83c0,
    0x8b96,
    0x93e3,
    0x9cae,
    0xa5ff,
    0xafde,
    0xba53,
    0xc567,
    0xd124,
    0xdd94,
    0xeac1,
    0xf8b6
  };
  uint16_t freqhigh = freq >> 16;
  int note = 0;
  for (; note < 12; note++) {
    if (freqhigh < freqtab[note]) break;
  }
  return (octave << 4) | note;
}