Last active
July 3, 2018 08:50
-
-
Save bit-hack/93310d1bb4f5e0572a5fe46a7b6044a6 to your computer and use it in GitHub Desktop.
Band limited waveform sample generation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
import csv | |
import StringIO | |
import random | |
def sinc(x): | |
theta = 2.0 * x * math.pi * 4.0 | |
try: | |
return min(1.0, math.sin(theta) / theta) | |
except: | |
return 1.0 | |
def gen_sync(): | |
y = [0] * 256 | |
for i, x in enumerate(range(-128, 128)): | |
atten = math.cos((float(abs(x)) / 128.0) * math.pi * 0.5) | |
y[i] = sinc(float(x) / 128) * atten | |
return y | |
def write_sync(): | |
y = gen_sync() | |
# write output | |
with open('out.csv', 'wb') as f: | |
for d in y: | |
f.write('{:f}'.format(d)) | |
f.write(',') | |
def fourier_tri(x, nyquist): | |
limit = nyquist * 2.0 * math.pi | |
v = 0.0 | |
for i in range(0, 50): | |
n = 2.0 * i + 1.0 | |
theta = 2.0 * math.pi * n | |
if theta > limit: | |
break | |
s = math.pow(-1, i) | |
l = math.pow(n, -2) | |
v += s * l * math.sin(theta * x) | |
return v | |
def fourier_saw(x, nyquist): | |
limit = nyquist * 2.0 * math.pi | |
v = 0.0 | |
for k in range(1, 50, 1): | |
theta = 2.0 * math.pi * float(k) | |
if theta > limit: | |
break | |
n = 1 if (k % 1 == 0) else -1 | |
v += n * math.sin(theta * x) / float(k) | |
return (2.0 / math.pi) * v | |
def fourier_sqr(x, nyquist): | |
limit = nyquist * 2.0 * math.pi | |
v = 0.0 | |
for k in range(1, 50, 2): | |
theta = 2.0 * math.pi * float(k) | |
if theta > limit: | |
break | |
v += math.sin(theta * x) / float(k) | |
return (4.0 / math.pi) * v | |
def gen_fourier(samples, func): | |
out = [0.0] * samples | |
offset = 0.5 / float(samples) | |
for i in range(0, samples): | |
x = (float(i) / float(samples)) + offset | |
out[i] = func(x, samples // 2) | |
return out | |
def fmt_sample(x): | |
return '{}{:04x}'.format( | |
'-0x' if x < 0 else ' 0x', | |
abs(int(x * 0x3fff + random.uniform(-1.2, 1.2)))) | |
def write_array(prefix, width, func, fmt, stream): | |
y = gen_fourier(width, func) | |
stream.write('static const int16_t {}{}[] = {{'.format(prefix, width)) | |
for i, v in enumerate(y): | |
if i > 0: | |
stream.write(', ') | |
if i % 8 == 0: | |
stream.write('\n ') | |
stream.write('{}'.format(fmt(v))) | |
stream.write('};') | |
def dump_c_arrays(): | |
stream = StringIO.StringIO() | |
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- | |
width = 1024 | |
while width > 1: | |
write_array('bl_sqr_', width, fourier_sqr, fmt_sample, stream) | |
stream.write('\n\n') | |
width /= 2 | |
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- | |
width = 1024 | |
while width > 1: | |
write_array('bl_saw_', width, fourier_saw, fmt_sample, stream) | |
stream.write('\n\n') | |
width /= 2 | |
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- | |
width = 1024 | |
while width > 1: | |
write_array('bl_tri_', width, fourier_tri, fmt_sample, stream) | |
stream.write('\n\n') | |
width /= 2 | |
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- | |
with file('tables.c', 'w') as fd: | |
fd.write(stream.getvalue()) | |
def dump_csv_files(): | |
width = 1024 | |
while width > 1: | |
y = gen_fourier(width, fourier_sqr) | |
# write output | |
name = 'sqr_{}.csv'.format(width) | |
with open(name, 'wb') as f: | |
for d in y: | |
f.write('{:f}'.format(d)) | |
f.write(',') | |
# next level of mip | |
width /= 2 | |
if __name__ == '__main__': | |
dump_c_arrays() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment