]> git.parisson.com Git - timeside.git/commitdiff
cleanup, add a SpectrogramLinear grapher
authorGuillaume Pellerin <yomguy@parisson.com>
Mon, 28 Oct 2013 22:33:23 +0000 (23:33 +0100)
committerGuillaume Pellerin <yomguy@parisson.com>
Mon, 28 Oct 2013 22:33:23 +0000 (23:33 +0100)
12 files changed:
timeside/analyzer/aubio_melenergy.py
timeside/analyzer/aubio_mfcc.py
timeside/analyzer/aubio_pitch.py
timeside/analyzer/aubio_specdesc.py
timeside/analyzer/aubio_temporal.py
timeside/analyzer/dc.py
timeside/analyzer/spectrogram.py
timeside/analyzer/waveform.py
timeside/grapher/__init__.py
timeside/grapher/spectrogram.py
timeside/grapher/spectrogram_linear.py [new file with mode: 0644]
timeside/grapher/utils.py

index d1ac0260cd3134bc03883f2e4bd76cfad68e0b6b..b353079eacd0c45eac728ffcddc155cc88f5c2b1 100644 (file)
@@ -73,13 +73,8 @@ class AubioMelEnergy(Analyzer):
         return frames, eod
 
     def post_process(self):
-
         melenergy = self.new_result(data_mode='value', time_mode='framewise')
-
-        # Metadata
         melenergy.parameters = dict(n_filters=self.n_filters,
                                     n_coeffs=self.n_coeffs)
-        # Set Data
         melenergy.data_object.value = self.melenergy_results
-
         self._results.add(melenergy)
index c29c20c824167b95fcaa76c246711072fa0405d5..3697b8173c2ef3a1f85b1980f5f6397e12810458 100644 (file)
@@ -74,11 +74,8 @@ class AubioMfcc(Analyzer):
         return frames, eod
 
     def post_process(self):
-        # MFCC
         mfcc = self.new_result(data_mode='value', time_mode='framewise')
-
         mfcc.parameters = dict(n_filters=self.n_filters,
                                n_coeffs=self.n_coeffs)
-
         mfcc.data_object.value = self.mfcc_results
         self._results.add(mfcc)
index 76bdb28bd211bbd440e167205d93aecb655b2b1c..899d64de23fc6a2a960d3fafd56625a65e853cfb 100644 (file)
@@ -72,13 +72,10 @@ class AubioPitch(Analyzer):
         return frames, eod
 
     def post_process(self):
-        # set Result
         pitch = self.new_result(data_mode='value', time_mode='framewise')
 
         # parameters : None # TODO check with Piem "default" and "freq" in
         # setup
 
-        # Set Data
         pitch.data_object.value = self.pitches
-
         self._results.add(pitch)
index 175cf08696b0be5342c0d084206aae8b88ef7be7..b23d58b4ad869e9f77bd9c66713498a04698865b 100644 (file)
@@ -88,7 +88,6 @@ class AubioSpecdesc(Analyzer):
             # Set metadata
             res_specdesc.id_metadata.id += '.' + method
             res_specdesc.id_metadata.name = ' ' + method
-
             res_specdesc.data_object.value = self.specdesc_results[method]
 
             self._results.add(res_specdesc)
index 8c9d03a09d715629a246dbb1f0cc7db98e10f2db..e6c0a9c2c20b4769e7d256ee41e1705a5010b59a 100644 (file)
@@ -94,7 +94,6 @@ class AubioTemporal(Analyzer):
 
         onsets.data_object.label = numpy.ones(len(self.onsets))
         onsets.data_object.time = self.onsets
-
         onsets.label_metadata.label = {1: 'Onset'}
 
         self._results.add(onsets)
index 88b5911b36bbef31d4c4eaee755e090656253880..8ce3290f574fa16d3affe2f1c0905442dc516cd6 100644 (file)
@@ -59,8 +59,6 @@ class MeanDCShift(Analyzer):
 
     def post_process(self):
         dc_result = self.new_result(data_mode='value', time_mode='global')
