Audio Synthesis with Sines

In [1]:
import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as pt
In [2]:
from simple_audio import play

Let's fix some parameters. The sample_rate says how many values (so-called "samples") are played per second.

The audio hardware takes these 'samples' in blocks of 1024, so we need to do some rounding.

In [3]:
sample_rate = 44100
count = (sample_rate//1024) * 1024
In [4]:
t = np.linspace(0, 1, sample_rate)[:count]

Here are some example tones. What are they?

In [14]:
#signal = np.sin(440*2*np.pi*t)
#signal = np.sin(880*2*np.pi*t)
#signal = 0.5 * (np.sin(880*2*np.pi*t) + np.sin(440*2*np.pi*t))
signal = 0.5 * (np.sin(1209*2*np.pi*t) + np.sin(697*2*np.pi*t))
In [15]:
play(signal)
In [16]:
pt.plot(signal[:500])
Out[16]:
[<matplotlib.lines.Line2D at 0x7f74c341b550>]

That last tone--wouldn't it be useful to pick that apart into its frequency components?

In [17]:
n = 2047
assert n % 2 == 1

cos_k = np.arange(0, n//2 + 1, dtype=np.float64)
sin_k = np.arange(1, n//2 + 1, dtype=np.float64)

x = np.linspace(0, 2*np.pi, n, endpoint=False)

DFT = np.zeros((n,n))
DFT[:, ::2] = np.cos(cos_k*x[:, np.newaxis])
DFT[:, 1::2] = np.sin(sin_k*x[:, np.newaxis])

IDFT = la.inv(DFT)
In [18]:
pt.xlim([-100, 1100])
pt.plot(np.abs(IDFT.dot(signal[:n])))
Out[18]:
[<matplotlib.lines.Line2D at 0x7f74c343abe0>]
In []: