Skip to content

Instantly share code, notes, and snippets.

@Kailang
Created October 20, 2017 00:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kailang/b41321a99eaad8d44bc648ab75440753 to your computer and use it in GitHub Desktop.
Save Kailang/b41321a99eaad8d44bc648ab75440753 to your computer and use it in GitHub Desktop.
advanced app
import numpy as np;
import matplotlib.pyplot as plt;
import sounddevice as sd;
from math import *;
def note_to_freq(n):
return 27.5 * 2 ** ((n - 21.0) / 12.0);
def build_sin(size):
return [sin(2.0 * pi * i / size) for i in range(size)];
def virtual_to_buffer(index):
return int(round((sample_rate / clock_rate) * index));
def freq_to_step(freq):
return int(round(clock_rate / freq));
sample_rate = 48000.0;
clock_rate = 3579545.454545;
buffer_size = 1024; # in sample_rate
buffer_size_virtual = int(round((clock_rate / sample_rate) * buffer_size)); # in clock_rate
buf = np.zeros(buffer_size * 2);
print("A", note_to_freq(69));
print("buffer_size_virtual", buffer_size_virtual);
freqs = [note_to_freq(n) for n in range(21, 109)];
periods = [int(round(sample_rate / f)) for f in freqs];
time = 0;
period = 0;
table = build_sin(16);
samples = np.zeros(len(table));
for i in range(0, len(table)):
samples[i] = table[(i + 1) % len(table)] - table[i];
# samples = [ 0.7, 0.3, -0.3, -0.7 ];
plt.plot(range(len(table)), table);
plt.show();
plt.plot(range(len(samples)), samples);
plt.show();
step = freq_to_step(note_to_freq(69) * len(samples));
# step
fc = 0.25;
pulse_table_size = 40;
pulse_step_size = 20;
pulse_table = np.zeros((pulse_step_size, pulse_table_size + 1));
for j in range(pulse_step_size):
s = -float(j) / pulse_step_size;
for i in range(pulse_table_size + 1):
if (i - pulse_table_size / 2 == 0):
pulse_table[j][i] = 2 * pi * fc;
else:
pulse_table[j][i] = sin(2 * pi * fc * ((i + s) - pulse_table_size / 2)) / ((i + s) - pulse_table_size / 2);
pulse_table[j][i] *= 0.42 + 0.8 * cos(4 * pi * (i + s) / pulse_table_size) - 0.5 * cos(2 * pi * (i + s) / pulse_table_size);
s = sum(pulse_table[j]);
for i in range(pulse_table_size + 1):
pulse_table[j][i] /= s;
plt.plot(range(pulse_table_size + 1), pulse_table[0]);
plt.show();
# plt.plot(range(pulse_table_size + 1), pulse_table[pulse_step_size // 2]);
# plt.show();
# plt.plot(range(pulse_table_size + 1), pulse_table[pulse_step_size - 1]);
# plt.show();
# somehow doesn't work
def mix_buffer(value, time, bandlimited):
if bandlimited:
current = (sample_rate / clock_rate) * time;
step = int(round((current - int(current)) * pulse_step_size));
# if step == pulse_step_size:
# step = 0;
# current + 1;
# print(step);
for i in range(pulse_table_size + 1):
# buf[int(current) + i] += value * pulse_table[step][i];
buf[int(round(current)) + i] += value * pulse_table[0][i];
else:
buf[virtual_to_buffer(time)] = value;
while time < buffer_size_virtual:
mix_buffer(samples[period], time, True);
time += step;
period += 1;
if period >= len(samples):
period = 0;
plt.plot(range(buffer_size), buf[:buffer_size]);
plt.show();
running_sum = 0;
for i in range(buffer_size):
running_sum = running_sum + buf[i];
buf[i] = running_sum * 0.5;
plt.plot(range(buffer_size), buf[:buffer_size]);
plt.show();
fft = np.abs(np.fft.fft(buf[:buffer_size]))[:int(buffer_size / 2)];
plt.plot(range(int(buffer_size / 2)), fft);
plt.show();
plt.semilogy(range(int(buffer_size / 2)), fft);
plt.show();
sd.play(buf, sample_rate, blocking = True);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment