changeset 37:2cc444441f42 branch-tests

refactor pitchbihist and introduce default melody_sr
author Maria Panteli
date Thu, 14 Sep 2017 14:50:00 +0100
parents 3b67cd634b9a
children e5e8e8a96948
files scripts/PitchBihist.py tests/test_PitchBihist.py
diffstat 2 files changed, 28 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/PitchBihist.py	Thu Sep 14 14:16:29 2017 +0100
+++ b/scripts/PitchBihist.py	Thu Sep 14 14:50:00 2017 +0100
@@ -13,13 +13,9 @@
 
 class PitchBihist:
     def __init__(self, win2sec=8):
-        self.y = None
-        self.sr = None
-        self.chroma = None
-        self.chromasr = None
-        self.melodiasr = 44100. / 128.
-        self.bihist = None
         self.win2sec = win2sec
+        self.hop2sec = 0.5
+        self.melody_sr = 44100. / 128.
 
 
     def hz_to_cents(self, freq_Hz, ref_Hz=32.703, n_cents=1200):
@@ -42,13 +38,13 @@
             return []
         data = np.loadtxt(melodia_file, delimiter=',')
         times, freqs = (data[:, 0], data[:, 1])
-        self.chromasr = 1. / (times[1] - times[0])
+        #melody_sr = 1. / (times[1] - times[0])
         if stop_sec is not None:
             stop_idx = np.where(times < stop_sec)[0]
             times, freqs = times[stop_idx], freqs[stop_idx]
         freqs[freqs<=0] = np.nan
         melody = freqs
-        return melody
+        return melody#, melody_sr
 
 
     def get_melody_matrix(self, melody):
@@ -64,15 +60,16 @@
 
 
     def bihist_from_melodia(self, filename='sample_melodia.csv', secondframedecomp=True, stop_sec=None):
+        #melody, melody_sr = self.get_melody_from_file(filename, stop_sec=stop_sec)
         melody = self.get_melody_from_file(filename, stop_sec=stop_sec)
         if len(melody) == 0:
-            self.bihist = []
-            return self.bihist
+            return []
         melody_matrix = self.get_melody_matrix(melody)
+        bihist = []
         if secondframedecomp:
             nbins, norigframes = melody_matrix.shape
-            win2 = int(round(self.win2sec*self.chromasr))
-            hop2 = int(round(0.5*self.chromasr))
+            win2 = int(round(self.win2sec * self.melody_sr))
+            hop2 = int(round(self.hop2sec * self.melody_sr))
             if norigframes<=win2:
                 nframes = 1
                 win2 = norigframes
@@ -84,16 +81,19 @@
                 bihist = self.bihistogram(frame)
                 bihist = np.reshape(bihist, -1)
                 bihistframes[:, i] = bihist
-            self.bihist = bihistframes
+            bihist = bihistframes
         else:
-            self.bihist = self.bihistogram(melody_matrix)
-        return self.bihist
+            bihist = self.bihistogram(melody_matrix)
+        return bihist
 
 
-    def bihistogram(self, spec, winsec=0.5, align=True):
-        win = int(round(winsec*self.chromasr))
+    def bihistogram(self, spec, spec_sr=None, winsec=0.5, align=True):
+        if spec_sr is None:
+            # assume spec is melody_matrix with default sr
+            spec_sr = self.melody_sr
+        win = int(round(winsec * spec_sr))
         ker = np.concatenate([np.zeros((win, 1)), np.ones((win+1, 1))], axis=0)
-        spec = spec.T  # transpose to have franes as rows in convolution
+        spec = spec.T  # transpose to have frames as rows in convolution
 
         # energy threshold
         thr = 0.3*np.max(spec)
@@ -120,54 +120,6 @@
         return B
 
 
-    def bihist_from_chroma(self, filename='test.wav', secondframedecomp=True):
-        self.chroma, self.chromasr = s.get_smoothie_for_bihist(filename=filename, hopinsec=0.005)
-        if secondframedecomp:
-            win2 = int(round(8*self.chromasr))
-            hop2 = int(round(0.5*self.chromasr))
-            nbins, norigframes = self.chroma.shape
-            if norigframes<win2:
-                nframes = 1
-            else:
-                nframes = int(1+np.floor((norigframes-win2)/float(hop2)))
-            bihistframes = np.empty((nbins*nbins, nframes))
-            for i in range(nframes):  # loop over all 8-sec frames
-                frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
-                bihist = self.bihistogram(frame)
-                bihist = np.reshape(bihist, -1)
-                bihistframes[:, i] = bihist
-            self.bihist = bihistframes
-        else:
-            self.bihist = np.reshape(self.bihistogram(), -1)
-
-
-    def bihist_from_precomp_chroma(self, align=False):
-        win2 = int(round(self.win2sec*self.chromasr))
-        hop2 = int(round(0.5*self.chromasr))
-        nbins, norigframes = self.chroma.shape
-        if norigframes<win2:
-            nframes = 1
-        else:
-            nframes = int(1+np.floor((norigframes-win2)/float(hop2)))
-        bihistframes = np.empty((nbins*nbins, nframes))
-        for i in range(nframes):  # loop over all 8-sec frames
-            frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
-            bihist = self.bihistogram(frame, align=align)
-            bihist = np.reshape(bihist, -1)
-            bihistframes[:, i] = bihist
-        self.bihist = bihistframes
-
-    def get_pitchbihist(self, filename='test.wav'):
-        self.bihist_from_chroma(filename=filename)
-        return self.bihist
-        
-    def get_pitchbihist_from_chroma(self, chroma=[], chromasr=[]):
-        self.chroma = chroma
-        self.chromasr = chromasr
-        self.bihist_from_precomp_chroma(align=False)
-        return self.bihist
-
-
 if __name__ == '__main__':
     pb = PitchBihist()
-    pb.get_pitchbihist()
+    pb.bihist_from_melodia(filename='vamp_melodia.csv')
--- a/tests/test_PitchBihist.py	Thu Sep 14 14:16:29 2017 +0100
+++ b/tests/test_PitchBihist.py	Thu Sep 14 14:50:00 2017 +0100
@@ -32,7 +32,7 @@
 def test_get_melody_from_file():
     melodia_file = 'data/sample_dataset/Melodia/mel_1_2_1.csv'
     melody = pbi.get_melody_from_file(melodia_file)
-    assert len(melody) < 12. * pbi.chromasr
+    assert len(melody) < 12. * pbi.melody_sr
 
 
 def test_get_melody_matrix():
@@ -72,4 +72,11 @@
     assert bihist[45, 0] > 0 and (np.sum(bihist) - bihist[45, 0]) == 0
 
 
-
+def test_bihistogram_align():
+    melody = np.concatenate([660 * np.ones(250), 440 * np.ones(500)])
+    melody_matrix = pbi.get_melody_matrix(melody)
+    # bin of max magnitude = A = 45/60
+    bihist = pbi.bihistogram(melody_matrix, align=True)
+    # bihist[20, 45] == 0
+    # we shift up 45 so rows 20-45 and left 45 so cols 45-45
+    assert bihist[20-45, 0] == 1