diff --git a/Filtering/Filtering.py b/Filtering/Filtering.py index 5f336f3..833fc2b 100644 --- a/Filtering/Filtering.py +++ b/Filtering/Filtering.py @@ -2,14 +2,14 @@ # -*- coding: utf-8 -*- # -from numpy import array, convolve, zeros +from numpy import array, zeros, convolve class AbstractFilter(): def __init__(self): pass - def Apply (self, samples): + def __call__ (self, samples): """ Apply the filter to samples. This method has to be overloaded from the specific filter class @@ -23,7 +23,7 @@ class FIR(AbstractFilter): self.coefficients = coefficients - def Apply(self, samples): + def __call__(self, samples): """Apply the FIR to samples""" return convolve (self.coefficients, samples, 'same') diff --git a/Filtering/Splitting.py b/Filtering/Splitting.py index 0875844..2d0e98e 100644 --- a/Filtering/Splitting.py +++ b/Filtering/Splitting.py @@ -9,26 +9,51 @@ class SplittingExample(): def __init__(self): + # Numero di ricorsioni della filter bank + self.depth = 2 + # Creo i filtri che userò in maniera arguta # in seguito. Questo filtro è ortogonale, nel # senso che posso ottenere la filter bank inversa # invertendo semplicemente la matrice. - low = 0.125 * array([1+sqrt(3), 3+sqrt(3), 3-sqrt(3), 1-sqrt(3)]) - high = 0.125 * array([1-sqrt(3), -3+sqrt(3), 3+sqrt(3),-1-sqrt(3)]) + # h0 = 0.125 * array([1+sqrt(3), 3+sqrt(3), 3-sqrt(3), 1-sqrt(3)]) + #h1 = 0.125 * array([1-sqrt(3), -3+sqrt(3), 3+sqrt(3),-1-sqrt(3)]) + + #f0 = 0.25 * array([1-sqrt(3), 3-sqrt(3), 3+sqrt(3), 1+sqrt(3)]) + #f1 = 0.25 * array([-1-sqrt(3),3+sqrt(3),-3-sqrt(3), 1-sqrt(3)]) + h0 = array([0.5 , 0.5]) + h1 = array([-0.5, 0.5]) + + f0 = array([0.5, 0.5]) + f1 = array([-0.5, 0.5]) - self.lowpass = Filtering.FIR (low) - self.highpass = Filtering.FIR (high) + self.lowpass = Filtering.FIR (h0) + self.highpass = Filtering.FIR (h1) + + self.f0 = Filtering.FIR (f0) + self.f1 = Filtering.FIR (f1) self.LoadSamples () + self.TruncateSamples () self.Split () + self.Rebuild () + self.WriteSamples(self.samples , "rebuilt.pcm") + # self.Show () + + def TruncateSamples(self): + """ + Check that samples loaded have a length that is a multiple + of 2^self.depth so that I can apply recursive filtering + without any problem. If not, just truncate :) + """ + self.samples = self.samples[:-1*(len(self.samples) % (pow(2,self.depth)))] - def LoadSamples(self): + def LoadSamples(self, filename = "sunny.pcm"): """ Load the samples from an audio file """ - filename = "sunny.pcm" samples = memmap (filename, dtype="<h", mode="r") @@ -48,8 +73,8 @@ class SplittingExample(): lowpass and the highpass filter""" # Primo giro di filtri - self.low = self.lowpass.Apply (self.samples) - self.high = self.highpass.Apply (self.samples) + self.low = self.lowpass (self.samples) + self.high = self.highpass (self.samples) self.low_d = Filtering.DownSample(self.low) self.high_d = Filtering.DownSample(self.high) @@ -64,12 +89,36 @@ class SplittingExample(): # Per il momento usiamo suffix per controllare il punto della # ricorsione a quale ci troviamo. - if len(suffix) < 4: + if len(suffix) < self.depth: self.Split(suffix + "d") else: # Memorizziamo i low ed usciamo self.WriteSamples(self.low_d, "low_" + suffix + ".pcm" ) + def Rebuild(self, suffix = None): + """ + Ricostruisce il segnale originale partendo dalla wavelet downsamplate. + (scusate il neologismo). Ovviamente non ha praticamente nessun senso, + a parte far vedere che si può fare + """ + # Se è il primo giro leggo low da file, altrimenti + # me li dovrei trovare in samples. + + if(suffix == None): + suffix = self.depth * "d" + self.LoadSamples("low_" + suffix + ".pcm") + + print " => Rebuild called with suffix = %s" % suffix + + low = Filtering.UpSample(self.samples) + + self.LoadSamples("high_" + suffix + ".pcm") + high = Filtering.UpSample(self.samples) + + self.samples = self.f0(low) + self.f1(high) + if (len(suffix) > 1): + self.Rebuild (suffix[:-1]) + def Show(self): """