ii-sound/waveform.py

80 lines
2.0 KiB
Python

import math
import librosa
import numpy
import soundfile as sf
def params(freq, damping, dt):
w = freq * 2 * math.pi * dt
d = damping * dt
e = math.exp(d)
c1 = 2 * e * math.cos(w)
c2 = e * e
t0 = (1 - 2 * e * math.cos(w) + e * e) / (d * d + w * w)
t = d * d + w * w - math.pi * math.pi
t1 = (1 + 2 * e * math.cos(w) + e * e) / math.sqrt(t * t + 4 * d * d *
math.pi * math.pi)
b2 = (t1 - t0) / (t1 + t0)
b1 = b2 * dt * dt * (t0 + t1) / 2
return c1, c2, b1, b2
def wave(count: int, sample_rate):
freq = 3875
dt = 1 / sample_rate
damping = -1210 # -0.015167
c1, c2, b1, b2 = params(freq, damping, dt)
# freq2 = 525
# damping2 = -130
#
# cc1, cc2, bb1, bb2 = params(freq2, damping2, dt)
# mult2 = 1# 0.11
y1 = y2 = 0
x1 = 0
x2 = 0
# tm = math.atan(w/d)/w
# scale = 500 * math.sqrt(d * d+ w * w) * math.exp(-d * tm) / (dt * 2000)
x1 = 1.0
th = 23 # sample_rate // 10
switch = th
scale = 650 # TODO: analytic expression
maxy = 0
for i in range(count):
# y = (c1 * y1 - c2 * y2 + b1 * x1 + b2 * x2) + mult2 * (
# 1 - cc1 * y1 + cc2 * y2 - bb1 * x1 - bb2 * x2)
y = (c1 * y1 - c2 * y2 + b1 * x1 + b2 * x2)
# print(i, y / scale, x1)
x2 = x1
if i >= switch:
x1 = -x1
switch += th
y2 = y1
y1 = y
if math.fabs(y) > maxy:
maxy = math.fabs(y)
yield y / scale
print(maxy)
def main():
# print(list(wave(1020400)))
sample_rate = 1015657
output = numpy.array(list(wave(1015657, sample_rate)), dtype=numpy.float32)
output_rate = 96000 # int(sample_rate / 4)
output = librosa.resample(output, orig_sr=sample_rate,
target_sr=output_rate)
with sf.SoundFile("out.wav", "w", samplerate=96000, channels=1) as f:
f.write(output)
if __name__ == "__main__":
main()