Este documento apresenta um resumo da biblioteca AudioLazy para processamento digital de sinal em Python. Em três frases ou menos:
A biblioteca AudioLazy fornece ferramentas para análise, síntese e processamento de áudio em Python, incluindo filtros digitais, síntese por modulação e amostragem, e suporte para tempo real. A biblioteca usa a transformada Z para modelar filtros digitais linearmente invariantes no tempo. AudioLazy permite prototipagem e simulação de sistemas de processamento de sinal digital de áudio em Python
(2013-07-05) [fisl] Compatibilidade entre Python 2 e 3
(2013-11-29) [RuPy] AudioLazy Python DSP (Digital Signal Processing)
1. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
AudioLazy
Python DSP (Digital Signal Processing)
Danilo de Jesus da Silva Bellini
(AudioLazy Developer)
danilo.bellini [at] gmail.com
Twitter: @danilobellini
https://pypi.python.org/pypi/audiolazy
2. RuPy
2013
●
c/ o Pyth
me on 2
AudioLazy
sm
oc e3
ód
igo
DSP (Digital Signal Processing) para áudio
!
–
Análise
●
–
–
●
MIR (Music Information Retrieval)
Síntese
Processamento
Expressividade de código
–
●
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Prototipação, simulação
Tempo real
–
Uso em aplicações finais
Documentação (Sphinx)
http://pythonhosted.org/audiolazy
4. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Talk is cheap.
Show me the code.
(Linus Torvalds)
5. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
“Hello world”
●
Tocar uma senóide
–
Console
(e.g. IPython)
from audiolazy import *
from audiolazy import *
Multith
re
rate = 44100
rate = 44100
s, Hz = sHz(rate)
s, Hz = sHz(rate)
ad!
player = AudioIO()
player = AudioIO()
snd = sinusoid(440 * Hz).limit(2 * s)
snd = sinusoid(440 * Hz).limit(2 * s)
th = player.play(snd, rate=rate) # an AudioThread
th = player.play(snd, rate=rate) # an AudioThread
player.close() # Kill th (AudioIO arg isn't true)
player.close() # Kill th (AudioIO arg isn't true)
–
Scripts
●
Gerenciadores de contexto
with AudioIO(True) as player: # Wait threads
with AudioIO(True) as player: # Wait threads
player.play(snd, rate=rate)
player.play(snd, rate=rate)
6. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Notas/Alturas e MIDI Pitch
●
Pitch (notas/alturas)
–
–
●
C, D, E, F, G, A, B
Do, Re, Mi, Fa, Sol, La, Si
Oitavas
–
–
Iniciam em dó
Ignoram a alteração
●
●
“Cb4” (dó bemol) é a mesma
nota que B3
MIDI Pitch
–
Define 69 como A4 (lá
central), deslocamento em
semitons
●
Funções para realizar
conversões
–
–
–
–
–
–
midi2str
str2midi
freq2str
str2freq
midi2freq
freq2midi
7. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Controle e tipos de síntese
●
ControlStream
–
–
Property “value”
Permite interatividade
●
●
Tempo real
Síntese
–
–
In [2]: data.take(5)
In [2]: data.take(5)
Out[2]: [42, 42, 42, 42, 42]
Out[2]: [42, 42, 42, 42, 42]
In [3]: data.value = -1
In [3]: data.value = -1
In [4]:
In [4]:
Out[4]:
Out[4]:
data.take(5)
data.take(5)
[-1, -1, -1, -1, -1]
[-1, -1, -1, -1, -1]
Aditiva (e.g. classe TableLookup)
Modulação
●
Ring Modulation (Anel)
–
●
●
Senóide * Senóide
AM (Amplitude)
–
Senóide * (1 + Senóide)
FM (Frequência ou fase)
–
–
In [1]: data = ControlStream(42)
In [1]: data = ControlStream(42)
Senóide(Senóide)
Subtrativa (e.g. modelo de Karplus-Strong)
8. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Exemplos
●
●
Exempl
os no re
Hardware
positório
!!!
keyboar
– Arduino via PySerial
d.py (co
m tkinte
mcfm.p
y (com
Jogos
play_ba
wxPytho r)
ch_chor
n)
al.py (co
save_an
– Campo minado
m m us i c
d_m em
2 1)
oize_sy
nth (wa
Síntese em tempo real
ve)
– Klockwork
●
●
Recortes e normalização (geração de arquivos WAV)
9. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Container para áudio
●
Qualquer iterável pode ser áudio!
●
Tempo real
–
Amostras (dados/elementos) inexistentes...
●
●
...em tempo de compilação (dados a serem coletados)
...em tempo de execução (dados criados no futuro)
–
Suporte a “endless”
Causal (independe de dados futuros)
–
Minimizar lag (atraso) entre entrada e saída
–
Lazy!
10. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Classe Stream
In [1]: data = Stream(range(7))
In [1]: data = Stream(range(7))
Iterável
In [2]: blks = data.blocks(size=3, hop=2)
In [2]: blks = data.blocks(size=3, hop=2)
●
Heterogêneo
In [3]: [list(blk) for blk in blks]
In [3]: [list(blk) for blk in blks]
Out[3]: [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
Out[3]: [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
●
Lazy! (Avaliação tardia)
●
Operadores (Elementwise/broadcast)
●
Métodos (take, peek, limit, skip, map, filter, blocks)
●
In
In
In
In
In
In
[1]:
[1]:
[2]:
[2]:
[3]:
[3]:
from audiolazy import Stream, inf
from audiolazy import Stream, inf
dados = Stream(5, 7, 1, 2, 5, 3, 2) # Periódico
dados = Stream(5, 7, 1, 2, 5, 3, 2) # Periódico
dados2 = Stream(0, 1) # Idem
dados2 = Stream(0, 1) # Idem
In [4]: (dados + dados2).take(15)
In [4]: (dados + dados2).take(15)
Out[4]: [5, 8, 1, 3, 5, 4, 2, 6, 7, 2, 2, 6, 3, 3, 5]
Out[4]: [5, 8, 1, 3, 5, 4, 2, 6, 7, 2, 2, 6, 3, 3, 5]
In [5]: (_ * Stream(1 + 2j, -3j, 7).imag).map(int).take(inf)
In [5]: (_ * Stream(1 + 2j, -3j, 7).imag).map(int).take(inf)
Out[5]: [2.0, 0.0, 14]
Out[5]: [2.0, 0.0, 14]
11. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Efeito “wah”, knob guitarra, transições
Filtros digitais e a Transformada Z
12. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Filtros LTI
(Lineares e invariantes no tempo)
“Digital signal processing is mainly
based on linear time-invariant
systems.”
systems.”
(Dutilleux, Dempwolf, Holters e Zölzer
DAFx, segunda edição, capítulo 4, p. 103)
13. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Transformada Z
●
Definição:
●
Interpretação:
Atraso em k
amostras!
In [1]: from audiolazy import z, inf
In [1]: from audiolazy import z, inf
In [2]: sig = [1, 2, 3, 4, 5, 6, 7]
In [2]: sig = [1, 2, 3, 4, 5, 6, 7]
In [3]:
In [3]:
Out[3]:
Out[3]:
(z **
(z **
[0.0,
[0.0,
-2)(sig).take(inf)
-2)(sig).take(inf)
0.0, 1, 2, 3, 4, 5]
0.0, 1, 2, 3, 4, 5]
In [4]: (1 - z ** -2)(sig).take(inf)
In [4]: (1 - z ** -2)(sig).take(inf)
Out[4]: [1.0, 2.0, 2, 2, 2, 2, 2]
Out[4]: [1.0, 2.0, 2, 2, 2, 2, 2]
14. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Plot (AudioLazy + MatPlotLib)!
g
●
gammat
o n e _ p lo
ts.py
também
tem
respost
a ao i m
pul s o
DTFT - Caso particular da transformada Z
–
●
Método plot dos filtros
–
●
O valor de z está na circunferência complexa unitária
Resposta em frequência
X
Método zplot
–
–
Estabilidade do filtro
Pólos: “X”
●
–
Raízes do denominador
Zeros: “O”
●
Raízes do numerador
X
15. RuPy
2013
●
AudioLazy
–
–
–
–
–
–
●
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Média móvel
Ressonadores
Comb
Passa-baixas
Filtr
Coe os varia
ntes
parc ficien
n
tes (
elas
fato o temp
“a *
o
r
obje z ** -k” es “a” e !
tos S ) po
d em m
trea
se r
m)
e.g.
lptv.
py
Passa-altas
Gammatone (Patterson-Holdsworth, audição)
Scipy.signal
–
Butterworth
Chebyshev
–
Elíptico
–
Filtros prontos!
JIT!
16. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Fibonacci
●
h[0] = 0
●
h[1] = 1
●
E o e xe
mplo
pi.py?
h[n] = h[n-1] + h[n-2]
–
●
Entrada [0, 1, 0, 0, 0, 0, ...] aplicado a esse filtro digital
Função impulse()
h [n]=h[n−1]+ h[ n−2]+ δ[ n−1]
In [2]: (z ** -1 / (1 - z ** -1 - z ** -2))(impulse(zero=0,
In [2]: (z ** -1 / (1 - z ** -1 - z ** -2))(impulse(zero=0,
...:
one=1),
...:
one=1),
Out[2]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
Out[2]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
zero=0).take(17)
zero=0).take(17)
377, 610, 987]
377, 610, 987]
17. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Pitch – Shepard
●
Exemplo no GitHub
●
2 dimensões:
–
Altura (pitch height)
●
–
Croma (pitch chroma)
●
●
●
Dimensão “linear”
Dimensão “circular”
Lembra Escher →
“Hélice”
18. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Série harmônica
●
F0, 2F0, 3F0, 4F0 …
–
100 Hz, 200 Hz, 300 Hz...
Comb!
freqs = [str2freq(note) for note in "E2 G#2 B2".split()] # Mi maior
freqs = [str2freq(note) for note in "E2 G#2 B2".split()] # Mi maior
filt = ParallelFilter(comb.tau(freq_to_lag(freq * Hz), .1 * s)
filt = ParallelFilter(comb.tau(freq_to_lag(freq * Hz), .1 * s)
for freq in freqs)
for freq in freqs)
filt.plot(samples=8192, rate=rate, min_freq=220*Hz, max_freq=880*Hz).show()
filt.plot(samples=8192, rate=rate, min_freq=220*Hz, max_freq=880*Hz).show()
19. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Coletando a altura
●
ZCR (Taxa de cruzamento no zero)
●
DFT (Transformada Discreta de Fourier)
●
AMDF (Average Magnitude Difference Function)
20. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Envoltória espectral com
LPC (Linear Predictive Coding)
Formantes
Pode ser utilizado
para classificação de
vogais
(análise e síntese)
e.g.
lpc_plot.py
formants.py
21. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Polinômios
●
Baseados em dicionário
In [7]: (x + x ** 2 + x ** -.5)(4)
In [7]: (x + x ** 2 + x ** -.5)(4)
Out[7]: 20.5
Out[7]: 20.5
–
Memória
Expoente negativo (Laurent)
–
Expoente fracionário (soma de potências)
–
●
Objeto “x”
●
Interpolação
–
Lagrange
In [9]: lagrange.poly([(0, 0), (1, 1)])
In [9]: lagrange.poly([(0, 0), (1, 1)])
Out[9]: x
Out[9]: x
In [10]: lagrange.poly([(0, 0), (1, 1), (2, 2)])
In [10]: lagrange.poly([(0, 0), (1, 1), (2, 2)])
Out[10]: x
Out[10]: x
In [11]: lagrange.poly([(0, 0), (1, 1), (2, 4)])
In [11]: lagrange.poly([(0, 0), (1, 1), (2, 4)])
Out[11]: x^2
Out[11]: x^2
In [9]:
In [9]:
Out[9]:
Out[9]:
lagrange.poly([(1, 3), (3, 14), (45, 0)])
lagrange.poly([(1, 3), (3, 14), (45, 0)])
-2.89773 + 6.0303 * x - 0.132576 * x^2
-2.89773 + 6.0303 * x - 0.132576 * x^2
22. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Imagens feitas com a AudioLazy
23. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
24. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
25. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
26. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
27. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
28. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
29. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
30. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
É possível... ?
●
Em tempo real...
–
–
Distorção ?
Delay ?
–
Flanger ?
Phaser ?
–
Compressor/limiter ?
–
Vejamos...
31. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
2013 – PSI2222
Orientações at Poli-USP
●
Pedaleira (4 alunos)
–
–
https://github.com/RicardoBoccoliGallego/DigitalPedalBoard
PySerial
●
●
–
AudioLazy
●
–
–
Hardware controlador em Arduino
2 botões + pedal expressão
Distorção, flanger, filtros, …
wxPython
MatPlotLib
●
Gráfico da envoltória dinâmica (envelope) atualizado em tempo real
32. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
33. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
34. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
35. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
2013 – PSI2222
Orientações at Poli-USP
●
Sintetizador (outros 4 alunos) [inacabado]
–
–
https://github.com/elisatengan/Synthesis
PyGame
●
–
AudioLazy
●
●
–
I/O MIDI
Modelo de Karplus-Strong modificado
LPC: Filtros de síntese/análise
PyQt4
36. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
GUI dos alunos inacabada, conforme exibida no RuPy.
Posteriormente ocorreram modificações.
37. RuPy
2013
2013-11-29 – AudioLazy Python DSP (Digital Signal Processing)
São José dos Campos – SP – Danilo J. S. Bellini – @danilobellini
Obrigado!
Perguntas?
Fork me on GitHub
https://github.com/danilobellini/audiolazy