From aed81865c323db8932644137dc8bdd757223bed6 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 13 Apr 2013 23:21:26 -0500 Subject: [PATCH] timeside/analyzer/: factorise aubio temporal stuff --- tests/testaubio_onset.py | 26 ----- tests/testaubio_onsetrate.py | 27 ----- ...testaubio_bpm.py => testaubio_temporal.py} | 13 ++- timeside/analyzer/__init__.py | 4 +- timeside/analyzer/aubio_bpm.py | 72 ------------- timeside/analyzer/aubio_onset.py | 70 ------------ timeside/analyzer/aubio_onsetrate.py | 72 ------------- timeside/analyzer/aubio_temporal.py | 100 ++++++++++++++++++ 8 files changed, 110 insertions(+), 274 deletions(-) delete mode 100755 tests/testaubio_onset.py delete mode 100755 tests/testaubio_onsetrate.py rename tests/{testaubio_bpm.py => testaubio_temporal.py} (61%) delete mode 100644 timeside/analyzer/aubio_bpm.py delete mode 100644 timeside/analyzer/aubio_onset.py delete mode 100644 timeside/analyzer/aubio_onsetrate.py create mode 100644 timeside/analyzer/aubio_temporal.py diff --git a/tests/testaubio_onset.py b/tests/testaubio_onset.py deleted file mode 100755 index 0cd9651..0000000 --- a/tests/testaubio_onset.py +++ /dev/null @@ -1,26 +0,0 @@ -#! /usr/bin/env python - -from unit_timeside import * -from timeside.decoder import * -from timeside.analyzer.aubio_onset import AubioOnset - -class TestAubioOnset(TestCase): - - def setUp(self): - self.analyzer = AubioOnset() - - 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() - #print "result:", self.analyzer.result() - -if __name__ == '__main__': - unittest.main(testRunner=TestRunner()) diff --git a/tests/testaubio_onsetrate.py b/tests/testaubio_onsetrate.py deleted file mode 100755 index 56e5530..0000000 --- a/tests/testaubio_onsetrate.py +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/bin/env python - -from unittest import TestCase -from timeside.decoder import * -from timeside.analyzer.aubio_onsetrate import AubioOnsetRate - -class TestAubioOnset(TestCase): - - def setUp(self): - self.analyzer = AubioOnsetRate() - - 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() - #print "result:", self.analyzer.result() - -if __name__ == '__main__': - from unittest import main - main() diff --git a/tests/testaubio_bpm.py b/tests/testaubio_temporal.py similarity index 61% rename from tests/testaubio_bpm.py rename to tests/testaubio_temporal.py index 5887127..ec8a25b 100755 --- a/tests/testaubio_bpm.py +++ b/tests/testaubio_temporal.py @@ -2,12 +2,12 @@ from unit_timeside import * from timeside.decoder import * -from timeside.analyzer.aubio_bpm import AubioBPM +from timeside.analyzer.aubio_temporal import AubioTemporal -class TestAubioBPM(TestCase): +class TestAubioTemporal(TestCase): def setUp(self): - self.analyzer = AubioBPM() + self.analyzer = AubioTemporal() def testOnSweep(self): "runs on sweep" @@ -20,7 +20,12 @@ class TestAubioBPM(TestCase): def tearDown(self): decoder = FileDecoder(self.source) (decoder | self.analyzer).run() - #print 'result:', self.analyzer.result() + for r in self.analyzer.results(): + assert hasattr(r, 'id') + assert hasattr(r, 'name') + assert hasattr(r, 'unit') + assert hasattr(r, 'value') + #print 'result:', r if __name__ == '__main__': unittest.main(testRunner=TestRunner()) diff --git a/timeside/analyzer/__init__.py b/timeside/analyzer/__init__.py index 7ecbc12..99330d0 100644 --- a/timeside/analyzer/__init__.py +++ b/timeside/analyzer/__init__.py @@ -3,7 +3,5 @@ from max_level import * from mean_level import * from dc import * -from aubio_bpm import * -from aubio_onsetrate import * -from aubio_onset import * +from aubio_temporal import * from aubio_pitch import * diff --git a/timeside/analyzer/aubio_bpm.py b/timeside/analyzer/aubio_bpm.py deleted file mode 100644 index 096a053..0000000 --- a/timeside/analyzer/aubio_bpm.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2012 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 -from aubio import tempo - -class AubioBPM(Processor): - implements(IValueAnalyzer) - - @interfacedoc - def setup(self, channels=None, samplerate=None, blocksize=None, - totalframes=None): - super(AubioBPM, self).setup(channels, samplerate, blocksize, totalframes) - self.win_s = 512 - self.hop_s = self.win_s / 2 - self.t = tempo("default", self.win_s, self.hop_s, samplerate) - self.block_read = 0 - self.beats = [] - - @staticmethod - @interfacedoc - def id(): - return "aubio_bpm" - - @staticmethod - @interfacedoc - def name(): - return "bpm (aubio)" - - @staticmethod - @interfacedoc - def unit(): - return "bpm" - - def __str__(self): - return "%s %s" % (str(self.value), unit()) - - def process(self, frames, eod=False): - i = 0 - while i < frames.shape[0]: - downmixed = frames[i:i+self.hop_s, :].sum(axis = -1) - if self.t(downmixed): - self.beats += [self.t.get_last_s()] - i += self.hop_s - self.block_read += 1 - return frames, eod - - def result(self): - if len(self.beats) < 2: return 0 - from numpy import median - periods = [60./(b - a) for a,b in zip(self.beats[:-1],self.beats[1:])] - return median (periods) diff --git a/timeside/analyzer/aubio_onset.py b/timeside/analyzer/aubio_onset.py deleted file mode 100644 index a754322..0000000 --- a/timeside/analyzer/aubio_onset.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- 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 -from aubio import onset - -class AubioOnset(Processor): - implements(IValueAnalyzer) - - @interfacedoc - def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): - super(AubioOnset, self).setup(channels, samplerate, blocksize, totalframes) - self.win_s = 512 - self.hop_s = self.win_s / 2 - self.t = onset("default", self.win_s, self.hop_s, samplerate) - self.block_read = 0 - self.onsets = [] - - @staticmethod - @interfacedoc - def id(): - return "aubio_onset" - - @staticmethod - @interfacedoc - def name(): - return "onsets (aubio)" - - @staticmethod - @interfacedoc - def unit(): - return "seconds" - - def __str__(self): - return "%s %s" % (str(self.value), unit()) - - def process(self, frames, eod=False): - i = 0 - while i < frames.shape[0]: - downmixed = frames[i:i+self.hop_s, :].sum(axis = -1) - isonset = self.t(downmixed) - if isonset: - #print self.t.get_last_s() - self.onsets += [self.t.get_last_s()] - i += self.hop_s - self.block_read += 1 - return frames, eod - - def result(self): - return self.onsets diff --git a/timeside/analyzer/aubio_onsetrate.py b/timeside/analyzer/aubio_onsetrate.py deleted file mode 100644 index 5846ba9..0000000 --- a/timeside/analyzer/aubio_onsetrate.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2012 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 -from aubio import onset - -class AubioOnsetRate(Processor): - implements(IValueAnalyzer) - - @interfacedoc - def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): - super(AubioOnsetRate, self).setup(channels, samplerate, blocksize, totalframes) - self.win_s = 512 - self.hop_s = self.win_s / 2 - self.t = onset("default", self.win_s, self.hop_s, samplerate) - self.block_read = 0 - self.onsets = [] - - @staticmethod - @interfacedoc - def id(): - return "aubio_onsetrate" - - @staticmethod - @interfacedoc - def name(): - return "onset rate (aubio)" - - @staticmethod - @interfacedoc - def unit(): - return "bpm" - - def __str__(self): - return "%s %s" % (str(self.value), unit()) - - def process(self, frames, eod=False): - i = 0 - while i < frames.shape[0]: - downmixed = frames[i:i+self.hop_s, :].sum(axis = -1) - isonset = self.t(downmixed) - if isonset: - self.onsets += [self.t.get_last_s()] - i += self.hop_s - self.block_read += 1 - return frames, eod - - def result(self): - if len(self.onsets) < 2: return 0 - from numpy import mean - periods = [60./(b - a) for a,b in zip(self.onsets[:-1],self.onsets[1:])] - return mean(periods) diff --git a/timeside/analyzer/aubio_temporal.py b/timeside/analyzer/aubio_temporal.py new file mode 100644 index 0000000..5893fdd --- /dev/null +++ b/timeside/analyzer/aubio_temporal.py @@ -0,0 +1,100 @@ +# -*- 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 IAnalyzer +from aubio import onset, tempo + +class AubioTemporal(Processor): + implements(IAnalyzer) + + @interfacedoc + def setup(self, channels=None, samplerate=None, blocksize=None, totalframes=None): + super(AubioTemporal, self).setup(channels, samplerate, blocksize, totalframes) + self.win_s = 1024 + self.hop_s = 256 + self.o = onset("default", self.win_s, self.hop_s, samplerate) + self.t = tempo("default", self.win_s, self.hop_s, samplerate) + self.block_read = 0 + self.onsets = [] + self.beats = [] + + @staticmethod + @interfacedoc + def id(): + return "aubio_onset" + + @staticmethod + @interfacedoc + def name(): + return "onsets (aubio)" + + @staticmethod + @interfacedoc + def unit(): + return "seconds" + + def __str__(self): + return "%s %s" % (str(self.value), unit()) + + def process(self, frames, eod=False): + i = 0 + while i < frames.shape[0]: + downmixed = frames[i:i+self.hop_s, :].sum(axis = -1) + if self.o(downmixed): + self.onsets += [self.o.get_last_s()] + if self.t(downmixed): + self.beats += [self.t.get_last_s()] + i += self.hop_s + self.block_read += 1 + return frames, eod + + def results(self): + from numpy import mean, median + + onsets = AnalyzerResult(id = "aubio_onset", name = "onsets (aubio)", unit = "s") + onsets.value = self.onsets + + onsetrate_mean = AnalyzerResult(id = "aubio_onset_rate_mean", name = "onset rate (aubio)", unit = "bpm") + if len(self.onsets) > 1: + periods = [60./(b - a) for a,b in zip(self.onsets[:-1],self.onsets[1:])] + onsetrate_mean.value = mean (periods) + else: + onserate_mean.value = 0 + + onsetrate_median = AnalyzerResult(id = "aubio_onset_rate_median", name = "onset rate (median) (aubio)", unit = "bpm") + if len(self.onsets): + onsetrate_median.value = mean (periods) + else: + onsetrate_median.value = 0 + + beats = AnalyzerResult(id = "aubio_beat", name = "beats (aubio)", unit = "s") + beats.value = self.beats + + bpm = AnalyzerResult(id = "aubio_bpm", name = "bpm (aubio)", unit = "bpm") + if len(self.beats) > 1: + periods = [60./(b - a) for a,b in zip(self.beats[:-1],self.beats[1:])] + bpm.value = median (periods) + else: + bpm.value = 0 + + return onsets, onsetrate_mean, onsetrate_median, beats, bpm -- 2.39.5