diff --git a/Filtering/Filtering.py b/Filtering/Filtering.py index b046372..bf939be 100644 --- a/Filtering/Filtering.py +++ b/Filtering/Filtering.py @@ -19,24 +19,24 @@ class AbstractFilter(): class FIR(AbstractFilter): - def __init__(self, coefficients, inverse = False): + def __init__(self, coefficients): self.coefficients = coefficients - self.inverse = inverse def __call__(self, samples): """Apply the FIR to samples""" - if not self.inverse: - return convolve (self.coefficients, - samples, 'same') - else: - s = samples - # Questa è un po' una grezzata e trascuriamo i bordi, - # ma per ora voglio vedere se funziona. - for i in xrange(0,len(s) - len(self.coefficients)): - s[i] = dot(self.coefficients, - samples[i:i+len(self.coefficients)]) - return s + return convolve (self.coefficients, + samples, 'same') + + + def GetResponseFunction(self): + """ + Obtain the vector of coefficients. + """ + return self.coefficients + + def __mul__(self, other): + return FIR(convolve(self.coefficients, other.GetResponseFunction())) @@ -130,6 +130,13 @@ class FilterBank(): """ self.highPassInverseFilter = highpass + def SetLength(self, length): + """ + Set the length of the filter, i.e how much + will be the delay when recovering + """ + self.length = length + def Split(self, samples): """ Split the samples using the filter provided @@ -170,7 +177,7 @@ class FilterBank(): for high in sampleArray[::-1]: low = self.lowPassInverseFilter (UpSample (low)) low += self.highPassInverseFilter (UpSample (high)) - low = roll(low, -1) + low = roll(low, -1 * self.length) return low diff --git a/Filtering/Splitting.py b/Filtering/Splitting.py index 14488b5..4d10bf5 100644 --- a/Filtering/Splitting.py +++ b/Filtering/Splitting.py @@ -9,54 +9,26 @@ class SplittingExample(): def __init__(self): - # Numero di ricorsioni della filter bank - self.depth = 4 - - # 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. - # 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([1, 1]) - f1 = array([1, -1]) + 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([1, 1]) + # f1 = array([1, -1]) + + filterBank = Filtering.FilterBank () + filterBank.SetFilterMatrix ([h0,h1,f0,f1]) + filterBank.SetDepth (4) - self.lowpass = Filtering.FIR (h0) - self.highpass = Filtering.FIR (h1) - - self.f0 = Filtering.FIR (f0) - self.f1 = Filtering.FIR (f1) - - self.samples = self.LoadSamples ("sunny.pcm") - print self.samples - self.TruncateSamples () - self.Split () + samples = self.LoadSamples ("sunny.pcm") + wavelets = filterBank.Split (samples) + rebuilt = filterBank.Rebuild (wavelets) + self.WriteSamples(rebuilt, "rebuilt.pcm") - self.Rebuild () - self.WriteSamples(self.samples , "rebuilt.pcm") - print self.LoadSamples("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 :) - """ - to_remove = len(self.samples) % (pow(2,self.depth)) - # Se non c'è niente da rimuovere l'istruzione che segue - # portebbe produrre casini. - if to_remove is 0: - return - self.samples = self.samples[:-1*to_remove] - def LoadSamples(self, filename = "sunny.pcm"): """ Load the samples from an audio file @@ -75,66 +47,6 @@ class SplittingExample(): data[:] = samples[:] data.flush () - def Split(self, suffix = "d"): - """ - Split the signal in two signals filtered with the - lowpass and the highpass filter""" - - # Primo giro di filtri - 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) - - print self.low_d - print self.high_d - - self.WriteSamples(self.high_d, "high_" + suffix + ".pcm") - - # Applichiamo ricorsivamente il filtro alle basse frequenze, - # per suddividerle ancora meglio fra details and average. - self.samples = self.low_d - - # Per il momento usiamo suffix per controllare il punto della - # ricorsione a quale ci troviamo. - 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" - low = self.LoadSamples("low_" + suffix + ".pcm") - low = Filtering.UpSample(low) - else: - low = Filtering.UpSample(self.samples) - - high = self.LoadSamples("high_" + suffix + ".pcm") - high = Filtering.UpSample(high) - - print " => Upsampled" - - # print " => Rebuild called with suffix = %s" % suffix - # print " shape = (%d, %d)" % (len(low), len(high)) - self.samples = roll(self.f0(low) + self.f1(high), -1) - print self.samples - - if (len(suffix) > 1): - self.WriteSamples(self.samples, "prova.pcm") - self.Rebuild (suffix[:-1]) - - def Show(self): """ Shows the result of filtering