-
-        # Set Data
         dc_result.data_object.value = numpy.round(
             numpy.mean(100 * self.values), 3)
         self._results.add(dc_result)
index 17b6d78db2ad21878b79a1043b763d601ce549fb..0597e311407da5a3d3e06af331dccbbb8d8279aa 100644 (file)
@@ -61,17 +61,10 @@ class Spectrogram(Analyzer):
         for samples in downsample_blocking(frames, self.input_stepsize):
             #time = self.block_read * self.input_stepsize * 1. / self.samplerate()
             self.values.append(np.abs(np.fft.rfft(samples, self.FFT_SIZE)))
-
         return frames, eod
 
     def post_process(self):
-        # set Result
         spectrogram = self.new_result(data_mode='value', time_mode='framewise')
-
-        # parameters :
         spectrogram.parameters = {'FFT_SIZE': self.FFT_SIZE}
-
-        # Set Data
         spectrogram.data_object.value = self.values
-
         self._results.add(spectrogram)
index 8d5b0c9accad8a47fab0e820a99ec11b57a83646..ace57c801fae7f644b0fb9c61d76879aac6b0197 100644 (file)
@@ -60,14 +60,9 @@ class Waveform(Analyzer):
     def process(self, frames, eod=False):
         for samples in downsample_blocking(frames, self.input_blocksize):
             self.values.append(samples)
-
         return frames, eod
 
     def post_process(self):
-        # set Result
         waveform = self.new_result(data_mode='value', time_mode='framewise')
-
-        # Set Data
         waveform.data_object.value = np.asarray(self.values).flatten()
-
         self._results.add(waveform)
index 1c21ffc5024a08c8fddff1d9236ad426257d7e76..d49a41e35d919212e989d9135962c08595a5e847 100644 (file)
@@ -6,3 +6,4 @@ from waveform_transparent import *
 from waveform_contour_black import *
 from waveform_contour_white import *
 from spectrogram import *
+from spectrogram_linear import *
index ade5f65ec316c7ccf54e67bf8541bc2087b5c599..7d7f6910a60b637c17fad1ba2cd3d1fbe46ca932 100644 (file)
@@ -35,19 +35,7 @@ class Spectrogram(Grapher):
         super(Spectrogram, self).__init__(width, height, bg_color, color_scheme)
         self.colors = default_color_schemes[color_scheme]['spectrogram']
         self.pixels = []
-
-        # generate the lookup which translates y-coordinate to fft-bin
         self.y_to_bin = []
-        f_min = float(self.lower_freq)
-        f_max = float(self.higher_freq)
-        y_min = math.log10(f_min)
-        y_max = math.log10(f_max)
-        for y in range(self.image_height):
-            freq = math.pow(10.0, y_min + y / (self.image_height - 1.0) *(y_max - y_min))
-            fft_bin = freq / 22050.0 * (self.fft_size/2 + 1)
-            if fft_bin < self.fft_size/2:
-                alpha = fft_bin - int(fft_bin)
-                self.y_to_bin.append((int(fft_bin), alpha * 255))
 
     @staticmethod
     @interfacedoc
@@ -64,6 +52,21 @@ class Spectrogram(Grapher):
         super(Spectrogram, self).setup(channels, samplerate, blocksize, totalframes)
         self.image = Image.new("P", (self.image_height, self.image_width))
         self.image.putpalette(interpolate_colors(self.colors, True))
+        self.set_scale()
+
+    def set_scale(self):
+        """generate the lookup which translates y-coordinate to fft-bin"""
+
+        f_min = float(self.lower_freq)
+        f_max = float(self.higher_freq)
+        y_min = math.log10(f_min)
+        y_max = math.log10(f_max)
+        for y in range(self.image_height):
+            freq = math.pow(10.0, y_min + y / (self.image_height - 1.0) *(y_max - y_min))
+            fft_bin = freq / f_max * (self.fft_size/2 + 1)
+            if fft_bin < self.fft_size/2:
+                alpha = fft_bin - int(fft_bin)
+                self.y_to_bin.append((int(fft_bin), alpha * 255))
 
     def draw_spectrum(self, x, spectrum):
         for (index, alpha) in self.y_to_bin:
