Skip to content

Instantly share code, notes, and snippets.

@danilobellini
Created October 11, 2013 18:59
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 danilobellini/6940208 to your computer and use it in GitHub Desktop.
Save danilobellini/6940208 to your computer and use it in GitHub Desktop.
A Hard Day's Night first chord with AudioLazy + PyAudio (Based on an example from the Coursera DSP course)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created on Thu Oct 10 15:29:33 2013
# @author: Danilo J. S. Bellini
"""
A Hard Day's Night first chord with AudioLazy + PyAudio
"""
from audiolazy import (white_noise, rint, freq_to_lag, zeros, comb, sHz,
str2freq, AudioIO)
def truncated_karplus_strong(freq, tau, memory=white_noise):
"""
Karplus-Strong algorithm.
Parameters
----------
freq:
Frequency, in rad/sample.
tau:
Time, in samples, until decaying from 1 to 1/e in amplitude (approx.
-8.686 dB). You can find ``tau`` from half-power decay duration with
``tau = halfpower_decay * dB20(1/e) / dB10(.5)``.
memory:
Past memory in the Karplus-Strong comb filter. Original algorithm
proposes random data (white noise). Defaults to uniformly distributed
white noise from -1 to 1.
Returns
-------
A Stream object with the played tune.
Note
----
This function truncates the frequency to the nearest integer lag. Decay
time (in samples) doesn't need to be integer.
"""
rounded_lag = rint(freq_to_lag(freq))
filt = comb.tau(rounded_lag, tau)
return filt(zeros(), memory=memory)
# Initialization
rate = 48000
s, Hz = sHz(rate)
ms = 1e-3 * s
# Synth model parameters
tau = 626.7 * ms # 217.2 * ms half-power decay
# Original tau was approx. 626.698490797 * ms
memory = white_noise(low=0, high=1) # No negative value: DC level isn't zero
ks = lambda freq: truncated_karplus_strong(freq, tau=tau, memory=memory)
# Synthesizes the chord
pitches = "D2 D3 F3 G3 F4 A4 C5 G5"
gains = [1.2, 3.0, 1.0, 2.2, 1.0, 1.0, 1.0, 3.5] # Per note
freqs = str2freq(pitches.split())
notes = (gain * ks(freq * Hz) for freq, gain in zip(freqs, gains))
snd = sum(notes) / sum(gains)
# Plays it for some seconds
with AudioIO(True) as player:
player.play(snd.take(4 * s), rate=rate)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment