Aggiunta dell'operatore di moltiplicazione fra i filtri (che funge

Leonardo Robol [2010-03-02 18:55]
Aggiunta dell'operatore di moltiplicazione fra i filtri (che funge
da composizione) e modifiche per usare la nuova classe FilterBank.
Filename
Filtering/Filtering.py
Filtering/Splitting.py
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
ViewGit