(2013-10-16) [LatinoWare] Processamento de sinais em Python

download (2013-10-16) [LatinoWare] Processamento de sinais em Python

If you can't read please download the document

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