From 1a88d4b16149097602bf201ab1e769176863f99d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Bo=CC=88ck?= <research@minimoog.org>
Date: Sat, 9 Sep 2023 11:33:54 +0200
Subject: [PATCH 1/5] configure CI pipeline with GitHub actions

---
 .github/workflows/ci.yml              | 38 ++++++++++++++++++++
 .github/workflows/codeql-analysis.yml | 51 ++++++++++-----------------
 2 files changed, 56 insertions(+), 33 deletions(-)
 create mode 100644 .github/workflows/ci.yml

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..9e05d13c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,38 @@
+name: Python package
+
+on: [push]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
+
+    steps:
+      - uses: actions/checkout@v3
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+          cache: 'pip'  # caching pip dependencies
+      - name: Install dependencies
+        run: |
+          sudo apt install ffmpeg libfftw3-dev
+          python -m pip install --upgrade pip
+          pip install pytest pytest-cov ruff
+          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+#      - name: Lint with ruff
+#        run: |
+#          # stop the build if there are Python syntax errors or undefined names
+#          ruff --format=github --select=E9,F63,F7,F82 --target-version=py37 .
+#          # default set of ruff rules with GitHub Annotations
+#          ruff --format=github --target-version=py37 .
+      - name: Setup madmom
+        run: |
+          git submodule update --init --remote
+          pip install -e .
+      - name: Test with pytest
+        run: |
+          pytest --cov --doctest-ignore-import-errors madmom tests
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 6a52dd28..405daf20 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,29 +1,20 @@
 # For most projects, this workflow file will not need changing; you simply need
 # to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
 name: "CodeQL"
 
 on:
   push:
-    branches: [ master ]
+    branches: [ "main" ]
   pull_request:
-    # The branches below must be a subset of the branches above
-    branches: [ master ]
+    branches: [ "main" ]
   schedule:
-    - cron: '15 6 * * 2'
+    - cron: '29 13 * * 0'
 
 jobs:
   analyze:
     name: Analyze
-    runs-on: ubuntu-latest
+    runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+    timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
     permissions:
       actions: read
       contents: read
@@ -33,39 +24,33 @@ jobs:
       fail-fast: false
       matrix:
         language: [ 'python' ]
-        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
-        # Learn more:
-        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
+      uses: github/codeql-action/init@v2
       with:
         languages: ${{ matrix.language }}
-        # If you wish to specify custom queries, you can do so here or in a config file.
-        # By default, queries listed here will override any specified in a config file.
-        # Prefix the list here with "+" to use these queries and those in the config file.
-        # queries: ./path/to/local/query, your-org/your-repo/queries@main
 
-    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
     # If this step fails, then you should remove it and run the build manually (see below)
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
+      uses: github/codeql-action/autobuild@v2
 
     # ℹī¸ Command-line programs to run using the OS shell.
-    # 📚 https://git.io/JvXDl
+    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
 
-    # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines
-    #    and modify them (or add more) to build your code if your project
-    #    uses a compiled language
+    #   If the Autobuild fails above, remove it and uncomment the following three lines.
+    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
 
-    #- run: |
-    #   make bootstrap
-    #   make release
+    # - run: |
+    #     echo "Run, Build Application using script"
+    #     ./location_of_script_within_repo/buildscript.sh
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
+      uses: github/codeql-action/analyze@v2
+      with:
+        category: "/language:${{matrix.language}}"

From 04e108de66e387e15119f86b2ee9e3405d9ccc92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Bo=CC=88ck?= <research@minimoog.org>
Date: Sat, 9 Sep 2023 13:57:32 +0200
Subject: [PATCH 2/5] numpy & scipy compatibility fixes

---
 madmom/audio/spectrogram.py   | 3 +--
 madmom/features/beats_crf.pyx | 2 +-
 madmom/features/onsets.py     | 3 +--
 madmom/features/tempo.py      | 4 ++--
 madmom/ml/nn/layers.py        | 3 +--
 5 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/madmom/audio/spectrogram.py b/madmom/audio/spectrogram.py
index d046ec9b..3794bda8 100644
--- a/madmom/audio/spectrogram.py
+++ b/madmom/audio/spectrogram.py
@@ -11,6 +11,7 @@
 
 import inspect
 import numpy as np
+from scipy.ndimage import maximum_filter
 
 from ..processors import Processor, SequentialProcessor, BufferProcessor
 from .filters import (Filterbank, LogarithmicFilterbank, NUM_BANDS, FMIN, FMAX,
@@ -226,7 +227,6 @@ def tuning_frequency(self, **kwargs):
             Tuning frequency of the spectrogram.
 
         """
-        from scipy.ndimage.filters import maximum_filter
         # widen the spectrogram in frequency dimension
         max_spec = maximum_filter(self, size=[1, 3])
         # get the peaks of the spectrogram
@@ -973,7 +973,6 @@ def __new__(cls, spectrogram, diff_ratio=DIFF_RATIO,
 
         # apply a maximum filter to diff_spec if needed
         if diff_max_bins is not None and diff_max_bins > 1:
-            from scipy.ndimage.filters import maximum_filter
             # widen the spectrogram in frequency dimension
             size = (1, int(diff_max_bins))
             diff_spec = maximum_filter(spectrogram, size=size)
diff --git a/madmom/features/beats_crf.pyx b/madmom/features/beats_crf.pyx
index eb47cd03..08581c70 100644
--- a/madmom/features/beats_crf.pyx
+++ b/madmom/features/beats_crf.pyx
@@ -18,6 +18,7 @@ References
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
+from scipy.ndimage import correlate1d
 
 cimport numpy as np
 cimport cython
@@ -97,7 +98,6 @@ def normalisation_factors(activations, transition_distribution):
         Normalisation factors for model.
 
     """
-    from scipy.ndimage.filters import correlate1d
     return correlate1d(activations, transition_distribution,
                        mode='constant', cval=0,
                        origin=-int(transition_distribution.shape[0] / 2))
diff --git a/madmom/features/onsets.py b/madmom/features/onsets.py
index e7db1f89..3cdb5eba 100644
--- a/madmom/features/onsets.py
+++ b/madmom/features/onsets.py
@@ -10,8 +10,7 @@
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
-from scipy.ndimage import uniform_filter
-from scipy.ndimage.filters import maximum_filter, minimum_filter
+from scipy.ndimage import maximum_filter, minimum_filter, uniform_filter
 
 from ..audio.signal import smooth as smooth_signal
 from ..processors import (BufferProcessor, OnlineProcessor, ParallelProcessor,
diff --git a/madmom/features/tempo.py b/madmom/features/tempo.py
index ffe2d547..36168107 100644
--- a/madmom/features/tempo.py
+++ b/madmom/features/tempo.py
@@ -393,12 +393,12 @@ def process_online(self, activations, reset=True, **kwargs):
 
         """
 
-        activations = np.array(activations, copy=False, subok=True, ndmin=1)
+        activations = np.array(activations, copy=False, subok=True, ndmin=1, dtype=float)
         # reset to initial state
         if reset:
             self.reset()
         # indices at which to retrieve y[n - Ī„]
-        idx = [-self.intervals, np.arange(len(self.intervals))]
+        idx = (-self.intervals, np.arange(len(self.intervals)))
         # iterate over all activations
         # Note: in online mode, activations are just float values, thus cast
         #       them as 1-dimensional array
diff --git a/madmom/ml/nn/layers.py b/madmom/ml/nn/layers.py
index c0769d6e..c0214c54 100644
--- a/madmom/ml/nn/layers.py
+++ b/madmom/ml/nn/layers.py
@@ -12,8 +12,7 @@
 
 import numpy as np
 from numpy.lib.stride_tricks import as_strided
-from scipy.ndimage import convolve as _scipy_convolve
-from scipy.ndimage.filters import maximum_filter
+from scipy.ndimage import convolve as _scipy_convolve, maximum_filter
 
 from .activations import sigmoid, tanh
 

From 44f6cbd1a332313110a21036c948f7dde2c769bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Bo=CC=88ck?= <research@minimoog.org>
Date: Sat, 9 Sep 2023 14:19:27 +0200
Subject: [PATCH 3/5] optimise imports

---
 bin/TCNBeatTracker               |  1 -
 bin/TCNTempoDetector             |  4 +---
 docs/conf.py                     |  3 ++-
 madmom/__init__.py               |  1 -
 madmom/audio/__init__.py         |  4 +---
 madmom/audio/cepstrogram.py      |  2 +-
 madmom/audio/chroma.py           |  5 +++--
 madmom/audio/filters.py          |  1 +
 madmom/audio/hpss.py             |  1 +
 madmom/audio/signal.py           |  1 +
 madmom/audio/spectrogram.py      |  3 ++-
 madmom/evaluation/beats.py       |  2 +-
 madmom/evaluation/chords.py      |  1 -
 madmom/evaluation/key.py         |  1 -
 madmom/evaluation/notes.py       |  2 +-
 madmom/evaluation/tempo.py       |  1 +
 madmom/features/beats_hmm.py     |  1 -
 madmom/features/key.py           |  1 -
 madmom/features/notes_hmm.py     |  1 -
 madmom/io/__init__.py            |  2 +-
 madmom/io/audio.py               |  2 +-
 madmom/io/midi.py                |  5 +++--
 madmom/ml/__init__.py            |  1 -
 madmom/ml/gmm.py                 |  1 -
 madmom/utils/__init__.py         |  3 +--
 setup.py                         |  7 +++----
 tests/test_audio_chroma.py       | 10 ++++++----
 tests/test_audio_filters.py      |  3 +--
 tests/test_audio_spectrogram.py  | 10 ++++------
 tests/test_audio_stft.py         |  7 +++----
 tests/test_evaluation.py         |  3 +--
 tests/test_features_beats.py     |  5 +++--
 tests/test_features_beats_hmm.py |  2 +-
 tests/test_features_onsets.py    |  7 +++----
 tests/test_io_audio.py           |  2 +-
 tests/test_io_midi.py            |  3 +--
 tests/test_ml_crf.py             |  1 +
 tests/test_ml_hmm.py             |  2 +-
 tests/test_ml_nn.py              |  4 ++--
 tests/test_processors.py         |  5 +++--
 tests/test_utils_midi.py         |  3 +--
 41 files changed, 57 insertions(+), 67 deletions(-)

diff --git a/bin/TCNBeatTracker b/bin/TCNBeatTracker
index aa87b75f..011c2dac 100755
--- a/bin/TCNBeatTracker
+++ b/bin/TCNBeatTracker
@@ -13,7 +13,6 @@ from madmom.audio import SignalProcessor
 from madmom.features import ActivationsProcessor
 from madmom.features.beats import DBNBeatTrackingProcessor, TCNBeatProcessor
 from madmom.io import write_beats
-from madmom.ml.nn import NeuralNetworkEnsemble
 from madmom.processors import IOProcessor, io_arguments
 
 
diff --git a/bin/TCNTempoDetector b/bin/TCNTempoDetector
index 716aedda..52554f54 100755
--- a/bin/TCNTempoDetector
+++ b/bin/TCNTempoDetector
@@ -9,13 +9,11 @@ from __future__ import absolute_import, division, print_function
 
 import argparse
 
-import numpy as np
-
 from madmom.audio import SignalProcessor
 from madmom.features import ActivationsProcessor
 from madmom.features.beats import TCNBeatProcessor
 from madmom.features.tempo import TCNTempoHistogramProcessor, TempoEstimationProcessor
-from madmom.io import write_events, write_tempo
+from madmom.io import write_tempo
 from madmom.processors import IOProcessor, io_arguments
 
 
diff --git a/docs/conf.py b/docs/conf.py
index dfdb4d0b..e048acb9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -12,8 +12,9 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys
 import os
+import sys
+
 import pkg_resources
 
 # If extensions (or modules to document with autodoc) are in another directory,
diff --git a/madmom/__init__.py b/madmom/__init__.py
index 88a11199..9e6a3838 100644
--- a/madmom/__init__.py
+++ b/madmom/__init__.py
@@ -17,7 +17,6 @@
 
 import doctest
 
-import numpy as np
 import pkg_resources
 
 # import all packages
diff --git a/madmom/audio/__init__.py b/madmom/audio/__init__.py
index 69b37d60..9f90a790 100644
--- a/madmom/audio/__init__.py
+++ b/madmom/audio/__init__.py
@@ -23,9 +23,7 @@ class or inherit from madmom.SequentialProcessor or ParallelProcessor.
 
 from __future__ import absolute_import, division, print_function
 
-# import the submodules
-from . import comb_filters, filters, signal, spectrogram, stft
-# import classes used often
+# import submodules and classes used often
 from .chroma import DeepChromaProcessor
 from .signal import (FramedSignal, FramedSignalProcessor, Signal,
                      SignalProcessor, )
diff --git a/madmom/audio/cepstrogram.py b/madmom/audio/cepstrogram.py
index 0978a089..6610fbb9 100644
--- a/madmom/audio/cepstrogram.py
+++ b/madmom/audio/cepstrogram.py
@@ -12,9 +12,9 @@
 import numpy as np
 from scipy.fftpack import dct
 
-from ..processors import Processor
 from .filters import MelFilterbank
 from .spectrogram import Spectrogram
+from ..processors import Processor
 
 
 class Cepstrogram(np.ndarray):
diff --git a/madmom/audio/chroma.py b/madmom/audio/chroma.py
index c8ed279b..16ebc0ca 100644
--- a/madmom/audio/chroma.py
+++ b/madmom/audio/chroma.py
@@ -10,13 +10,14 @@
 from __future__ import absolute_import, division, print_function
 
 import warnings
+
 import numpy as np
 
-from madmom.audio.spectrogram import (Spectrogram, FilteredSpectrogram,
-                                      SemitoneBandpassSpectrogram)
 from madmom.audio.filters import (A4, Filterbank,
                                   PitchClassProfileFilterbank as PCP,
                                   HarmonicPitchClassProfileFilterbank as HPCP)
+from madmom.audio.spectrogram import (Spectrogram, FilteredSpectrogram,
+                                      SemitoneBandpassSpectrogram)
 from madmom.processors import SequentialProcessor, Processor
 
 
diff --git a/madmom/audio/filters.py b/madmom/audio/filters.py
index f3c6da35..de7d262f 100644
--- a/madmom/audio/filters.py
+++ b/madmom/audio/filters.py
@@ -10,6 +10,7 @@
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
+
 from ..processors import Processor
 
 FILTER_DTYPE = np.float32
diff --git a/madmom/audio/hpss.py b/madmom/audio/hpss.py
index 93538486..fa0769c8 100644
--- a/madmom/audio/hpss.py
+++ b/madmom/audio/hpss.py
@@ -13,6 +13,7 @@
 
 from madmom.processors import Processor
 
+
 # TODO: keep this as Processors or should it be done as np.ndarray classes?
 
 
diff --git a/madmom/audio/signal.py b/madmom/audio/signal.py
index 88a2d905..dcd8cd90 100644
--- a/madmom/audio/signal.py
+++ b/madmom/audio/signal.py
@@ -10,6 +10,7 @@
 from __future__ import absolute_import, division, print_function
 
 import warnings
+
 import numpy as np
 
 from ..processors import BufferProcessor, Processor
diff --git a/madmom/audio/spectrogram.py b/madmom/audio/spectrogram.py
index 3794bda8..44a1dc8a 100644
--- a/madmom/audio/spectrogram.py
+++ b/madmom/audio/spectrogram.py
@@ -10,12 +10,13 @@
 from __future__ import absolute_import, division, print_function
 
 import inspect
+
 import numpy as np
 from scipy.ndimage import maximum_filter
 
-from ..processors import Processor, SequentialProcessor, BufferProcessor
 from .filters import (Filterbank, LogarithmicFilterbank, NUM_BANDS, FMIN, FMAX,
                       A4, NORM_FILTERS, UNIQUE_FILTERS)
+from ..processors import Processor, SequentialProcessor, BufferProcessor
 
 
 def spec(stft):
diff --git a/madmom/evaluation/beats.py b/madmom/evaluation/beats.py
index c4bafca1..a6ed2591 100644
--- a/madmom/evaluation/beats.py
+++ b/madmom/evaluation/beats.py
@@ -28,8 +28,8 @@
 
 from __future__ import absolute_import, division, print_function
 
-from functools import wraps
 import warnings
+from functools import wraps
 
 import numpy as np
 
diff --git a/madmom/evaluation/chords.py b/madmom/evaluation/chords.py
index c044c070..d190b053 100644
--- a/madmom/evaluation/chords.py
+++ b/madmom/evaluation/chords.py
@@ -34,7 +34,6 @@
 from . import evaluation_io, EvaluationMixin
 from ..io import load_chords
 
-
 CHORD_DTYPE = [('root', int),
                ('bass', int),
                ('intervals', int, (12,))]
diff --git a/madmom/evaluation/key.py b/madmom/evaluation/key.py
index b728b7fc..ae39cdb9 100644
--- a/madmom/evaluation/key.py
+++ b/madmom/evaluation/key.py
@@ -9,7 +9,6 @@
 from . import EvaluationMixin, evaluation_io
 from ..io import load_key
 
-
 _KEY_TO_SEMITONE = {'c': 0, 'c#': 1, 'db': 1, 'd': 2, 'd#': 3, 'eb': 3, 'e': 4,
                     'f': 5, 'f#': 6, 'gb': 6, 'g': 7, 'g#': 8, 'ab': 8, 'a': 9,
                     'a#': 10, 'bb': 10, 'b': 11, 'cb': 11}
diff --git a/madmom/evaluation/notes.py b/madmom/evaluation/notes.py
index f1d4bad2..bb484d09 100644
--- a/madmom/evaluation/notes.py
+++ b/madmom/evaluation/notes.py
@@ -10,6 +10,7 @@
 from __future__ import absolute_import, division, print_function
 
 import warnings
+
 import numpy as np
 
 from . import (evaluation_io, MultiClassEvaluation, SumEvaluation,
@@ -17,7 +18,6 @@
 from .onsets import onset_evaluation, OnsetEvaluation
 from ..io import load_notes
 
-
 # default note evaluation values
 WINDOW = 0.025
 
diff --git a/madmom/evaluation/tempo.py b/madmom/evaluation/tempo.py
index 6d0df40d..44ff8c2c 100644
--- a/madmom/evaluation/tempo.py
+++ b/madmom/evaluation/tempo.py
@@ -10,6 +10,7 @@
 from __future__ import absolute_import, division, print_function
 
 import warnings
+
 import numpy as np
 
 from . import EvaluationMixin, MeanEvaluation, evaluation_io
diff --git a/madmom/features/beats_hmm.py b/madmom/features/beats_hmm.py
index 12f65d6a..63d18464 100644
--- a/madmom/features/beats_hmm.py
+++ b/madmom/features/beats_hmm.py
@@ -16,7 +16,6 @@
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
-
 from madmom.ml.hmm import ObservationModel, TransitionModel
 
 
diff --git a/madmom/features/key.py b/madmom/features/key.py
index 70de408c..cfe05c08 100644
--- a/madmom/features/key.py
+++ b/madmom/features/key.py
@@ -11,7 +11,6 @@
 
 from ..processors import SequentialProcessor
 
-
 KEY_LABELS = ['A major', 'Bb major', 'B major', 'C major', 'Db major',
               'D major', 'Eb major', 'E major', 'F major', 'F# major',
               'G major', 'Ab major', 'A minor', 'Bb minor', 'B minor',
diff --git a/madmom/features/notes_hmm.py b/madmom/features/notes_hmm.py
index 2c43288a..b95ef8f6 100644
--- a/madmom/features/notes_hmm.py
+++ b/madmom/features/notes_hmm.py
@@ -16,7 +16,6 @@
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
-
 from madmom.ml.hmm import TransitionModel, ObservationModel
 
 
diff --git a/madmom/io/__init__.py b/madmom/io/__init__.py
index 9a51c09b..69209d20 100644
--- a/madmom/io/__init__.py
+++ b/madmom/io/__init__.py
@@ -6,8 +6,8 @@
 
 from __future__ import absolute_import, division, print_function
 
-import io as _io
 import contextlib
+import io as _io
 
 import numpy as np
 
diff --git a/madmom/io/audio.py b/madmom/io/audio.py
index 066bea2b..0a6efedd 100644
--- a/madmom/io/audio.py
+++ b/madmom/io/audio.py
@@ -17,8 +17,8 @@
 
 import numpy as np
 
-from ..utils import string_types, file_types
 from ..audio.signal import Signal
+from ..utils import string_types, file_types
 
 
 # error classes
diff --git a/madmom/io/midi.py b/madmom/io/midi.py
index c89da516..80cef9db 100644
--- a/madmom/io/midi.py
+++ b/madmom/io/midi.py
@@ -7,10 +7,11 @@
 
 from __future__ import absolute_import, division, print_function
 
-import numpy as np
-import mido
 import warnings
 
+import mido
+import numpy as np
+
 DEFAULT_TEMPO = 500000  # microseconds per quarter note (i.e. 120 bpm in 4/4)
 DEFAULT_TICKS_PER_BEAT = 480  # ticks per quarter note
 DEFAULT_TIME_SIGNATURE = (4, 4)
diff --git a/madmom/ml/__init__.py b/madmom/ml/__init__.py
index 10989a58..c7a128e9 100644
--- a/madmom/ml/__init__.py
+++ b/madmom/ml/__init__.py
@@ -7,4 +7,3 @@
 from __future__ import absolute_import, division, print_function
 
 # import the submodules
-from . import nn, hmm, gmm, crf
diff --git a/madmom/ml/gmm.py b/madmom/ml/gmm.py
index 41b8ede1..b459bcf6 100644
--- a/madmom/ml/gmm.py
+++ b/madmom/ml/gmm.py
@@ -21,7 +21,6 @@
 from __future__ import absolute_import, division, print_function
 
 import numpy as np
-
 from scipy import linalg
 
 
diff --git a/madmom/utils/__init__.py b/madmom/utils/__init__.py
index 352559b6..b5f661bf 100644
--- a/madmom/utils/__init__.py
+++ b/madmom/utils/__init__.py
@@ -10,13 +10,12 @@
 
 from __future__ import absolute_import, division, print_function
 
-import io
 import argparse
 import contextlib
+import io
 
 import numpy as np
 
-
 # Python 2/3 string compatibility (like six does it)
 try:
     string_types = basestring
diff --git a/setup.py b/setup.py
index 8f3f13f1..c28ff123 100755
--- a/setup.py
+++ b/setup.py
@@ -6,13 +6,12 @@
 
 """
 
-from setuptools import setup, find_packages
+import glob
 from distutils.extension import Extension
 
-from Cython.Build import cythonize, build_ext
-
-import glob
 import numpy as np
+from Cython.Build import cythonize, build_ext
+from setuptools import setup, find_packages
 
 # define version
 version = '0.17.dev0'
diff --git a/tests/test_audio_chroma.py b/tests/test_audio_chroma.py
index acf29b72..5945ff34 100644
--- a/tests/test_audio_chroma.py
+++ b/tests/test_audio_chroma.py
@@ -7,13 +7,15 @@
 
 from __future__ import absolute_import, division, print_function
 
-import numpy as np
 import unittest
-from . import AUDIO_PATH, ACTIVATIONS_PATH
-from madmom.audio.chroma import DeepChromaProcessor, CLPChroma
-from madmom.features import Activations
 from os.path import join as pj
+
+import numpy as np
+
+from madmom.audio.chroma import DeepChromaProcessor, CLPChroma
 from madmom.audio.signal import Signal
+from madmom.features import Activations
+from . import AUDIO_PATH, ACTIVATIONS_PATH
 
 sample_files = [pj(AUDIO_PATH, sf) for sf in ['sample.wav', 'sample2.wav']]
 sample_acts = [Activations(pj(ACTIVATIONS_PATH, af))
diff --git a/tests/test_audio_filters.py b/tests/test_audio_filters.py
index 45aa9a98..e5307f8a 100644
--- a/tests/test_audio_filters.py
+++ b/tests/test_audio_filters.py
@@ -7,12 +7,11 @@
 
 from __future__ import absolute_import, division, print_function
 
-import unittest
 import types
+import unittest
 
 from madmom.audio.filters import *
 
-
 # Mel frequency scale
 HZ = np.asarray([20, 258.7484, 576.6645, 1000])
 MEL = np.asarray([31.749, 354.5, 677.25, 1000])
diff --git a/tests/test_audio_spectrogram.py b/tests/test_audio_spectrogram.py
index 8d791786..cdd5cfa5 100644
--- a/tests/test_audio_spectrogram.py
+++ b/tests/test_audio_spectrogram.py
@@ -10,14 +10,12 @@
 import unittest
 from os.path import join as pj
 
-from . import AUDIO_PATH
-from .test_audio_filters import FFT_FREQS_1024, LOG_FILTERBANK_CENTER_FREQS
-
+from madmom.audio.filters import (MelFilterbank, BarkFilterbank)
+from madmom.audio.signal import Signal
 from madmom.audio.spectrogram import *
-from madmom.audio.filters import (Filterbank, LogarithmicFilterbank,
-                                  MelFilterbank, BarkFilterbank)
 from madmom.audio.stft import ShortTimeFourierTransform
-from madmom.audio.signal import Signal
+from . import AUDIO_PATH
+from .test_audio_filters import FFT_FREQS_1024, LOG_FILTERBANK_CENTER_FREQS
 
 sample_file = pj(AUDIO_PATH, 'sample.wav')
 sample_file_22050 = pj(AUDIO_PATH, 'sample_22050.wav')
diff --git a/tests/test_audio_stft.py b/tests/test_audio_stft.py
index 420d4b6e..1598bedf 100644
--- a/tests/test_audio_stft.py
+++ b/tests/test_audio_stft.py
@@ -7,14 +7,13 @@
 
 from __future__ import absolute_import, division, print_function
 
-import unittest
 import sys
+import unittest
 from os.path import join as pj
 
-from . import AUDIO_PATH
-from madmom.audio.stft import *
 from madmom.audio.spectrogram import Spectrogram
-from madmom.audio.signal import FramedSignal
+from madmom.audio.stft import *
+from . import AUDIO_PATH
 
 sample_file = pj(AUDIO_PATH, 'sample.wav')
 sig_2d = np.array([[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
diff --git a/tests/test_evaluation.py b/tests/test_evaluation.py
index 5ff331f6..1ebdad16 100644
--- a/tests/test_evaluation.py
+++ b/tests/test_evaluation.py
@@ -7,13 +7,12 @@
 
 from __future__ import absolute_import, division, print_function
 
-import unittest
 import math
+import unittest
 from collections import OrderedDict
 
 from madmom.evaluation import *
 
-
 DETECTIONS = np.asarray([0.99, 1.45, 2.01, 2.015, 3.1, 8.1])
 ANNOTATIONS = np.asarray([1, 1.5, 2.0, 2.03, 2.05, 2.5, 3])
 MATCHES = np.asarray([0, 1, 2, 3, 6, 6])
diff --git a/tests/test_features_beats.py b/tests/test_features_beats.py
index 8312925c..16034e52 100644
--- a/tests/test_features_beats.py
+++ b/tests/test_features_beats.py
@@ -10,12 +10,13 @@
 import unittest
 from os.path import join as pj
 
-from . import AUDIO_PATH, ACTIVATIONS_PATH
+from madmom.ml.hmm import HiddenMarkovModel
+
 from madmom.audio.signal import FramedSignal
 from madmom.features import Activations
 from madmom.features.beats import *
 from madmom.features.beats_hmm import *
-from madmom.ml.hmm import HiddenMarkovModel
+from . import AUDIO_PATH, ACTIVATIONS_PATH
 
 sample_file = pj(AUDIO_PATH, "sample.wav")
 sample_lstm_act = Activations(pj(ACTIVATIONS_PATH, "sample.beats_lstm.npz"))
diff --git a/tests/test_features_beats_hmm.py b/tests/test_features_beats_hmm.py
index 162d8202..80484d3c 100644
--- a/tests/test_features_beats_hmm.py
+++ b/tests/test_features_beats_hmm.py
@@ -8,7 +8,7 @@
 from __future__ import absolute_import, division, print_function
 
 import unittest
-from madmom.ml.hmm import *
+
 from madmom.features.beats_hmm import *
 
 
diff --git a/tests/test_features_onsets.py b/tests/test_features_onsets.py
index 09d744cd..b6489caa 100644
--- a/tests/test_features_onsets.py
+++ b/tests/test_features_onsets.py
@@ -10,17 +10,16 @@
 import unittest
 from os.path import join as pj
 
-from . import AUDIO_PATH, ACTIVATIONS_PATH
-
-from madmom.audio.signal import SignalProcessor, FramedSignalProcessor
 from madmom.audio.filters import LogarithmicFilterbank
-from madmom.audio.stft import ShortTimeFourierTransformProcessor
+from madmom.audio.signal import SignalProcessor, FramedSignalProcessor
 from madmom.audio.spectrogram import (Spectrogram, SpectrogramProcessor,
                                       FilteredSpectrogramProcessor,
                                       LogarithmicFilteredSpectrogram,
                                       LogarithmicSpectrogramProcessor)
+from madmom.audio.stft import ShortTimeFourierTransformProcessor
 from madmom.features import Activations
 from madmom.features.onsets import *
+from . import AUDIO_PATH, ACTIVATIONS_PATH
 
 sample_file = pj(AUDIO_PATH, 'sample.wav')
 sample_spec = Spectrogram(sample_file, circular_shift=True)
diff --git a/tests/test_io_audio.py b/tests/test_io_audio.py
index 7d7f5257..5dc6bde6 100644
--- a/tests/test_io_audio.py
+++ b/tests/test_io_audio.py
@@ -7,9 +7,9 @@
 
 from __future__ import absolute_import, division, print_function
 
+import io
 import unittest
 from os.path import join as pj
-import io
 
 from madmom.io.audio import *
 from . import AUDIO_PATH, DATA_PATH
diff --git a/tests/test_io_midi.py b/tests/test_io_midi.py
index 750a0edd..3e394667 100644
--- a/tests/test_io_midi.py
+++ b/tests/test_io_midi.py
@@ -8,12 +8,11 @@
 from __future__ import absolute_import, division, print_function
 
 import os
-import unittest
 import tempfile
+import unittest
 from os.path import join as pj
 
 from madmom.io.midi import *
-
 from . import ANNOTATIONS_PATH
 
 tmp_file = tempfile.NamedTemporaryFile(delete=False).name
diff --git a/tests/test_ml_crf.py b/tests/test_ml_crf.py
index 7b072388..7ffee8f4 100644
--- a/tests/test_ml_crf.py
+++ b/tests/test_ml_crf.py
@@ -8,6 +8,7 @@
 from __future__ import absolute_import, division, print_function
 
 import unittest
+
 from madmom.ml.crf import *
 
 eta = 0.000000000000001  # numerical stability
diff --git a/tests/test_ml_hmm.py b/tests/test_ml_hmm.py
index 4d63231e..8cb94736 100644
--- a/tests/test_ml_hmm.py
+++ b/tests/test_ml_hmm.py
@@ -9,8 +9,8 @@
 
 import sys
 import unittest
-from madmom.ml.hmm import *
 
+from madmom.ml.hmm import *
 
 PRIOR = np.array([0.6, 0.2, 0.2])
 
diff --git a/tests/test_ml_nn.py b/tests/test_ml_nn.py
index 6b6f6d93..da66dd4a 100644
--- a/tests/test_ml_nn.py
+++ b/tests/test_ml_nn.py
@@ -9,10 +9,10 @@
 
 import unittest
 
-from madmom.models import *
 from madmom.ml.nn import *
-from madmom.ml.nn.layers import *
 from madmom.ml.nn.activations import *
+from madmom.ml.nn.layers import *
+from madmom.models import *
 
 
 class TestRNNClass(unittest.TestCase):
diff --git a/tests/test_processors.py b/tests/test_processors.py
index a9065334..8f4daaa1 100644
--- a/tests/test_processors.py
+++ b/tests/test_processors.py
@@ -6,12 +6,13 @@
 """
 
 from __future__ import absolute_import, division, print_function
+
 import tempfile
 import unittest
 
-from madmom.processors import *
-from madmom.models import *
 from madmom.ml.nn import NeuralNetwork
+from madmom.models import *
+from madmom.processors import *
 
 tmp_file = tempfile.NamedTemporaryFile(delete=False).name
 
diff --git a/tests/test_utils_midi.py b/tests/test_utils_midi.py
index 98d780d3..ef9318f1 100644
--- a/tests/test_utils_midi.py
+++ b/tests/test_utils_midi.py
@@ -8,12 +8,11 @@
 from __future__ import absolute_import, division, print_function
 
 import os
-import unittest
 import tempfile
+import unittest
 from os.path import join as pj
 
 from madmom.utils.midi import *
-
 from . import ANNOTATIONS_PATH
 
 tmp_file = tempfile.NamedTemporaryFile(delete=False).name

From 8e899ed3f145479b155114b9177d4c6d4f4adbf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Bo=CC=88ck?= <research@minimoog.org>
Date: Sat, 9 Sep 2023 15:00:36 +0200
Subject: [PATCH 4/5] update pre-commit hooks

---
 .codespellrc            |  2 ++
 .flake8                 |  7 ++++---
 .isort.cfg              |  5 +++++
 .pre-commit-config.yaml | 44 +++++++++++++++++++++++++++++++++++++----
 .pylintrc               | 32 ++++++++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 7 deletions(-)
 create mode 100644 .codespellrc
 create mode 100644 .isort.cfg
 create mode 100644 .pylintrc

diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 00000000..42489936
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,2 @@
+[codespell]
+ignore-words-list = linz
diff --git a/.flake8 b/.flake8
index d674beb1..052fef70 100644
--- a/.flake8
+++ b/.flake8
@@ -1,6 +1,7 @@
 [flake8]
-ignore = E203,W503,Q000
-max-line-length = 80
+ignore = E203,W503
+max-complexity = 18
+max-line-length = 120
 per-file-ignores =
     */__init__.py: F401
-    tests/***.py: F405
+    tests/*: F405
diff --git a/.isort.cfg b/.isort.cfg
new file mode 100644
index 00000000..ea0e813f
--- /dev/null
+++ b/.isort.cfg
@@ -0,0 +1,5 @@
+[settings]
+profile=black
+known_madmom=madmom
+sections=FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER,MADMOM
+line_length=120
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f65dbfc4..2de60c7d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,27 +1,63 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.0.1
+    rev: v4.4.0
     hooks:  # for a list of hooks see https://github.com/pre-commit/pre-commit-hooks
       - id: check-added-large-files
-        args: ['--maxkb=100']
+      - id: check-builtin-literals
       - id: check-case-conflict
+      - id: check-docstring-first
       - id: check-executables-have-shebangs
       - id: check-json
       - id: check-shebang-scripts-are-executable
       - id: check-merge-conflict
       - id: check-symlinks
+      - id: check-toml
       - id: check-yaml
+      - id: debug-statements
       - id: destroyed-symlinks
       - id: detect-private-key
       - id: end-of-file-fixer
       - id: file-contents-sorter
+      - id: fix-byte-order-marker
       - id: mixed-line-ending
+      - id: name-tests-test
       - id: no-commit-to-branch
       - id: pretty-format-json
       - id: requirements-txt-fixer
       - id: sort-simple-yaml
       - id: trailing-whitespace
-  - repo: https://gitlab.com/pycqa/flake8
-    rev: 3.9.2
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.12.0
+    hooks:
+      - id: isort
+        args: [ '--settings-path', '.isort.cfg', '-a', 'from __future__ import annotations' ]
+  - repo: https://github.com/asottile/pyupgrade
+    rev: v3.10.1
+    hooks:
+      - id: pyupgrade
+        args: [ '--py39-plus', '--keep-runtime-typing']
+  - repo: https://github.com/psf/black
+    rev: 23.9.0
+    hooks:
+      - id: black
+        entry: black -t py39 -l 120 -S .
+  - repo: https://github.com/PyCQA/autoflake
+    rev: v2.2.1
+    hooks:
+      - id:
+          autoflake
+  - repo: https://github.com/PyCQA/flake8
+    rev: 6.1.0  # 6.0.0 with flake8-quotes raises ValueError
     hooks:
       - id: flake8
+        additional_dependencies: ['flake8-quotes']
+  - repo: https://github.com/PyCQA/prospector
+    rev: 1.10.2
+    hooks:
+      - id: prospector
+        additional_dependencies: [ 'pylint_pydantic' ]
+  - repo: https://github.com/codespell-project/codespell
+    rev: v2.2.5
+    hooks:
+      - id: codespell
+        entry: codespell -w -i 3
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 00000000..c822b0fc
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,32 @@
+[pylint]
+
+disable=
+    fixme,
+    import-error,
+    import-self,
+    invalid-name,
+    line-too-long,
+    locally-disabled,
+    logging-fstring-interpolation,
+    logging-not-lazy,
+    missing-function-docstring,
+    missing-class-docstring,
+    missing-module-docstring,
+    too-few-public-methods,
+    too-many-arguments,
+    too-many-instance-attributes,
+    too-many-locals,
+    undefined-variable,
+    ungrouped-imports,
+    unspecified-encoding,
+    unused-import,
+    unused-variable,
+    wrong-import-order,
+
+extension-pkg-whitelist=
+    cv2
+
+generated-members=
+    numpy.*,
+    scipy.*,
+    cv2.*,

From d1b2f46f047c36b00a71fed8ea7b812ec7b8f655 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Bo=CC=88ck?= <research@minimoog.org>
Date: Sat, 9 Sep 2023 16:19:16 +0200
Subject: [PATCH 5/5] remove obsolete CI pipeline config files

---
 .appveyor.yml    | 68 ------------------------------------------------
 .checkignore     |  2 --
 .codeclimate.yml | 68 ------------------------------------------------
 .codecov.yml     |  5 ----
 .travis.yml      | 49 ----------------------------------
 5 files changed, 192 deletions(-)
 delete mode 100644 .appveyor.yml
 delete mode 100644 .checkignore
 delete mode 100644 .codeclimate.yml
 delete mode 100644 .codecov.yml
 delete mode 100644 .travis.yml

diff --git a/.appveyor.yml b/.appveyor.yml
deleted file mode 100644
index c416a68c..00000000
--- a/.appveyor.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-version: 1.0.{build}
-
-environment:
-  matrix:
-    - PYTHON: C:\Python27
-      PYTHON_VERSION: 2.7
-      MINICONDA: C:\Miniconda
-      PYTHON_ARCH: "32"
-    - PYTHON: C:\Python27-x64
-      PYTHON_VERSION: 2.7
-      MINICONDA: C:\Miniconda-x64
-      PYTHON_ARCH: "64"
-    - PYTHON: C:\Python35
-      PYTHON_VERSION: 3.5
-      MINICONDA: C:\Miniconda35
-      PYTHON_ARCH: "32"
-    - PYTHON: C:\Python35-x64
-      PYTHON_VERSION: 3.5
-      MINICONDA: C:\Miniconda35-x64
-      PYTHON_ARCH: "64"
-    - PYTHON: C:\Python36
-      PYTHON_VERSION: 3.6
-      MINICONDA: C:\Miniconda36
-      PYTHON_ARCH: "32"
-    - PYTHON: C:\Python36-x64
-      PYTHON_VERSION: 3.6
-      MINICONDA: C:\Miniconda36-x64
-      PYTHON_ARCH: "64"
-    - PYTHON: C:\Python37
-      PYTHON_VERSION: 3.7
-      MINICONDA: C:\Miniconda37
-      PYTHON_ARCH: "32"
-    - PYTHON: C:\Python37-x64
-      PYTHON_VERSION: 3.7
-      MINICONDA: C:\Miniconda37-x64
-      PYTHON_ARCH: "64"
-
-init:
-  - "ECHO %PYTHON% %PYTHON_VERSION% %MINICONDA%"
-
-install:
-  # install Miniconda
-  - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%PATH%"
-  - conda config --set always_yes yes --set changeps1 no
-  - conda update -q conda
-  - conda config --add channels pypi
-  # activate the environment, fixes #439
-  - activate
-  - conda info -a
-  - "conda create -q -n test-environment python=%PYTHON_VERSION% pip cython numpy scipy"
-  - activate test-environment
-  - python -m pip install --upgrade pip
-  - pip install nose mido pytest
-  # Install ffmpeg
-  - ps: Start-FileDownload ('http://ffmpeg.zeranoe.com/builds/win' + $env:PYTHON_ARCH + '/shared/ffmpeg-latest-win' + $env:PYTHON_ARCH + '-shared.zip' ) ffmpeg-shared.zip
-  - 7z x ffmpeg-shared.zip > NULL
-  - "set PATH=%cd%\\ffmpeg-latest-win%PYTHON_ARCH%-shared\\bin;%PATH%"
-
-build: false
-
-build_script:
-  - python setup.py build
-  - git submodule update --init --remote
-
-test_script:
-  - "set PATH=C:\\projects\\madmom\\bin;%PATH%"
-  - "set PYTHONPATH=C:\\projects\\madmom;%PYTHONPATH%"
-  - python setup.py pytest
diff --git a/.checkignore b/.checkignore
deleted file mode 100644
index 8e8c758c..00000000
--- a/.checkignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# files/folders to be ignored by quantifiedcode.com
-tests/*
diff --git a/.codeclimate.yml b/.codeclimate.yml
deleted file mode 100644
index cff149bc..00000000
--- a/.codeclimate.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-version: "2"
-checks:
-  argument-count:
-    enabled: true
-    config:
-      threshold: 6
-  complex-logic:
-    enabled: true
-    config:
-      threshold: 4
-  file-lines:
-    enabled: true
-    config:
-      threshold: 1000
-  method-complexity:
-    enabled: true
-    config:
-      threshold: 5
-  method-count:
-    enabled: true
-    config:
-      threshold: 20
-  method-lines:
-    enabled: true
-    config:
-      threshold: 50
-  nested-control-flow:
-    enabled: true
-    config:
-      threshold: 4
-  return-statements:
-    enabled: true
-    config:
-      threshold: 4
-  similar-code:
-    enabled: false
-  identical-code:
-    enabled: true
-plugins:
-  fixme:
-    enabled: false
-  radon:
-    enabled: true
-    config:
-      threshold: "C"
-  sonar-python:
-    enabled: true
-    config:
-      tests_patterns:
-        - tests/**
-    checks:
-      python:S107:  # number of parameters
-        enabled: false
-      python:S125:  # interprets comment descriptions as commented out code
-        enabled: false
-      python:S1134:  # FIXMEs
-        enabled: false
-      python:S1845:  # rename variables because of CONSTANTS with same name
-        enabled: false
-  git-legal:
-    enabled: true
-ratings:
-  paths:
-  - "**.py"
-  - "**.pyx"
-exclude_paths:
-- docs/
-- tests/
diff --git a/.codecov.yml b/.codecov.yml
deleted file mode 100644
index d5abcd73..00000000
--- a/.codecov.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-coverage:
-  status:
-    patch: false
-
-comment: off
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 97b2aa92..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-language: python
-matrix:
-  include:
-    - python: 3.7
-      dist: xenial
-      sudo: required
-    - python: 3.8
-      dist: focal
-      sudo: required
-    - python: 3.9
-      dist: focal
-      sudo: required
-before_install:
-  # get a working ffmpeg
-  - sudo wget -O ffmpeg.tar.gz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
-  - sudo mkdir ffmpeg
-  - sudo tar xvf ffmpeg.tar.gz -C ffmpeg --strip-components=1
-  - sudo cp ffmpeg/ffmpeg ffmpeg/ffprobe /usr/bin/
-  # install system libraries
-  - sudo apt-get update -qq
-  - sudo apt-get install -qq libfftw3-dev
-  # install numpy etc. via miniconda
-  - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
-        wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -O miniconda.sh;
-    else
-        wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
-    fi
-  - bash miniconda.sh -b -p $HOME/miniconda
-  - export PATH="$HOME/miniconda/bin:$PATH"
-  - hash -r
-  - conda config --set always_yes yes --set changeps1 no
-  - conda update -q conda
-  - conda config --add channels conda-forge
-  - conda config --add channels pypi
-  - conda info -a
-  - deps='pip libgfortran cython numpy scipy pep8'
-  - conda create -q -n test-environment "python=$TRAVIS_PYTHON_VERSION" $deps
-  - source activate test-environment
-  - pip install codecov mido pyfftw
-install:
-  - pip install -e .
-  - pip install coveralls pytest pytest-cov
-before_script:
-  - pep8 --ignore=E402 madmom tests bin
-script:
-  - pytest --cov --doctest-ignore-import-errors madmom tests
-after_success:
-  - codecov
-  - coveralls