(2013-10-16) [LatinoWare] Processamento de sinais em Python
-
Upload
danilo-j-s-bellini -
Category
Technology
-
view
1.184 -
download
0
Transcript of (2013-10-16) [LatinoWare] Processamento de sinais em Python
Processamento de sinais em Python
Uma introduo com nfase em aplicaes em udio
Danilo de Jesus da Silva Bellini (AudioLazy Developer)danilo.bellini [at] gmail.com Twitter: @danilobellinihttps://pypi.python.org/pypi/audiolazy
AudioLazy
DSP (Digital Signal Processing) para udioAnliseMIR (Music Information Retrieval)
Sntese
Processamento
Expressividade de cdigoFacilita prototipao, simulao
Tempo real (latncia de aproximadamente 35ms c/ o Jack)Possibilita uso em aplicaes finais
Python 2 e 3c/ o mesmo cdigo!
Documentao (Sphinx)http://pythonhosted.org/audiolazy
Resultados cobertura de cdigo
(Testes automatizados)
--------------- coverage: platform linux2, python 2.7.3-final-0 ----------------Name Stmts Miss Branch BrPart Cover Missing------------------------------------------------------------__init__ 44 1 18 4 92% 72lazy_analysis 125 3 60 2 97% 211, 259-260lazy_auditory 60 0 14 0 100% lazy_compat 42 5 6 1 88% 43, 67-68, 78-79lazy_core 175 7 80 9 94% 124, 136-138, 346, 471, 478lazy_filters 521 176 247 115 62% 57, 64, 85, 95, [...]lazy_io 156 43 58 28 67% 89, 141-157, 161, [...]lazy_itertools 41 7 20 11 70% 39, 60-61, 66, 108-111lazy_lpc 128 15 42 7 87% 121, 135-136, [...]lazy_math 61 1 28 0 99% 133lazy_midi 54 5 26 3 90% 70, 111, 150, 156, 158lazy_misc 110 9 62 10 89% 156-157, 194, [...]lazy_poly 191 2 126 3 98% 396-397lazy_stream 175 2 76 4 98% 59, 738lazy_synth 251 32 124 40 81% 278-300, 467, 469, [...]lazy_text 102 33 70 29 64% 132-147, 205-229, [...]------------------------------------------------------------TOTAL 2236 341 1057 266 82%
========================= 2310 passed in 22.36 seconds =========================
Mock
Orculos(NumPy, SciPy)
Parte 1
Como funciona um teclado sintetizador?
Talk is cheap.Show me the code.
(Linus Torvalds)
Hello world em udio
Tocar uma senideConsole(e.g. IPython)
ScriptsGerenciadores de contexto
from audiolazy import *
rate = 44100s, Hz = sHz(rate)
player = AudioIO()snd = sinusoid(440 * Hz).limit(2 * s)th = player.play(snd, rate=rate) # an AudioThread
player.close() # Kill th (AudioIO arg isn't true)
with AudioIO(True) as player: # Wait threads player.play(snd, rate=rate)
Multithread!
Notas/Alturas e MIDI Pitch
Pitch (notas/alturas)C = D
D = R
E = Mi
F = F
G = Sol
A = L
B = Si
OitavasIniciam em d
Ignoram a alteraoCb4 (d bemol) a mesma nota que B3
MIDI PitchDefine 69 como A4 (l central), deslocamento em semitons
Funes para realizar conversesmidi2str
str2midi
freq2str
str2freq
midi2freq
freq2midi
Controle e tipos de sntese
ControlStreamProperty value
Permite interatividadeTempo real
SnteseAditiva (e.g. classe TableLookup)
ModulaoRing Modulation (Anel)Senide * Senide
AM (Amplitude)Senide * (1 + Senide)
FM (Frequncia ou fase)Senide(Senide)
Subtrativa (e.g. modelo de Karplus-Strong)
Exemplos!!!getch, tkinter,wxPython, music21
In [1]: data = ControlStream(42)
In [2]: data.take(5)Out[2]: [42, 42, 42, 42, 42]
In [3]: data.value = -1
In [4]: data.take(5)Out[4]: [-1, -1, -1, -1, -1]
Parte 2
Funcionamento do altofalante e Representao do udio
Container para udio
Tempo realAmostras (dados/elementos) inexistentes......em tempo de compilao (dados a serem coletados)
...em tempo de execuo (dados criados no futuro)
Durao possivelmente indefinida (endless)
No deve ser necessrio computar tudo para comear a apresentar o resultadoResultados parciais
Para cada amostra de entrada, deve haver uma de sadaMinimizar lag (atraso) entre entrada e sada
Laziness!
Ocorre em udio e em vdeos, mas no em imagens estticas
Classe Stream
Itervel
Heterogneo
Lazy! (Avaliao tardia)
Operadores (Elementwise/broadcast)
Mtodos (take, peek, limit, skip, map, filter, blocks)
In [1]: from audiolazy import Stream, infIn [2]: dados = Stream(5, 7, 1, 2, 5, 3, 2) # PeridicoIn [3]: dados2 = Stream(0, 1) # Idem
In [4]: (dados + dados2).take(15)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)Out[5]: [2.0, 0.0, 14]
In [1]: data = Stream(range(7))
In [2]: blks = data.blocks(size=3, hop=2)
In [3]: [list(blk) for blk in blks]Out[3]: [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
Parte 3
Efeito wah, knob guitarra, transies
Filtros digitais e a Transformada Z
Filtros LTI
(Lineares e invariantes no tempo)
Digital signal processing is mainly based on linear time-invariant systems.
(Dutilleux, Dempwolf, Holters e ZlzerDAFx, segunda edio, captulo 4, p. 103)
Transformada Z
Definio:
Interpretao:Atraso em k amostras!
In [1]: from audiolazy import z, inf
In [2]: sig = [1, 2, 3, 4, 5, 6, 7]
In [3]: (z ** -2)(sig).take(inf)Out[3]: [0.0, 0.0, 1, 2, 3, 4, 5]
In [4]: (1 - z ** -2)(sig).take(inf)Out[4]: [1.0, 2.0, 2, 2, 2, 2, 2]
Objeto z
In [1]: from audiolazy import z, Stream, maverage
In [2]: M = 5
In [3]: media_movel_5 = (1 - z ** -M) / (M * (1 - z ** -1))
In [4]: acumulador = 1 / (1 - z ** -1)
In [5]: media_movel_5(Stream(5)).take(10)Out[5]: [1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0]
In [6]: acumulador(Stream(5)).take(10)Out[6]: [5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0]
In [7]: maverage.recursive(4)Out[7]:0.25 - 0.25 * z^-4------------------ 1 - z^-1
Filtros LTI, em geral:
Filtros prontos!
AudioLazyMdia mvel
Ressonadores
Comb
Passa-baixas
Passa-altas
Gammatone (Patterson-Holdsworth, audio)
Scipy.signalButterworth
Chebyshev
Elptico
Filtros variantes no tempo!Coeficientes (fatores a em parcelas a * z ** -k) podem ser objetos Stream)
JIT!
Plot (AudioLazy + MatPlotLib)!
DTFT - Caso particular da transformada ZO valor de z est na circunferncia complexa unitria
Mtodo plot dos filtrosResposta em frequncia
Mtodo zplotEstabilidade do filtro
Plos: XRazes do denominador
Zeros: ORazes do numerador
X
X
Parte 4
Anlise
MIR(Music Information Retrieval)
O que altura / pitch?Como um afinador de guitarra funciona?
Pitch Shepard
Exemplo no GitHub
Cientista prope dividir o pitch em duas dimenses:Altura (pitch height)Dimenso linear
Croma (pitch chroma)Dimenso circular
Lembra Escher
Hlice
Srie harmnica
F0, 2F0, 3F0, 4F0 100 Hz, 200 Hz, 300 Hz...
Comb!
freqs = [str2freq(note) for note in "E2 G#2 B2".split()] # Mi maiorfilt = ParallelFilter(comb.tau(freq_to_lag(freq * Hz), .1 * s) for freq in freqs)filt.plot(samples=8192, rate=rate, min_freq=220*Hz, max_freq=880*Hz).show()
Inteiros?Racionais?Primos?2+oitava
Coletando a altura
ZCR (Taxa de cruzamento no zero)
DFT (Transformada Discreta de Fourier)
AMDF (Average Magnitude Difference Function)
Autocorrelao (numpy.correlate)
Transcrio por envoltria dinmica
Decomposio cromtica
Filtros gammatoneParalelo
Oitavas
In [1]: from audiolazy import octaves
In [2]: octaves(440)Out[2]: [27.5, 55.0, 110.0, 220.0, 440, 880, 1760, 3520, 7040, 14080]
from __future__ import divisionfrom audiolazy import *
def cromafb(classes=12, rate): s, Hz = sHz(rate) cg = gammatone_erb_constants(4)[0] fb = 440
return [ ParallelFilter( gammatone.sampled(f*Hz, cg*erb(f)) for f in octaves(fb * 2**(n/classes)) ) for n in xrange(classes) ]
rate = 44100bank = cromafb(rate=rate)bank[0].plot(freq_scale="log", rate=rate)
Cromagrama
from audiolazy import *
rate = 22050s, Hz = sHz(rate)size = 512table = sin_table.harmonize({1: 1, 2: 5, 3: 3, 4: 2, 6: 9, 8: 1}).normalize()
data = table(str2freq("Bb3") * Hz).take(size) # Nota si bemol da 3a oitavafilt = lpc(data, order=14) # Filtro de anliseG = 1e-2 # Ganho apenas para alinhamento na visualizao com a DFT
# Filtro de sntese(G / filt).plot(blk=data, rate=rate, samples=1024, unwrap=False).show()
Envoltria espectral
LPC - Predio Linear
Formantes
Pode ser utilizado para classificao de vogais
Parte 5
Interdisciplinaridade interna
Clculo numrico
Gerao de imagens
Fibonacci
h[0] = 0
h[1] = 1
h[n] = h[n-1] + h[n-2]Entrada [0, 1, 0, 0, 0, 0, ...] aplicado a esse filtro digital
Funo impulse()
In [2]: (z ** -1 / (1 - z ** -1 - z ** -2))(impulse(zero=0, ...: one=1), zero=0).take(17)Out[2]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
Polinmios
Baseados em dicionrioMemria
Expoente negativo (Laurent)
Expoente fracionrio (soma de potncias)
Objeto x
InterpolaoLagrange
In [9]: lagrange.poly([(0, 0), (1, 1)])Out[9]: x
In [10]: lagrange.poly([(0, 0), (1, 1), (2, 2)])Out[10]: x
In [11]: lagrange.poly([(0, 0), (1, 1), (2, 4)])Out[11]: x^2
In [9]: lagrange.poly([(1, 3), (3, 14), (45, 0)])Out[9]: -2.89773 + 6.0303 * x - 0.132576 * x^2
In [7]: (x + x ** 2 + x ** -.5)(4)Out[7]: 20.5
Licenas
LinguagemPython (CPython) PSFL
Processamento de SinaisAudioLazy (anlise, sntese e processamento) GPLv3
PyAudio (reproduo e gravao de udio) MIT
MatPlotLib (visualizao grfica) PSFL
NumPy (FFT, lgebra linear) BSD 3-Clause
SciPy (signal) BSD 3-Clause
GUIwxPython/wxWidgets wxWindows
[Tcl/]Tk BSD
Tkinter PSFL
Outrospy.test (testes automatizados) MIT
music21 (musicologia) LGPLv3+
Sphinx (documentao) BSD
Obrigado!
Perguntas?
Fork me on GitHubhttps://github.com/danilobellini/audiolazy
Foz do Iguau PR Processamento de sinais em Python2013-10-16 Danilo J. S. Bellini @danilobellini