%load_ext autoreload
%autoreload 2
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import Audio #, display
import numpy as np
# from pysas import World, waveread # https://github.com/shunsukeaihara/pysas
from matplotlib import pyplot as plt, colors
hsv = [(i, .8, .8) for i in np.linspace(0,1,12,endpoint=False)]
rgb = colors.hsv_to_rgb(hsv)
samplerate = 44100.
nyquist = samplerate / 2.
π = np.pi
τ = 2*π
import soundfile
def pad2(i):
return '{0:02d}'.format(i)
# read phoneme WAVs from file
datas = []
path = "/Users/pi/Dev/pythonStuff/VowelGen/4. Analyze my own vowels/vowels/me/"
for i in range(12):
file = path + pad2(i) + '.aiff'
print(file)
data, samplerate = soundfile.read( file )
data = data[:,0]
datas.append( data )
from pysas import World
world = World(samplerate, frameperiod=5)
def plot_spectrum(axes, spectrum, **kwargs):
axes.grid(which='both')
#axes.xaxis.grid(True)
axes.set_xticks(np.arange(0, 22.050, 3.000))
axes.set_xticks(np.arange(0, 22.050, 1.000), minor=True)
axes.xaxis.grid(which='minor', alpha=0.2)
axes.xaxis.grid(which='major', alpha=0.5)
freqs = np.linspace(0, 22.050, 1024+1)
axes.plot(freqs, np.log(spectrum), **kwargs)
spectra = []
for signal in datas:
f0, spec_mat, aperiod_mat = world.analyze(signal)
spec = np.average( spec_mat[f0 > 40][20:-20], axis=0 )
if len(spectra)==0:
plt.subplots()
plt.plot(f0, 'b', linewidth=2)
fig, axes = plt.subplots()
plot_spectrum( axes, spec, color='r', linewidth=2)
for i,k in enumerate([40,80,120]):
plot_spectrum( axes, spec_mat[k], color=rgb[3+i], alpha=.5)
spectra.append(spec)
symbols = ['ɑ', 'a', 'ɛ', 'e', 'i', 'ɔ', 'y', 'u', 'œ', 'ʌ', 'o', 'ɪ̈']
plt.rc('font', family='Arial')
#plt.figure(figsize=(15,8))
fig, axes = plt.subplots(figsize=(15,8))
for c,spec,symbol in zip(rgb,spectra,symbols):
plot_spectrum(axes, spec, color=c, alpha=0.5, label=symbol, linewidth=2)
legend = plt.legend(loc='upper right', shadow=True)
# http://stackoverflow.com/questions/24943991/matplotlib-change-grid-interval-and-specify-tick-labels
fig, ax = plt.subplots(4,3, figsize=(15,6))
for i,(c,spec,symbol) in enumerate(zip(rgb,spectra,symbols)):
axes = ax[i%4] [int(i/4)]
plot_spectrum(axes, spec, color=c, label=symbol, linewidth=2)
from collections import deque, namedtuple
formant_data = [
'ɑ', 660, 1, 9, 1090, 1, 9, 2440, 1, 9,
'a', 660, 1, 9, 1720, 1, 9, 2410, 1, 9,
'ɛ', 530, 1, 9, 1840, 1, 9, 2480, 1, 9,
'e', 490, 1, 9, 1350, 1, 9, 1590, 1, 9,
]
Formant = namedtuple('Formant', 'freq bandwidth gain')
Vowel = namedtuple('Vowel', 'symbol formants filter')
vowels = deque()
acc = []
for x in reversed(formant_data):
if isinstance(x,str):
symbol = x
freqs, bws, gains = acc[0::3], acc[1::3], acc[2::3]
formants = [ Formant(f,bw,g) for f,bw,g in zip(freqs, bws, gains) ]
filters = None # [ formant_filter( f,r,gain) for f,g,bw in formants ]
v = Vowel(symbol, formants, filters)
vowels.appendleft(v)
acc = []
else:
acc = [x] + acc
def formant_filter( f_peak, bandwidth, gain ):
r, θ = np.exp(-π*bandwidth/samplerate), π*f_peak/nyquist
z = r * np.exp( 1j * θ )
zeros, poles, tmp_gain = [], [z,z.conjugate()], 1
Bs, As = zpk2tf( zeros, poles, tmp_gain )
def gain_at(f):
_f = np.asarray(f)
Φ = π * _f/nyquist
w, h = freqz( Bs, As, Φ )
return np.abs( h[0] )
Bs *= gain/gain_at(f_peak)
def func(Xn):
Yn = lfilter( Bs, As, Xn )
return Yn
return func