-
Notifications
You must be signed in to change notification settings - Fork 0
/
lookup_gen.py
executable file
·90 lines (77 loc) · 2.35 KB
/
lookup_gen.py
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
#!/usr/bin/env python3
import math
DDS_VALUE_T = 'dds_value_t' # c++ type
DDS_INC_T = 'uint32_t'
DDS_FREQ = 40000 # keep in sync with C++ code
def dds_notes_incs():
M = 2 ** (1/12)
LEN = 12*9
freqs = [440/(M**x) for x in range(57,0,-1)] + [440] + [440*(M**x) for x in range(1,51)]
r = [round(2**32 * f / DDS_FREQ) for f in freqs]
assert len(r) == LEN
for x in r:
assert x > 0
assert x < 2**32 / 2
return r
def sin_points_full(n):
l = [
math.floor(math.sin(x*2*math.pi/n)*65535/2 + 65536/2)
for x in range(0, n)
]
assert len(l) == n
for x in l:
assert x >= 0
assert x < 65536
return l
def lookup_sin_quarter(i, table_quarter):
l = len(table_quarter)
if i < l:
# first quarter of sine period, just lookup
r = table_quarter[i]
return r
if i == l:
# maximum value
return 65535 # FIXME
if i < l * 2:
# second quarter of period
idx = l*2 - i
r = table_quarter[idx]
return r
if i == l * 2:
# half of period
return table_quarter[0]
if i < l * 3:
# 3rd quarter of period
r = table_quarter[0] - (table_quarter[i - l*2] - table_quarter[0])
r -= 1 # remove rounding error to match with "full table" (for tests)
return r
if i == l * 3:
# minimum value
return 0
# 4th quarter of period
assert i < l * 4
r = table_quarter[0] - (table_quarter[l*4 - i] - table_quarter[0])
r -= 1
return r
def sin_points_quarter(n):
assert n % 4 == 0
full = sin_points_full(n)
r = full[:int(n/4)]
#print(f'F[{len(full)}]: {full}')
#print(f'Q[{len(r)}]: {r}')
full_test = [lookup_sin_quarter(i, r) for i in range(0,n)]
#print(f'Q->F[{len(full_test)}]: {full_test}')
for i in range(0,n):
assert lookup_sin_quarter(i, r) == full[i]
return r
print('// Autogenerated file\n')
print('\nconst std::array<' + DDS_INC_T + ', 12*9> dds_notes_incs = {')
print(" " + ", ".join([str(i) for i in dds_notes_incs()]))
print('};')
# sin tables
for sz in [3, 4, 5, 10, 12]:
count_full = 2**sz
print(f'\n// sin{sz}')
print(f'constexpr std::array<{DDS_VALUE_T}, {int(count_full/4)}> lookup_table_sin{sz} = ' + '{')
print(f' ' + ", ".join([str(x) for x in sin_points_quarter(count_full)]))
print('};\n')