From 7f11fa19dc669e8de79aef55292c94bd2b9c8481 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Mon, 15 Apr 2013 15:25:52 -0500 Subject: [PATCH] timeside/analyzer/aubio_specdesc.py: add spectral descriptors --- tests/test_aubio_specdesc.py | 29 +++++++++ timeside/analyzer/aubio_specdesc.py | 91 +++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100755 tests/test_aubio_specdesc.py create mode 100644 timeside/analyzer/aubio_specdesc.py diff --git a/tests/test_aubio_specdesc.py b/tests/test_aubio_specdesc.py new file mode 100755 index 0000000..4170a5c --- /dev/null +++ b/tests/test_aubio_specdesc.py @@ -0,0 +1,29 @@ +#! /usr/bin/env python + +from unit_timeside import * +from timeside.decoder import * +from timeside.analyzer.aubio_specdesc import AubioSpecdesc + +class TestAubioSpecdesc(TestCase): + + def setUp(self): + self.analyzer = AubioSpecdesc() + + def testOnSweep(self): + "runs on sweep" + self.source = os.path.join (os.path.dirname(__file__), "samples", "sweep.wav") + + def testOnGuitar(self): + "runs on guitar" + self.source = os.path.join (os.path.dirname(__file__), "samples", "guitar.wav") + + def tearDown(self): + decoder = FileDecoder(self.source) + (decoder | self.analyzer).run() + results = self.analyzer.results() + #results.to_yaml() + #results.to_json() + #results.to_xml() + +if __name__ == '__main__': + unittest.main(testRunner=TestRunner()) diff --git a/timeside/analyzer/aubio_specdesc.py b/timeside/analyzer/aubio_specdesc.py new file mode 100644 index 0000000..b9a1c10 --- /dev/null +++ b/timeside/analyzer/aubio_specdesc.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2013 Paul Brossier + +# 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 . + +# Author: Paul Brossier + +from timeside.core import Processor, implements, interfacedoc, FixedSizeInputAdapter +from timeside.analyzer.core import * +from timeside.api import IValueAnalyzer + +import numpy +from aubio import specdesc, pvoc + +class AubioSpecdesc(Processor): + implements(IValueAnalyzer) + + @interfacedoc + def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): + super(AubioSpecdesc, self).setup(channels, samplerate, blocksize, totalframes) + self.block_read = 0 + self.win_s = 1024 + self.hop_s = self.win_s / 4 + self.pvoc = pvoc(self.win_s, self.hop_s) + self.methods = ['default', 'energy', 'hfc', 'complex', 'phase', 'specdiff', 'kl', + 'mkl', 'specflux', 'centroid', 'slope', 'rolloff', 'spread', 'skewness', + 'kurtosis', 'decrease'] + self.specdesc = {} + self.specdesc_results = {} + for method in self.methods: + self.specdesc[method] = specdesc(method, self.win_s) + self.specdesc_results[method] = [] + + @staticmethod + @interfacedoc + def id(): + return "aubio_specdesc_analyzer" + + @staticmethod + @interfacedoc + def name(): + return "Mel Energy analysis (aubio)" + + def process(self, frames, eod=False): + for samples in downsample_blocking(frames, self.hop_s): + fftgrain = self.pvoc(samples) + for method in self.methods: + self.specdesc_results[method] += [self.specdesc[method](fftgrain)[0]] + return frames, eod + + def results(self): + + container = AnalyzerResultContainer() + + for method in self.methods: + id = '_'.join(["aubio_specdesc", method]) + name = ' '.join(["spectral descriptor", method, "(aubio)"]) + unit = "" + + values = numpy.array(self.specdesc_results[method]) + + specdesc = AnalyzerResult(id = id, name = name, unit = unit) + specdesc.value = values + + mean_id = '_'.join([id, 'mean']) + mean_name = ' '.join(["spectral descriptor", method, "mean", "(aubio)"]) + specdesc_mean = AnalyzerResult(id = mean_id, name = mean_name, unit = "") + specdesc_mean.value = numpy.mean(values,axis=0) + + median_id = '_'.join([id, 'median']) + median_name = ' '.join(["spectral descriptor", method, "median", "(aubio)"]) + specdesc_median = AnalyzerResult(id = median_id , name = median_name , unit = "") + specdesc_median.value = numpy.median(values,axis=0) + + container.add_result([specdesc, specdesc_mean, specdesc_median]) + + return AnalyzerResultContainer() -- 2.39.5