SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o Python
Slides da apresentação no DevInSampa 2013 (18 de maio), com algumas complementações e correções. Esses mesmos slides foram utilizados na apresentação feita no fisl 2014 (2013-07-05).
Slides da apresentação no DevInSampa 2013 (18 de maio), com algumas complementações e correções. Esses mesmos slides foram utilizados na apresentação feita no fisl 2014 (2013-07-05).
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o Python
1.
AudioLazy - DSP expressivo e em
tempo real para o Python
http://pypi.python.org/pypi/audiolazyhttp://pypi.python.org/pypi/audiolazy
Copyright (C) 2012-2013Copyright (C) 2012-2013
Danilo de Jesus da Silva Bellini <danilo.bellini@gmail.com>Danilo de Jesus da Silva Bellini <danilo.bellini@gmail.com>
2.
Parte 1
Síntese! Show me the code!
Go go go!Go go go!
Não, Python!Não, Python!
3.
“Hello world” em áudio
● Tocar uma senóide
– Console interativo
– Script
from audiolazy import *
rate = 44100
s, Hz = sHz(rate)
th = AudioIO().play(sinusoid(440 * Hz), rate=rate)
from audiolazy import *
rate = 44100
s, Hz = sHz(rate)
th = AudioIO().play(sinusoid(440 * Hz), rate=rate)
from audiolazy import *
rate = 44100
s, Hz = sHz(rate)
with AudioIO(True) as player:
player.play(sinusoid(440 * Hz), rate=rate)
from audiolazy import *
rate = 44100
s, Hz = sHz(rate)
with AudioIO(True) as player:
player.play(sinusoid(440 * Hz), rate=rate)
Multithread!
4.
Síntese
● ControlStream
– Property “value”
– Permite interatividade
● Tempo real
● Síntese
– Ring Modulation - Senóide * Senóide
– AM - Senóide * (1 + Senóide)
– FM - Senóide(Senóide)
– Subtrativa (e.g. Karplus-Strong)
– Aditiva (e.g. TableLookup) Imagem da
Wikipedia
Exemplos!!!wxPython,
Music21
6.
Container para á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)
– Duração possivelmente indefinida
– Não deve ser necessário computar tudo para começar
a apresentar o resultado
● Resultados parciais
● Para cada amostra de entrada, deve haver uma de saída
– Minimizar lag (atraso) entre entrada e saída
Avaliação tardia!
7.
Classe Stream
● Iterável
● Heterogêneo
● Operadores
– Elementwise/broadcast
como no NumPy
● Avaliação tardia
– Lembra geradores
● Já estávamos usando!
– sinusoid,
karplus_strong,
ControlStream, ...
● Ausência de índices
– Limite de representação
inteira (32 bits
estouraria em 27:03:12)
In [1]: from audiolazy import Stream
In [2]: dados = Stream(5, 7, 1, 2, 5, 3, 2) # Periódico
In [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 [1]: from audiolazy import Stream
In [2]: dados = Stream(5, 7, 1, 2, 5, 3, 2) # Periódico
In [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]
8.
Classe Stream
● Métodos, atributos e propriedades são aplicados
elemento a elemento
– Exceto quando existe na classe Stream (“take”,
“blocks”, “peek”, “skip”, “limit”, ...)
● Finito ou de finalização indeterminada
In [5]: Stream([2, 3, 4]).take(5) # Lista de entrada
Out[5]: [2, 3, 4]
In [6]: Stream(2, 3, 4).take(5) # Números de entrada
Out[6]: [2, 3, 4, 2, 3]
In [7]: Stream(*[2, 3, 4]).take(5) # Lista com "*"
Out[7]: [2, 3, 4, 2, 3]
In [8]: (2 * Stream([1 + 2j, -3j, 7]).real).take(inf)
Out[8]: [2.0, 0.0, 14]
In [5]: Stream([2, 3, 4]).take(5) # Lista de entrada
Out[5]: [2, 3, 4]
In [6]: Stream(2, 3, 4).take(5) # Números de entrada
Out[6]: [2, 3, 4, 2, 3]
In [7]: Stream(*[2, 3, 4]).take(5) # Lista com "*"
Out[7]: [2, 3, 4, 2, 3]
In [8]: (2 * Stream([1 + 2j, -3j, 7]).real).take(inf)
Out[8]: [2.0, 0.0, 14]
9.
Decorador tostream:
Geradores convertidos em Stream
● Já foi aplicado a TODOS os itertools (e.g. count)!!!
In [1]: from audiolazy import tostream
In [2]: @tostream
...: def impulse():
...: yield 1
...: while True:
...: yield 0
...:
In [3]: impulse # De fato, uma função
Out[3]: <function __main__.impulse>
In [4]: impulse() # Devolve um objeto Stream
Out[4]: <audiolazy.lazy_stream.Stream at 0x30824d0>
In [5]: impulse().take(5)
Out[5]: [1, 0, 0, 0, 0]
In [6]: (impulse() + 1).take(5) # Outro objeto instanciado
Out[6]: [2, 1, 1, 1, 1]
In [1]: from audiolazy import tostream
In [2]: @tostream
...: def impulse():
...: yield 1
...: while True:
...: yield 0
...:
In [3]: impulse # De fato, uma função
Out[3]: <function __main__.impulse>
In [4]: impulse() # Devolve um objeto Stream
Out[4]: <audiolazy.lazy_stream.Stream at 0x30824d0>
In [5]: impulse().take(5)
Out[5]: [1, 0, 0, 0, 0]
In [6]: (impulse() + 1).take(5) # Outro objeto instanciado
Out[6]: [2, 1, 1, 1, 1]
Síntese
personalizada!
(Acesso direto
às amostras)
10.
Processamento em bloco
● Stream.blocks(size, hop)
– Qualquer salto (hop) positivo
– Se mudar a saída, a mudança persistirá na próxima
saída quando hop < size
● Saídas são a mesma fila circular implementada como
collections.deque
In [1]: data = Stream([1, 2, 3, 4, 5])
In [2]: blks = data.blocks(size=2, hop=1)
In [3]: [list(blk) for blk in blks]
Out[3]: [[1, 2], [2, 3], [3, 4], [4, 5]]
In [1]: data = Stream([1, 2, 3, 4, 5])
In [2]: blks = data.blocks(size=2, hop=1)
In [3]: [list(blk) for blk in blks]
Out[3]: [[1, 2], [2, 3], [3, 4], [4, 5]]
12.
Filtros LTI
(Lineares e invariantes no tempo)
““Digital signal processing is mainlyDigital signal processing is mainly
based on linear time-invariantbased on linear time-invariant
systems.systems.””
(Dutilleux, Dempwolf, Holters e Zölzer(Dutilleux, Dempwolf, Holters e Zölzer
DAFx, segunda edição, capítulo 4, p. 103)DAFx, segunda edição, capítulo 4, p. 103)
13.
Transformada Z
● Definição:
● Interpretação:
–Atrasoem k
amostras!
● Muitos “infinitos”
– Teoremas
● Possibilitam o uso prático
(eliminam os “infinitos”)
14.
Exemplo de transformada Z
● Acumulador ● Média móvel
Tá legal...mas, na prática, cadê o tal código?!
Saída / Entrada, ou
H(z) = Y(z) / X(z)
15.
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
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:
16.
Filtros prontos!
● Média móvel
● Ressonadores
● Comb
● Passa-baixas e passa-altas
● Gammatone (Patterson-Holdsworth, audição)
– Slaney
– Klapuri
● 4 ressonadores em cascata
– Implementação genérica (qualquer ordem)
● Teoremas (parte de meu mestrado)
Filtros variantes no tempo!
Coeficientes “a” em de a * z ** -k
podem ser objetos Stream)
17.
Plot (AudioLazy + MatPlotLib)!
● DTFT - Caso particular da transformada Z
– O valor de z está na circunferência complexa unitária
● Método plot dos filtros
– Resposta em frequência
● Método zplot
– Estabilidade do filtro
– Pólos: “X”
● Raízes do denominador
– Zeros: “O”
● Raízes do numerador
X
X
MatPlotLib
faz melhor
que isto...
18.
Considerações finais sobre filtros
● Implementação direta I
– Evita multiplicação por 1
– Não cria os termos com coeficiente nulo
● JIT (Just in Time)
– Cada filtro é criado e compilado em tempo de
execução
– Permite filtros variantes no tempo gerais e (até certo
ponto) eficientes
19.
Parte 4 - Cálculo numérico (e um
pouco de simbólico também)
Heeeeeey, não era sobre áudio?Heeeeeey, não era sobre áudio?
20.
Exemplos
● Pi (exemplo no repositório da AudioLazy)
– Série de Madhava-Gregory-Leibniz
● Fibonacci
atan(v)=v−
v3
3
+
v5
5
−
v7
7
+
v9
9
...
atan(1)= π
4
In [2]: (z ** -1 / (1 - z ** -1 - z ** -2))(impulse()).take(10)
Out[2]: [0.0, 1.0, 1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 21.0, 34.0]
In [2]: (z ** -1 / (1 - z ** -1 - z ** -2))(impulse()).take(10)
Out[2]: [0.0, 1.0, 1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 21.0, 34.0]
h[n]=h[n−1]+h[ n−2]+δ[ n−1]
21.
Polinômios
● Necessário para os filtros lineares
● Baseados em dicionário
– Memória
– Expoente negativo (Laurent)
– Expoente fracionário (soma de potências)
● Coeficientes podem ser objetos Stream, símbolos
do SymPy, etc.
● Objeto “x”
● Interpolação (polinômios de Lagrange)
In [9]: lagrange.poly([(1, 3), (3, 14), (45, 0)])
Out[9]: -2.89773 + 6.0303 * x - 0.132576 * x^2
In [9]: lagrange.poly([(1, 3), (3, 14), (45, 0)])
Out[9]: -2.89773 + 6.0303 * x - 0.132576 * x^2
In [8]: (x + x ** 2 + x ** -.5)(4)
Out[8]: 20.5
In [8]: (x + x ** 2 + x ** -.5)(4)
Out[8]: 20.5
23.
Comparação de números em ponto
flutuante (IEEE 754)
● Valor absoluto (limiar “l”)
● Comparação pelo número de bits de mantissa (“t”
bits de tolerância para “s” bits de mantissa)
● Implementado em um dicionário de estratégias:
– almost_eq.diff
– almost_eq ou almost_eq.bits
∣a−b∣≤l
∣a−b∣≤2(t − s−1)∣a+b∣
24.
Quantização em ponto flutuante
Com CascadeFilter
Warning:
Há textos que nem sempre são claros quanto aos aspectos
necessários à implementação para garantir a estabilidade numérica
freq = 100 * Hz
bw = erb(freq, Hz) * gammatone_erb_constants(4)[0]
filt = gammatone.slaney(freq, bw)
filt.plot(rate=rate, freq_scale="log", samples=8192).show()
freq = 100 * Hz
bw = erb(freq, Hz) * gammatone_erb_constants(4)[0]
filt = gammatone.slaney(freq, bw)
filt.plot(rate=rate, freq_scale="log", samples=8192).show()
Sem CascadeFilter
25.
Parte 5
MIRMIR
((Music Information RetrievalMusic Information Retrieval))
26.
Pitch – Shepard
● Som de Shepard
– Subir “sem parar”
– Exemplo no GitHub
● Duas dimensões:
– Altura (pitch height)
● Dimensão “linear”
– Croma (pitch chroma)
● Dimensão “circular”
● Lembra Escher →
27.
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
filt = 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()
freqs = [str2freq(note) for note in "E2 G#2 B2".split()] # Mi maior
filt = 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
28.
ZCR
Taxa de cruzamentos no zero
In [15]: pitch1.take(10) # Resultado em Hz
Out[15]:
[872.0947265625001,
882.861328125,
872.0947265625001,
882.861328125,
882.861328125,
882.861328125,
882.861328125,
872.0947265625001,
882.861328125,
872.0947265625001]
In [16]: freq2str(pitch1).take(10) # Resultado em nomes de notas
Out[16]:
['A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5-15.62%',
'A5+5.62%',
'A5-15.62%',
'A5+5.62%',
'A5+5.62%']
In [15]: pitch1.take(10) # Resultado em Hz
Out[15]:
[872.0947265625001,
882.861328125,
872.0947265625001,
882.861328125,
882.861328125,
882.861328125,
882.861328125,
872.0947265625001,
882.861328125,
872.0947265625001]
In [16]: freq2str(pitch1).take(10) # Resultado em nomes de notas
Out[16]:
['A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5+5.62%',
'A5-15.62%',
'A5+5.62%',
'A5-15.62%',
'A5+5.62%',
'A5+5.62%']
pitch1 = zcross_pitch(data1) / Hzpitch1 = zcross_pitch(data1) / Hz
@tostream
def zcross_pitch(sig, size=2048):
"Devolve a altura em cada bloco com o dado tamanho"
for blk in zcross(sig, hysteresis=.2).blocks(size):
yield lag_to_freq(2. * size / sum(blk))
@tostream
def zcross_pitch(sig, size=2048):
"Devolve a altura em cada bloco com o dado tamanho"
for blk in zcross(sig, hysteresis=.2).blocks(size):
yield lag_to_freq(2. * size / sum(blk))
data1 = .5 * sinusoid(880 * Hz)
data1 += .5 * saw_table(880*3 * Hz)
data1 *= .9 + .1 * white_noise()
data1 = .5 * sinusoid(880 * Hz)
data1 += .5 * saw_table(880*3 * Hz)
data1 *= .9 + .1 * white_noise()
Por quenão DFT?
33.
from audiolazy import *
rate = 22050
s, Hz = sHz(rate)
size = 512
table = 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 oitava
filt = lpc(data, order=14) # Filtro de análise
G = 1e-2 # Ganho apenas para alinhamento na visualização com a DFT
# Filtro de síntese
(G / filt).plot(blk=data, rate=rate, samples=1024, unwrap=False).show()
from audiolazy import *
rate = 22050
s, Hz = sHz(rate)
size = 512
table = 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 oitava
filt = lpc(data, order=14) # Filtro de análise
G = 1e-2 # Ganho apenas para alinhamento na visualização com a DFT
# Filtro de síntese
(G / filt).plot(blk=data, rate=rate, samples=1024, unwrap=False).show()
Envoltória espectral
LPC - Predição Linear
Formantes
Pode ser
utilizado para
classificação
de vogais
34.
Parte 6
NúcleoNúcleo
(Não, não vai explodir...)(Não, não vai explodir...)
35.
AbstractOperatorOverloaderMeta
● Metaclasse
– Classe cujas instâncias são classes
● Abstrata
– Classe com recursos especificados porém sem
implementação
● Sobrecarga massiva de operadores:
– Binários
– Binários reversos
– Unários
● Utiliza-se da classe OpMethod
– Organiza todos os 33 possíveis dunders de operadores
Há, entretanto, 35 no Python 2.
AbstractOperatorOverloaderMeta
insere __div__ e __rdiv__
automaticamente a partir de
__truediv__ e __rtruediv__
(quando aplicável)
36.
Objeto window
Um dicionário de estratégias
In [1]: from audiolazy import window
In [2]: window # Vejamos as estratégias disponíveis
Out[2]:
{('bartlett',): <function audiolazy.lazy_analysis.bartlett>,
('blackman',): <function audiolazy.lazy_analysis.blackman>,
('hamming',): <function audiolazy.lazy_analysis.hamming>,
('hann', 'hanning'): <function audiolazy.lazy_analysis.hann>,
('rectangular', 'rect'): <function audiolazy.lazy_analysis.rectangular>,
('triangular', 'triangle'): <function audiolazy.lazy_analysis.triangular>}
In [3]: window["rect"](3) # Obtém a estratégia, chamando com 1 argumento
Out[3]: [1.0, 1.0, 1.0]
In [4]: window.triangle(3) # Idem, mas feito com outra sintaxe (dicionário)
Out[4]: [0.5, 1.0, 0.5]
In [5]: hm_wnd = window.hamming # Referenciando fora do dicionário
In [6]: hm_wnd # Esta estratégia é uma função comum
Out[6]: <function audiolazy.lazy_analysis.hamming>
In [1]: from audiolazy import window
In [2]: window # Vejamos as estratégias disponíveis
Out[2]:
{('bartlett',): <function audiolazy.lazy_analysis.bartlett>,
('blackman',): <function audiolazy.lazy_analysis.blackman>,
('hamming',): <function audiolazy.lazy_analysis.hamming>,
('hann', 'hanning'): <function audiolazy.lazy_analysis.hann>,
('rectangular', 'rect'): <function audiolazy.lazy_analysis.rectangular>,
('triangular', 'triangle'): <function audiolazy.lazy_analysis.triangular>}
In [3]: window["rect"](3) # Obtém a estratégia, chamando com 1 argumento
Out[3]: [1.0, 1.0, 1.0]
In [4]: window.triangle(3) # Idem, mas feito com outra sintaxe (dicionário)
Out[4]: [0.5, 1.0, 0.5]
In [5]: hm_wnd = window.hamming # Referenciando fora do dicionário
In [6]: hm_wnd # Esta estratégia é uma função comum
Out[6]: <function audiolazy.lazy_analysis.hamming>
Também é um iterável por
suas estratégias
(ver windows_plot.py)
37.
Documentação
● Docstrings: documentação no código
– Uso em ambientes interativos
– reStructuredText
– Organização em seções
● Visualização no Spyder (Rich Text), IPython
● Sphinx
– Conversão automática do sistema de seções para o formato do
Sphinx
– Muitos formatos: LaTeX (PDF, DVI, PS), ePUB, HTML, TexInfo, etc.
● Apresentação, instruções de instalação e exemplos básicos
– Integração com MatPlotLib, Music21, wxPython, Tkinter, etc.
http://pythonhosted.org/audiolazy
https://github.com/danilobellini/audiolazy/tree/master/audiolazy/examples
39.
AudioLazy
● DSP (Digital Signal Processing) para áudio
– Análise
● MIR (Music Information Retrieval)
– Síntese
– Processamento
● Expressividade de código
– Facilita prototipação, simulação
● Tempo real (latência de 35ms é possível)
– Possibilita uso em aplicações finais
● 100% Python
– Multiplataforma
Suporta Python 2 e 3 com o
mesmo código!
40.
Motivações e justificativas
No papel...
● Demanda e insatisfação com código existente
– Por mim
● Vetores (NumPy, Octave/MatLab)...tempo real?
● Índices...=(
– Por outros
● Sustainable Software for Audio and Music Research
– ISMIR 2012 (Tutorial)
– DAFx 2012 (Tutorial)
● Software Carpentry
● Ausência de código fonte disponível
– Algoritmo de Klapuri (2008)!!! Bad guy...código?
● Base para trabalhos futuros
41.
Resumidamente:
The Litmus Test
If you have to refer to theIf you have to refer to the
documentation every timedocumentation every time
you use a module, find (oryou use a module, find (or
build) a new module.build) a new module.
Até tentei evitar...mas...
43.
Testes com oráculos
● 80 c/ o scipy.signal.lfilter
● 64 c/ o subpacote de otimização do SciPy
● 2 c/ o NumPy
import pytest
p = pytest.mark.parametrize
from scipy.signal import lfilter
from audiolazy import ZFilter, almost_eq
class TestZFilterScipy(object):
@p("a", [[1.], [3.], [1., 3.], [15., -17.2], [-18., 9.8, 0., 14.3]])
@p("b", [[1.], [-1.], [1., 0., -1.], [1., 3.]])
@p("data", [range(5), range(5, 0, -1), [7, 22, -5], [8., 3., 15.]])
def test_lfilter(self, a, b, data):
filt = ZFilter(b, a) # Cria um filtro com a AudioLazy
expected = lfilter(b, a, data).tolist() # Aplica o filtro com o SciPy
assert almost_eq(filt(data), expected) # Compara os resultados
import pytest
p = pytest.mark.parametrize
from scipy.signal import lfilter
from audiolazy import ZFilter, almost_eq
class TestZFilterScipy(object):
@p("a", [[1.], [3.], [1., 3.], [15., -17.2], [-18., 9.8, 0., 14.3]])
@p("b", [[1.], [-1.], [1., 0., -1.], [1., 3.]])
@p("data", [range(5), range(5, 0, -1), [7, 22, -5], [8., 3., 15.]])
def test_lfilter(self, a, b, data):
filt = ZFilter(b, a) # Cria um filtro com a AudioLazy
expected = lfilter(b, a, data).tolist() # Aplica o filtro com o SciPy
assert almost_eq(filt(data), expected) # Compara os resultados
44.
Conclusões
● Tempo real em Python
● Expressividade + avaliação tardia
– Modularidade
● Multiparadigma
– Funcional
– Reflexivo
– Objetos
● Filtros digitais a partir de filtros analógicos
● Orientação a testes
● Padrão IEEE 754
45.
Últimas novidades!
● Python 3!
● Contas com polinômios variantes no tempo
● Métodos das classes Stream e StreamTeeHub
– Peek
– Skip
– Limit
● Polinômios de Lagrange (interpolação)
● Reamostragem (taxa de amostragem variante no
tempo)
– Isso é útil? (variante no tempo)
46.
Possíveis continuações para o
desenvolvimento da AudioLazy
● Análise
– FFT
– Heurísticas para transcrição
– Outras transformadas
● Modelagem audição
– Outros modelos (Lyon, Seneff,
gamma chirp, etc.)
– Conversão entre x-dB e ERB
● Síntese e processamento
– Wah, phaser, flanger, chorus, eco,
compressor, noise gate, limiter, …
● Testes
– 100%
– Mock MatPlotLib
●
Filtros
– Atrasos/expoentes variantes no
tempo
– Interpolação por splines
– Frações parciais
– Otimização
– Escrita no tempo
– SymPy
– Treliça
●
Outros
– Integrar com PureData
– I/O MIDI
– Plugins (e.g. Vamp)
– Tutorial
– Logo
47.
Obrigado!
Perguntas?Perguntas?
Fork me on GitHubFork me on GitHub
https://github.com/danilobellini/audiolazyhttps://github.com/danilobellini/audiolazy