diff --git a/timeside/grapher/spectrogram_linear.py b/timeside/grapher/spectrogram_linear.py
new file mode 100644 (file)
index 0000000..3ccdbc2
--- /dev/null
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2010 Guillaume Pellerin <yomguy@parisson.com>
+# Copyright (c) 2010 Olivier Guilyardi <olivier@samalyse.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+
+
+from timeside.core import implements, interfacedoc
+from timeside.api import IGrapher
+from timeside.grapher.core import *
+from timeside.grapher.spectrogram import Spectrogram
+
+
+class SpectrogramLinear(Spectrogram):
+    """ Builds a PIL image representing a spectrogram of the audio stream (level vs. frequency vs. time).
+    Adds pixels iteratively thanks to the adapter providing fixed size frame buffers."""
+
+    implements(IGrapher)
+
+    @interfacedoc
+    def __init__(self, width=1024, height=256, bg_color=(0,0,0), color_scheme='default'):
+        super(SpectrogramLinear, self).__init__(width, height, bg_color, color_scheme)
+
+    @staticmethod
+    @interfacedoc
+    def id():
+        return "spectrogram_linear"
+
+    @staticmethod
+    @interfacedoc
+    def name():
+        return "Spectrogram linear"
+
+    @interfacedoc
+    def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None):
+        super(SpectrogramLinear, self).setup(channels, samplerate, blocksize, totalframes)
+
+    def set_scale(self):
+        """generate the lookup which translates y-coordinate to fft-bin"""
+
+        f_min = float(self.lower_freq)
+        f_max = float(self.higher_freq)
+        y_min = f_min
+        y_max = f_max
+        for y in range(self.image_height):
+            freq = y_min + y / (self.image_height - 1.0) *(y_max - y_min)
+            fft_bin = freq / f_max * (self.fft_size/2 + 1)
+            if fft_bin < self.fft_size/2:
+                alpha = fft_bin - int(fft_bin)
+                self.y_to_bin.append((int(fft_bin), alpha * 255))
index 178e76ddee09e7f505229c831f8f7e692ace3572..b262650eeb8056cf2f591e67c19b0b86975c98fd 100644 (file)
@@ -104,7 +104,6 @@ def smooth(x, window_len=10, window='hanning'):
     numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
     scipy.signal.lfilter
 
-
     Examples
     --------
 
@@ -125,20 +124,16 @@ def smooth(x, window_len=10, window='hanning'):
 
     # TODO: the window parameter could be the window itself if an array instead of a string
 
-
     if x.ndim != 1:
         raise ValueError, "smooth only accepts 1 dimension arrays."
-
     if x.size < window_len:
         raise ValueError, "Input vector needs to be bigger than window size."
-
     if window_len < 3:
         return x
-
     if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']:
         raise ValueError, "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"
 
-    s=numpy.r_[2*x[0]-x[window_len:1:-1], x, 2*x[-1]-x[-1:-window_len:-1]]
+    s = numpy.r_[2*x[0]-x[window_len:1:-1], x, 2*x[-1]-x[-1:-window_len:-1]]
 
     if window == 'flat': #moving average
         w = numpy.ones(window_len,'d')
@@ -163,9 +158,7 @@ def reduce_opacity(im, opacity):
 
 
 def im_watermark(im, inputtext, font=None, color=None, opacity=.6, margin=(30,30)):
-    """
-    imprints a PIL image with the indicated text in lower-right corner
-    """
+    """imprints a PIL image with the indicated text in lower-right corner"""
     if im.mode != "RGBA":
         im = im.convert("RGBA")
     textlayer = Image.new("RGBA", im.size, (0,0,0,0))
@@ -206,5 +199,3 @@ def mean(samples):
 def normalize(contour):
     contour = contour-min(contour)
     return contour/max(contour)
-
-