Skip to content

Instantly share code, notes, and snippets.

@bit-hack
Last active July 3, 2018 08:50
Show Gist options
  • Save bit-hack/93310d1bb4f5e0572a5fe46a7b6044a6 to your computer and use it in GitHub Desktop.
Save bit-hack/93310d1bb4f5e0572a5fe46a7b6044a6 to your computer and use it in GitHub Desktop.
Band limited waveform sample generation
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