<commit_before>""" Test Iterator Length Transparency

Some functions or methods which accept general iterable arguments have
optional, more efficient code paths if they know how many items to expect.
For instance, map(func, iterable), will pre-allocate the exact amount of
space required whenever the iterable can report its length.

The desired invariant is:  len(it)==len(list(it)).

A complication is that an iterable and iterator can be the same object. To
maintain the invariant, an iterator needs to dynamically update its length.
For instance, an iterable such as range(10) always reports its length as ten,
but it=iter(range(10)) starts at ten, and then goes to nine after next(it).
Having this capability means that map() can ignore the distinction between
map(func, iterable) and map(func, iter(iterable)).

When the iterable is immutable, the implementation can straight-forwardly
report the original length minus the cumulative number of calls to next().
This is the case for tuples, range objects, and itertools.repeat().

Some containers become temporarily immutable during iteration.  This includes
dicts, sets, and collections.deque.  Their implementation is equally simple
though they need to permantently set their length to zero whenever there is
an attempt to iterate after a length mutation.

The situation slightly more involved whenever an object allows length mutation
during iteration.  Lists and sequence iterators are dynanamically updatable.
So, if a list is extended during iteration, the iterator will continue through
the new items.  If it shrinks to a point before the most recent iteration,
then no further items are available and the length is reported at zero.

Reversed objects can also be wrapped around mutable objects; however, any
appends after the current position are ignored.  Any other approach leads
to confusion and possibly returning the same item more than once.

The iterators not listed above, such as enumerate and the other itertools,
are not length transparent because they have no way to distinguish between
iterables that report static length and iterators whose length changes with
each call (i.e. the difference between enumerate('abc') and
enumerate(iter('abc')).

"""

import unittest
from test import test_support
from itertools import repeat
from collections import deque
from UserList import UserList
from builtins import len as _len

n = 10

def len(obj):
    try:
        return _len(obj)
    except TypeError:
        try:
            # note: this is an internal undocumented API,
            # don't rely on it in your own programs
            return obj.__length_hint__()
        except AttributeError:
            raise TypeError

class TestInvariantWithoutMutations(unittest.TestCase):

    def test_invariant(self):
        it = self.it
        for i in reversed(range(1, n+1)):
            self.assertEqual(len(it), i)
            next(it)
        self.assertEqual(len(it), 0)
        self.assertRaises(StopIteration, next, it)
        self.assertEqual(len(it), 0)

class TestTemporarilyImmutable(TestInvariantWithoutMutations):

    def test_immutable_during_iteration(self):
        # objects such as deques, sets, and dictionaries enforce
        # length immutability  during iteration

        it = self.it
        self.assertEqual(len(it), n)
        next(it)
        self.assertEqual(len(it), n-1)
        self.mutate()
        self.assertRaises(RuntimeError, next, it)
        self.assertEqual(len(it), 0)

## ------- Concrete Type Tests -------

class TestRepeat(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = repeat(None, n)

    def test_no_len_for_infinite_repeat(self):
        # The repeat() object can also be infinite
        self.assertRaises(TypeError, len, repeat(None))

class TestXrange(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(range(n))

class TestXrangeCustomReversed(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = reversed(range(n))

class TestTuple(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(tuple(range(n)))

## ------- Types that should not be mutated during iteration -------

class TestDeque(TestTemporarilyImmutable):

    def setUp(self):
        d = deque(range(n))
        self.it = iter(d)
        self.mutate = d.pop

class TestDequeReversed(TestTemporarilyImmutable):

    def setUp(self):
        d = deque(range(n))
        self.it = reversed(d)
        self.mutate = d.pop

class TestDictKeys(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d)
        self.mutate = d.popitem

class TestDictItems(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d.items())
        self.mutate = d.popitem

class TestDictValues(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d.values())
        self.mutate = d.popitem

class TestSet(TestTemporarilyImmutable):

    def setUp(self):
        d = set(range(n))
        self.it = iter(d)
        self.mutate = d.pop

## ------- Types that can mutate during iteration -------

class TestList(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(range(n))

    def test_mutation(self):
        d = list(range(n))
        it = iter(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-1)  # grow with append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])
        d.extend(range(20))
        self.assertEqual(len(it), 0)

class TestListReversed(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = reversed(range(n))

    def test_mutation(self):
        d = list(range(n))
        it = reversed(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-2)  # ignore append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])  # confirm invariant
        d.extend(range(20))
        self.assertEqual(len(it), 0)

class TestSeqIter(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(UserList(range(n)))

    def test_mutation(self):
        d = UserList(range(n))
        it = iter(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-1)  # grow with append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])
        d.extend(range(20))
        self.assertEqual(len(it), 0)

class TestSeqIterReversed(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = reversed(UserList(range(n)))

    def test_mutation(self):
        d = UserList(range(n))
        it = reversed(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-2)  # ignore append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])  # confirm invariant
        d.extend(range(20))
        self.assertEqual(len(it), 0)

def test_main():
    unittests = [
        TestRepeat,
        TestXrange,
        TestXrangeCustomReversed,
        TestTuple,
        TestDeque,
        TestDequeReversed,
        TestDictKeys,
        TestDictItems,
        TestDictValues,
        TestSet,
        TestList,
        TestListReversed,
        TestSeqIter,
        TestSeqIterReversed,
    ]
    test_support.run_unittest(*unittests)

if __name__ == "__main__":
    test_main()
<commit_msg>Reversed UserLists are not required to support __length_hint__.<commit_after>""" Test Iterator Length Transparency

Some functions or methods which accept general iterable arguments have
optional, more efficient code paths if they know how many items to expect.
For instance, map(func, iterable), will pre-allocate the exact amount of
space required whenever the iterable can report its length.

The desired invariant is:  len(it)==len(list(it)).

A complication is that an iterable and iterator can be the same object. To
maintain the invariant, an iterator needs to dynamically update its length.
For instance, an iterable such as range(10) always reports its length as ten,
but it=iter(range(10)) starts at ten, and then goes to nine after next(it).
Having this capability means that map() can ignore the distinction between
map(func, iterable) and map(func, iter(iterable)).

When the iterable is immutable, the implementation can straight-forwardly
report the original length minus the cumulative number of calls to next().
This is the case for tuples, range objects, and itertools.repeat().

Some containers become temporarily immutable during iteration.  This includes
dicts, sets, and collections.deque.  Their implementation is equally simple
though they need to permantently set their length to zero whenever there is
an attempt to iterate after a length mutation.

The situation slightly more involved whenever an object allows length mutation
during iteration.  Lists and sequence iterators are dynanamically updatable.
So, if a list is extended during iteration, the iterator will continue through
the new items.  If it shrinks to a point before the most recent iteration,
then no further items are available and the length is reported at zero.

Reversed objects can also be wrapped around mutable objects; however, any
appends after the current position are ignored.  Any other approach leads
to confusion and possibly returning the same item more than once.

The iterators not listed above, such as enumerate and the other itertools,
are not length transparent because they have no way to distinguish between
iterables that report static length and iterators whose length changes with
each call (i.e. the difference between enumerate('abc') and
enumerate(iter('abc')).

"""

import unittest
from test import test_support
from itertools import repeat
from collections import deque
from builtins import len as _len

n = 10

def len(obj):
    try:
        return _len(obj)
    except TypeError:
        try:
            # note: this is an internal undocumented API,
            # don't rely on it in your own programs
            return obj.__length_hint__()
        except AttributeError:
            raise TypeError

class TestInvariantWithoutMutations(unittest.TestCase):

    def test_invariant(self):
        it = self.it
        for i in reversed(range(1, n+1)):
            self.assertEqual(len(it), i)
            next(it)
        self.assertEqual(len(it), 0)
        self.assertRaises(StopIteration, next, it)
        self.assertEqual(len(it), 0)

class TestTemporarilyImmutable(TestInvariantWithoutMutations):

    def test_immutable_during_iteration(self):
        # objects such as deques, sets, and dictionaries enforce
        # length immutability  during iteration

        it = self.it
        self.assertEqual(len(it), n)
        next(it)
        self.assertEqual(len(it), n-1)
        self.mutate()
        self.assertRaises(RuntimeError, next, it)
        self.assertEqual(len(it), 0)

## ------- Concrete Type Tests -------

class TestRepeat(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = repeat(None, n)

    def test_no_len_for_infinite_repeat(self):
        # The repeat() object can also be infinite
        self.assertRaises(TypeError, len, repeat(None))

class TestXrange(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(range(n))

class TestXrangeCustomReversed(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = reversed(range(n))

class TestTuple(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(tuple(range(n)))

## ------- Types that should not be mutated during iteration -------

class TestDeque(TestTemporarilyImmutable):

    def setUp(self):
        d = deque(range(n))
        self.it = iter(d)
        self.mutate = d.pop

class TestDequeReversed(TestTemporarilyImmutable):

    def setUp(self):
        d = deque(range(n))
        self.it = reversed(d)
        self.mutate = d.pop

class TestDictKeys(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d)
        self.mutate = d.popitem

class TestDictItems(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d.items())
        self.mutate = d.popitem

class TestDictValues(TestTemporarilyImmutable):

    def setUp(self):
        d = dict.fromkeys(range(n))
        self.it = iter(d.values())
        self.mutate = d.popitem

class TestSet(TestTemporarilyImmutable):

    def setUp(self):
        d = set(range(n))
        self.it = iter(d)
        self.mutate = d.pop

## ------- Types that can mutate during iteration -------

class TestList(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = iter(range(n))

    def test_mutation(self):
        d = list(range(n))
        it = iter(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-1)  # grow with append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])
        d.extend(range(20))
        self.assertEqual(len(it), 0)

class TestListReversed(TestInvariantWithoutMutations):

    def setUp(self):
        self.it = reversed(range(n))

    def test_mutation(self):
        d = list(range(n))
        it = reversed(d)
        next(it)
        next(it)
        self.assertEqual(len(it), n-2)
        d.append(n)
        self.assertEqual(len(it), n-2)  # ignore append
        d[1:] = []
        self.assertEqual(len(it), 0)
        self.assertEqual(list(it), [])  # confirm invariant
        d.extend(range(20))
        self.assertEqual(len(it), 0)

def test_main():
    unittests = [
        TestRepeat,
        TestXrange,
        TestXrangeCustomReversed,
        TestTuple,
        TestDeque,
        TestDequeReversed,
        TestDictKeys,
        TestDictItems,
        TestDictValues,
        TestSet,
        TestList,
        TestListReversed,
    ]
    test_support.run_unittest(*unittests)

if __name__ == "__main__":
    test_main()
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Display module for interacting with matplotlib"""

import numpy as np
import matplotlib.image as img
import matplotlib.pyplot as plt

import librosa.core

def specshow(X, sr=22050, hop_length=64, x_axis=None, y_axis=None, n_xticks=5, n_yticks=5,
    fmin=None, fmax=None, **kwargs):
    """Display a spectrogram. Wraps to `~matplotlib.pyplot.imshow` with some handy defaults.

    :parameters:
      - X : np.ndarray
          Matrix to display (eg, spectrogram)

      - sr : int > 0
          Sample rate. Used to determine time scale in x-axis

      - hop_length : int > 0
          Hop length. Also used to determine time scale in x-axis

      - x_axis : None or {'time', 'frames', 'off'}
          If None or 'off', no x axis is displayed.
          If 'time', markers are shown as seconds, minutes, or hours.
          If 'frames', markers are shown as frame counts.

      - y_axis : None or {'linear', 'mel', 'chroma', 'off'}
          If None or 'off', no y axis is displayed.
          If 'linear', frequency range is determined by the FFT window and sample rate.
          If 'log', the image is displayed on a vertical log scale.
          If 'mel', frequencies are determined by the mel scale.
          If 'chroma', pitches are determined by the chroma filters.

     - fmin, fmax : float > 0 or None
          Used for setting the Mel frequency scale

     - kwargs : dict
          Additional arguments passed through to ``matplotlib.pyplot.imshow``.

    :returns:
     - image : ``matplotlib.image.AxesImage``
          As returned from ``matplotlib.pyplot.imshow``.

    """

    kwargs['aspect']        = kwargs.get('aspect',          'auto')
    kwargs['origin']        = kwargs.get('origin',          'lower')
    kwargs['interpolation'] = kwargs.get('interpolation',   'nearest')

    kwargs['cmap']          = kwargs.get('cmap',            'OrRd')

    # FIXME:  2013-11-14 16:15:33 by Brian McFee <brm2132@columbia.edu>
    #  We draw the image twice here. This is a hack to get around NonUniformImage
    #  not properly setting hooks for color: drawing twice enables things like
    #  colorbar() to work properly.

    axes = plt.imshow(X, **kwargs)

    if y_axis is 'log':
        ax = plt.gca()

        # Non-uniform imshow doesn't like aspect
        del kwargs['aspect']
        im   = img.NonUniformImage(ax, **kwargs)

        y_log = (X.shape[0] - np.logspace( 0, np.log2( X.shape[0] ), X.shape[0], base=2.0))[::-1]
        y_inv = np.arange(len(y_log)+1)
        for i in range(len(y_log)-1):
            y_inv[y_log[i]:y_log[i+1]] = i

        im.set_data( np.arange(0, X.shape[1]), y_log, X)
        ax.images.append(im)
        ax.set_ylim(0, X.shape[0])
        ax.set_xlim(0, X.shape[1])

    # Set up the y ticks
    y_pos = np.linspace(0, X.shape[0], n_yticks).astype(int)

    if y_axis is 'linear':
        y_val = np.linspace(0, 0.5 * sr,  X.shape[0] + 1).astype(int)

        plt.yticks(y_pos, y_val[y_pos])
        plt.ylabel('Hz')

    elif y_axis is 'log':

        y_val = np.linspace(0, 0.5 * sr,  X.shape[0] + 1).astype(int)
        plt.yticks(y_pos, y_val[y_inv[y_pos]])

        plt.ylabel('Hz')

    elif y_axis is 'mel':
        m_args = {}
        if fmin is not None:
            m_args['fmin'] = fmin
        if fmax is not None:
            m_args['fmax'] = fmax

        y_val = librosa.core.mel_frequencies(X.shape[0], **m_args)[y_pos].astype(np.int)
        plt.yticks(y_pos, y_val)
        plt.ylabel('Hz')

    elif y_axis is 'chroma':
        y_pos = np.arange(0, X.shape[0], max(1, X.shape[0] / 12))
        y_val = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
        plt.yticks(y_pos, y_val)
        plt.ylabel('Note')

    elif y_axis is None or y_axis is 'off':
        plt.yticks([])
        plt.ylabel('')

    else:
        raise ValueError('Unknown y_axis parameter: %s' % y_axis)

    # Set up the x ticks
    x_pos = np.arange(0, X.shape[1]+1, max(1, X.shape[1] / (n_yticks-1)))

    if x_axis is 'time':
        # Reformat into seconds, or minutes:seconds
        x_val = x_pos * (hop_length / np.float(sr))

        if max(x_val) > 3600.0:
            # reformat into hours:minutes:seconds
            x_val = map(lambda y: '%d:%02d:%02d' % (int(y / 3600), int(np.mod(y, 3600)), int(np.mod(y, 60))), x_val)
        elif max(x_val) > 60.0:
            # reformat into minutes:seconds
            x_val = map(lambda y: '%d:%02d' % (int(y / 60), int(np.mod(y, 60))), x_val)
        else:
            # reformat into seconds, down to the millisecond
            x_val = np.around(x_val, 3)

        plt.xticks(x_pos, x_val)
        plt.xlabel('Time')

    elif x_axis is 'frames':
        # Nothing to do here, plot is in frames
        plt.xticks(x_pos, x_pos)
        plt.xlabel('Frames')
    elif x_axis is None or x_axis is 'off':
        plt.xticks([])
        plt.xlabel('')
    else:
        raise ValueError('Unknown x_axis parameter: %s' % x_axis)

    return axes

<commit_msg>fixed xticks in display<commit_after>#!/usr/bin/env python
"""Display module for interacting with matplotlib"""

import numpy as np
import matplotlib.image as img
import matplotlib.pyplot as plt

import librosa.core

def specshow(X, sr=22050, hop_length=64, x_axis=None, y_axis=None, n_xticks=5, n_yticks=5,
    fmin=None, fmax=None, **kwargs):
    """Display a spectrogram. Wraps to `~matplotlib.pyplot.imshow` with some handy defaults.

    :parameters:
      - X : np.ndarray
          Matrix to display (eg, spectrogram)

      - sr : int > 0
          Sample rate. Used to determine time scale in x-axis

      - hop_length : int > 0
          Hop length. Also used to determine time scale in x-axis

      - x_axis : None or {'time', 'frames', 'off'}
          If None or 'off', no x axis is displayed.
          If 'time', markers are shown as seconds, minutes, or hours.
          If 'frames', markers are shown as frame counts.

      - y_axis : None or {'linear', 'mel', 'chroma', 'off'}
          If None or 'off', no y axis is displayed.
          If 'linear', frequency range is determined by the FFT window and sample rate.
          If 'log', the image is displayed on a vertical log scale.
          If 'mel', frequencies are determined by the mel scale.
          If 'chroma', pitches are determined by the chroma filters.

     - fmin, fmax : float > 0 or None
          Used for setting the Mel frequency scale

     - kwargs : dict
          Additional arguments passed through to ``matplotlib.pyplot.imshow``.

    :returns:
     - image : ``matplotlib.image.AxesImage``
          As returned from ``matplotlib.pyplot.imshow``.

    """

    kwargs['aspect']        = kwargs.get('aspect',          'auto')
    kwargs['origin']        = kwargs.get('origin',          'lower')
    kwargs['interpolation'] = kwargs.get('interpolation',   'nearest')

    kwargs['cmap']          = kwargs.get('cmap',            'OrRd')

    # FIXME:  2013-11-14 16:15:33 by Brian McFee <brm2132@columbia.edu>
    #  We draw the image twice here. This is a hack to get around NonUniformImage
    #  not properly setting hooks for color: drawing twice enables things like
    #  colorbar() to work properly.

    axes = plt.imshow(X, **kwargs)

    if y_axis is 'log':
        ax = plt.gca()

        # Non-uniform imshow doesn't like aspect
        del kwargs['aspect']
        im   = img.NonUniformImage(ax, **kwargs)

        y_log = (X.shape[0] - np.logspace( 0, np.log2( X.shape[0] ), X.shape[0], base=2.0))[::-1]
        y_inv = np.arange(len(y_log)+1)
        for i in range(len(y_log)-1):
            y_inv[y_log[i]:y_log[i+1]] = i

        im.set_data( np.arange(0, X.shape[1]), y_log, X)
        ax.images.append(im)
        ax.set_ylim(0, X.shape[0])
        ax.set_xlim(0, X.shape[1])

    # Set up the y ticks
    y_pos = np.linspace(0, X.shape[0], n_yticks).astype(int)

    if y_axis is 'linear':
        y_val = np.linspace(0, 0.5 * sr,  X.shape[0] + 1).astype(int)

        plt.yticks(y_pos, y_val[y_pos])
        plt.ylabel('Hz')

    elif y_axis is 'log':

        y_val = np.linspace(0, 0.5 * sr,  X.shape[0] + 1).astype(int)
        plt.yticks(y_pos, y_val[y_inv[y_pos]])

        plt.ylabel('Hz')

    elif y_axis is 'mel':
        m_args = {}
        if fmin is not None:
            m_args['fmin'] = fmin
        if fmax is not None:
            m_args['fmax'] = fmax

        y_val = librosa.core.mel_frequencies(X.shape[0], **m_args)[y_pos].astype(np.int)
        plt.yticks(y_pos, y_val)
        plt.ylabel('Hz')

    elif y_axis is 'chroma':
        y_pos = np.arange(0, X.shape[0], max(1, X.shape[0] / 12))
        y_val = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
        plt.yticks(y_pos, y_val)
        plt.ylabel('Note')

    elif y_axis is None or y_axis is 'off':
        plt.yticks([])
        plt.ylabel('')

    else:
        raise ValueError('Unknown y_axis parameter: %s' % y_axis)

    # Set up the x ticks
    x_pos = np.linspace(0, X.shape[1], n_xticks).astype(int)

    if x_axis is 'time':
        # Reformat into seconds, or minutes:seconds
        x_val = x_pos * (hop_length / np.float(sr))

        if max(x_val) > 3600.0:
            # reformat into hours:minutes:seconds
            x_val = map(lambda y: '%d:%02d:%02d' % (int(y / 3600), int(np.mod(y, 3600)), int(np.mod(y, 60))), x_val)
        elif max(x_val) > 60.0:
            # reformat into minutes:seconds
            x_val = map(lambda y: '%d:%02d' % (int(y / 60), int(np.mod(y, 60))), x_val)
        else:
            # reformat into seconds, down to the millisecond
            x_val = np.around(x_val, 3)

        plt.xticks(x_pos, x_val)
        plt.xlabel('Time')

    elif x_axis is 'frames':
        # Nothing to do here, plot is in frames
        plt.xticks(x_pos, x_pos)
        plt.xlabel('Frames')
    elif x_axis is None or x_axis is 'off':
        plt.xticks([])
        plt.xlabel('')
    else:
        raise ValueError('Unknown x_axis parameter: %s' % x_axis)

    return axes

<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Commonly used filter banks: DCT, Chroma, Mel, CQT"""

import numpy as np
import librosa

def dct(n_filts, n_input):
    """Discrete cosine transform basis

    :usage:
        >>> # Compute MFCCs
        >>> S           = librosa.melspectrogram(y, sr)
        >>> dct_filters = librosa.filters.dct(13, S.shape[0])
        >>> mfcc        = dct_filters.dot(librosa.logamplitude(S))

    :parameters:
      - n_filts   : int
          number of output components
      - n_input   : int
          number of input components

    :returns:
      - D         : np.ndarray, shape=(n_filts, n_input)
          DCT basis vectors

    """

    basis       = np.empty((n_filts, n_input))
    basis[0, :] = 1.0 / np.sqrt(n_input)

    samples     = np.arange(1, 2*n_input, 2) * np.pi / (2.0 * n_input)

    for i in xrange(1, n_filts):
        basis[i, :] = np.cos(i*samples) * np.sqrt(2.0/n_input)

    return basis

def mel(sr, n_fft, n_mels=40, fmin=0.0, fmax=None, htk=False):
    """Create a Filterbank matrix to combine FFT bins into Mel-frequency bins

    :usage:
        >>> mel_fb = librosa.filters.mel(22050, 2048)

        >>> # Or clip the maximum frequency to 8KHz
        >>> mel_fb = librosa.filters.mel(22050, 2048, fmax=8000)

    :parameters:
      - sr        : int
          sampling rate of the incoming signal
      - n_fft     : int
          number of FFT components
      - n_mels    : int
          number of Mel bands
      - fmin      : float
          lowest frequency (in Hz)
      - fmax      : float
          highest frequency (in Hz)
      - htk       : bool
          use HTK formula instead of Slaney

    :returns:
      - M         : np.ndarray, shape=(n_mels, 1+ n_fft/2)
          Mel transform matrix

    """

    if fmax is None:
        fmax = sr / 2.0

    # Initialize the weights
    size        = 1 + n_fft / 2
    weights     = np.zeros( (n_mels, size) )

    # Center freqs of each FFT bin
    fftfreqs    = np.arange( size, dtype=float ) * sr / n_fft

    # 'Center freqs' of mel bands - uniformly spaced between limits
    freqs       = librosa.mel_frequencies(n_mels, fmin=fmin, fmax=fmax, htk=htk, extra=True)

    # Slaney-style mel is scaled to be approx constant energy per channel
    enorm       = 2.0 / (freqs[2:n_mels+2] - freqs[:n_mels])

    for i in xrange(n_mels):
        # lower and upper slopes for all bins
        lower   = (fftfreqs - freqs[i])     / (freqs[i+1] - freqs[i])
        upper   = (freqs[i+2] - fftfreqs)   / (freqs[i+2] - freqs[i+1])

        # .. then intersect them with each other and zero
        weights[i]   = np.maximum(0, np.minimum(lower, upper)) * enorm[i]

    return weights

def chroma(sr, n_fft, n_chroma=12, A440=440.0, ctroct=5.0, octwidth=2):
    """Create a Filterbank matrix to convert STFT to chroma

    :usage:
        >>> # Build a simple chroma filter bank
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096)

        >>> # Use quarter-tones instead of semitones
        >>> chroma_fbq  = librosa.filters.chroma(22050, 4096, n_chroma=24)

        >>> # Equally weight all octaves
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096, octwidth=None)

    :parameters:
      - sr        : int
          audio sampling rate
      - n_fft     : int
          FFT window size
      - n_chroma  : int
          number of chroma bins
      - A440      : float
          Reference frequency for A440
      - ctroct    : float
      - octwidth  : float or None
          These parameters specify a dominance window - Gaussian
          weighting centered on `ctroct` (in octs, re A0 = 27.5Hz) and
          with a gaussian half-width of `octwidth`.
          Set `octwidth` to `None` to use a flat weighting.

    :returns:
      - wts       : ndarray, shape=(n_chroma, 1 + n_fft / 2)
          Chroma filter matrix

    """

    wts         = np.zeros((n_chroma, n_fft))

    # Get the FFT bins, not counting the DC component
    frequencies = np.linspace(0, sr, n_fft, endpoint=False)[1:]

    fftfrqbins  = n_chroma * librosa.hz_to_octs(frequencies, A440)

    # make up a value for the 0 Hz bin = 1.5 octaves below bin 1
    # (so chroma is 50% rotated from bin 1, and bin width is broad)
    fftfrqbins = np.concatenate( (   [fftfrqbins[0] - 1.5 * n_chroma],
                                        fftfrqbins))

    binwidthbins = np.concatenate(
        (np.maximum(fftfrqbins[1:] - fftfrqbins[:-1], 1.0), [1]))

    D = np.tile(fftfrqbins, (n_chroma, 1))  \
        - np.tile(np.arange(0, n_chroma, dtype='d')[:, np.newaxis],
        (1, n_fft))

    n_chroma2 = round(n_chroma / 2.0)

    # Project into range -n_chroma/2 .. n_chroma/2
    # add on fixed offset of 10*n_chroma to ensure all values passed to
    # rem are +ve
    D = np.remainder(D + n_chroma2 + 10*n_chroma, n_chroma) - n_chroma2

    # Gaussian bumps - 2*D to make them narrower
    wts = np.exp(-0.5 * (2*D / np.tile(binwidthbins, (n_chroma, 1)))**2)

    # normalize each column
    wts = librosa.util.normalize(wts, norm=2, axis=0)

    # Maybe apply scaling for fft bins
    if octwidth is not None:
        wts *= np.tile(
            np.exp(-0.5 * (((fftfrqbins/n_chroma - ctroct)/octwidth)**2)),
            (n_chroma, 1))

    # remove aliasing columns
    return wts[:, :(1 + n_fft/2)]

def logfrequency(sr, n_fft, bins_per_octave=12, tuning=0.0, fmin=None, fmax=None, spread=0.125):
    '''Approximate a constant-Q filterbank for a fixed-window STFT.

    Each filter is a log-normal window centered at the corresponding pitch frequency.

    :usage:
        >>> # Simple log frequency filters
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096)

        >>> # Use a narrower frequency range
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, fmin=110, fmax=880)

        >>> # Use narrower filters for sparser response: 5% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.05)
        >>> # Or wider: 50% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.5)

    :parameters:
      - sr : int > 0
          audio sampling rate

      - n_fft : int > 0
          FFT window size

      - bins_per_octave : int > 0
          Number of bins per octave. Defaults to 12 (semitones).

      - tuning : None or float in [-0.5, +0.5]
          Tuning correction parameter, in fractions of a bin.

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - fmax : float > 0
          Maximum frequency bin. Defaults to ``C9 = 4816.01``

      - spread : float > 0
          Spread of each filter, as a fraction of a bin.

    :returns:
      - C : np.ndarray, shape=(ceil(log(fmax/fmin)) * bins_per_octave, 1 + n_fft/2)
          CQT filter bank.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if fmax is None:
        fmax = librosa.midi_to_hz(librosa.note_to_midi('C9'))

    # Apply tuning correction
    correction = 2.0**(float(tuning) / bins_per_octave)

    # How many bins can we get?
    n_filters = int(np.ceil(bins_per_octave * np.log2(float(fmax) / fmin)))

    # What's the shape parameter for our log-normal filters?
    sigma = float(spread) / bins_per_octave

    # Construct the output matrix
    basis = np.zeros( (n_filters, n_fft /2  + 1) )

    # Get log frequencies of bins
    log_freqs = np.log2(librosa.fft_frequencies(sr, n_fft)[1:])

    for i in range(n_filters):
        # What's the center (median) frequency of this filter?
        center_freq = correction * fmin * (2.0**(float(i)/bins_per_octave))

        # Place a log-normal window around center_freq
        # We skip the sqrt(2*pi) normalization because it will wash out below anyway
        basis[i, 1:] = np.exp(-0.5 * ((log_freqs - np.log2(center_freq)) /sigma)**2 - np.log2(sigma) - log_freqs)

        # Normalize each filter
        c_norm = np.sqrt(np.sum(basis[i]**2))
        if c_norm > 0:
            basis[i] = basis[i] / c_norm

    return basis

def constant_q(sr, fmin=None, fmax=None, bins_per_octave=12, tuning=0.0, window=np.hamming, resolution=2, pad=False):
    '''Construct a constant-Q basis.

    :usage:
        >>> # Get the CQT basis for C1 to C9, standard tuning
        >>> basis   = librosa.filters.constant_q(22050)
        >>> CQT     = librosa.cqt(y, sr, basis=basis)

        >>> # Change the windowing function to Hanning instead of Hamming
        >>> basis   = librosa.filters.constant_q(22050, window=np.hanning)

        >>> # Use a longer window for each filter
        >>> basis   = librosa.filters.constant_q(22050, resolution=2)

    :parameters:
      - sr : int > 0
          Audio sampling rate

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - fmax : float > 0
          Maximum frequency bin. Defaults to ``C9 = 4816.01``

      - bins_per_octave : int > 0
          Number of bins per octave

      - tuning : float in [-0.5, +0.5)
          Tuning deviation from A440 in fractions of a bin

      - window : function or None
          Windowing function to apply to filters.
          If None, no window is applied.
          Default is to use a hamming window.

      - resolution : float > 0
          Resolution of filter windows. Larger values use longer windows.

      - pad : boolean
          Zero-pad all filters to have a constant width (equal to the longest filter).

      .. note::
            @phdthesis{mcvicar2013,
              title  = {A machine learning approach to automatic chord extraction},
              author = {McVicar, M.},
              year   = {2013},
              school = {University of Bristol}}

    :returns:
      - filters : list of np.ndarray
          filters[i] is the time-domain representation of the i'th CQT basis.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if fmax is None:
        fmax = librosa.midi_to_hz(librosa.note_to_midi('C9'))

    correction = 2.0**(float(tuning) / bins_per_octave)

    fmin       = correction * fmin
    fmax       = correction * fmax

    # Q should be capitalized here, so we suppress the name warning
    Q = float(resolution) / (2.0**(1./bins_per_octave) - 1) # pylint: disable=invalid-name

    # How many bins can we get?
    n_filters = int(np.ceil(bins_per_octave * np.log2(float(fmax) / fmin)))

    filters = []
    for i in np.arange(n_filters, dtype=float):

        # Length of this filter
        ilen = np.ceil(Q * sr / (fmin * 2.0**(i / bins_per_octave)))

        # Build the filter and normalize
        if window is not None:
            win = window(ilen)
        else:
            win = 1.0

        win = win * np.exp(Q * 1j * np.linspace(0, 2 * np.pi, ilen, endpoint=False))
        win /= np.sqrt(np.sum(np.abs(win)**2))

        filters.append(win)

    if pad:
        max_len = max(map(len, filters))

        for i in range(len(filters)):
            f_len = len(filters[i])
            lpad = (max_len - f_len) / 2
            filters[i] = np.pad(filters[i], (lpad, max_len - f_len - lpad), mode='constant')

    return filters

def cq_to_chroma(n_input, bins_per_octave=12, n_chroma=12, roll=0):
    '''Convert a Constant-Q basis to Chroma.

    :usage:
        >>> # Get a CQT, and wrap bins to chroma
        >>> CQT         = librosa.cqt(y, sr)
        >>> chroma_map  = librosa.filters.cq_to_chroma(CQT.shape[0])
        >>> chromagram  = chroma_map.dot(CQT)

    :parameters:
      - n_input : int > 0
          Number of input components (CQT bins)

      - bins_per_octave : int > 0
          How many bins per octave in the CQT

      - n_chroma : int > 0
          Number of output bins (per octave) in the chroma

      - roll : int
          Number of bins to offset the output by.
          For example, if the 0-bin of the CQT is C, and
          the desired 0-bin for the chroma is A, then roll=-3.

    :returns:
      - cq_to_chroma : np.ndarray, shape=(n_chroma, n_input)
          Transformation matrix: ``Chroma = np.dot(cq_to_chroma, CQT)``

    :raises:
      - ValueError
          If n_input is not an integer multiple of n_chroma
    '''

    # How many fractional bins are we merging?
    n_merge = float(bins_per_octave) / n_chroma

    if np.mod(n_merge, 1) != 0:
        raise ValueError('Incompatible CQ merge: input bins must be an integer multiple of output bins.')

    # Tile the identity to merge fractional bins
    cq_to_ch = np.repeat(np.eye(n_chroma), n_merge, axis=1)

    # How many octaves are we repeating?
    n_octaves = np.ceil(np.float(n_input) / bins_per_octave)

    # Repeat and trim
    cq_to_ch = np.tile(cq_to_ch, n_octaves)[:, :n_input]

    # Apply the roll
    cq_to_ch = np.roll(cq_to_ch, -roll, axis=0)

    return cq_to_ch
<commit_msg>intified mel parameters<commit_after>#!/usr/bin/env python
"""Commonly used filter banks: DCT, Chroma, Mel, CQT"""

import numpy as np
import librosa

def dct(n_filts, n_input):
    """Discrete cosine transform basis

    :usage:
        >>> # Compute MFCCs
        >>> S           = librosa.melspectrogram(y, sr)
        >>> dct_filters = librosa.filters.dct(13, S.shape[0])
        >>> mfcc        = dct_filters.dot(librosa.logamplitude(S))

    :parameters:
      - n_filts   : int
          number of output components
      - n_input   : int
          number of input components

    :returns:
      - D         : np.ndarray, shape=(n_filts, n_input)
          DCT basis vectors

    """

    basis       = np.empty((n_filts, n_input))
    basis[0, :] = 1.0 / np.sqrt(n_input)

    samples     = np.arange(1, 2*n_input, 2) * np.pi / (2.0 * n_input)

    for i in xrange(1, n_filts):
        basis[i, :] = np.cos(i*samples) * np.sqrt(2.0/n_input)

    return basis

def mel(sr, n_fft, n_mels=40, fmin=0.0, fmax=None, htk=False):
    """Create a Filterbank matrix to combine FFT bins into Mel-frequency bins

    :usage:
        >>> mel_fb = librosa.filters.mel(22050, 2048)

        >>> # Or clip the maximum frequency to 8KHz
        >>> mel_fb = librosa.filters.mel(22050, 2048, fmax=8000)

    :parameters:
      - sr        : int
          sampling rate of the incoming signal
      - n_fft     : int
          number of FFT components
      - n_mels    : int
          number of Mel bands
      - fmin      : float
          lowest frequency (in Hz)
      - fmax      : float
          highest frequency (in Hz)
      - htk       : bool
          use HTK formula instead of Slaney

    :returns:
      - M         : np.ndarray, shape=(n_mels, 1+ n_fft/2)
          Mel transform matrix

    """

    if fmax is None:
        fmax = sr / 2.0

    # Initialize the weights
    size        = int(1 + n_fft / 2)
    n_mels      = int(n_mels)
    weights     = np.zeros( (n_mels, size) )

    # Center freqs of each FFT bin
    fftfreqs    = np.arange( size, dtype=float ) * sr / n_fft

    # 'Center freqs' of mel bands - uniformly spaced between limits
    freqs       = librosa.mel_frequencies(n_mels, fmin=fmin, fmax=fmax, htk=htk, extra=True)

    # Slaney-style mel is scaled to be approx constant energy per channel
    enorm       = 2.0 / (freqs[2:n_mels+2] - freqs[:n_mels])

    for i in xrange(n_mels):
        # lower and upper slopes for all bins
        lower   = (fftfreqs - freqs[i])     / (freqs[i+1] - freqs[i])
        upper   = (freqs[i+2] - fftfreqs)   / (freqs[i+2] - freqs[i+1])

        # .. then intersect them with each other and zero
        weights[i]   = np.maximum(0, np.minimum(lower, upper)) * enorm[i]

    return weights

def chroma(sr, n_fft, n_chroma=12, A440=440.0, ctroct=5.0, octwidth=2):
    """Create a Filterbank matrix to convert STFT to chroma

    :usage:
        >>> # Build a simple chroma filter bank
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096)

        >>> # Use quarter-tones instead of semitones
        >>> chroma_fbq  = librosa.filters.chroma(22050, 4096, n_chroma=24)

        >>> # Equally weight all octaves
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096, octwidth=None)

    :parameters:
      - sr        : int
          audio sampling rate
      - n_fft     : int
          FFT window size
      - n_chroma  : int
          number of chroma bins
      - A440      : float
          Reference frequency for A440
      - ctroct    : float
      - octwidth  : float or None
          These parameters specify a dominance window - Gaussian
          weighting centered on `ctroct` (in octs, re A0 = 27.5Hz) and
          with a gaussian half-width of `octwidth`.
          Set `octwidth` to `None` to use a flat weighting.

    :returns:
      - wts       : ndarray, shape=(n_chroma, 1 + n_fft / 2)
          Chroma filter matrix

    """

    wts         = np.zeros((n_chroma, n_fft))

    # Get the FFT bins, not counting the DC component
    frequencies = np.linspace(0, sr, n_fft, endpoint=False)[1:]

    fftfrqbins  = n_chroma * librosa.hz_to_octs(frequencies, A440)

    # make up a value for the 0 Hz bin = 1.5 octaves below bin 1
    # (so chroma is 50% rotated from bin 1, and bin width is broad)
    fftfrqbins = np.concatenate( (   [fftfrqbins[0] - 1.5 * n_chroma],
                                        fftfrqbins))

    binwidthbins = np.concatenate(
        (np.maximum(fftfrqbins[1:] - fftfrqbins[:-1], 1.0), [1]))

    D = np.tile(fftfrqbins, (n_chroma, 1))  \
        - np.tile(np.arange(0, n_chroma, dtype='d')[:, np.newaxis],
        (1, n_fft))

    n_chroma2 = round(n_chroma / 2.0)

    # Project into range -n_chroma/2 .. n_chroma/2
    # add on fixed offset of 10*n_chroma to ensure all values passed to
    # rem are +ve
    D = np.remainder(D + n_chroma2 + 10*n_chroma, n_chroma) - n_chroma2

    # Gaussian bumps - 2*D to make them narrower
    wts = np.exp(-0.5 * (2*D / np.tile(binwidthbins, (n_chroma, 1)))**2)

    # normalize each column
    wts = librosa.util.normalize(wts, norm=2, axis=0)

    # Maybe apply scaling for fft bins
    if octwidth is not None:
        wts *= np.tile(
            np.exp(-0.5 * (((fftfrqbins/n_chroma - ctroct)/octwidth)**2)),
            (n_chroma, 1))

    # remove aliasing columns
    return wts[:, :(1 + n_fft/2)]

def logfrequency(sr, n_fft, bins_per_octave=12, tuning=0.0, fmin=None, fmax=None, spread=0.125):
    '''Approximate a constant-Q filterbank for a fixed-window STFT.

    Each filter is a log-normal window centered at the corresponding pitch frequency.

    :usage:
        >>> # Simple log frequency filters
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096)

        >>> # Use a narrower frequency range
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, fmin=110, fmax=880)

        >>> # Use narrower filters for sparser response: 5% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.05)
        >>> # Or wider: 50% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.5)

    :parameters:
      - sr : int > 0
          audio sampling rate

      - n_fft : int > 0
          FFT window size

      - bins_per_octave : int > 0
          Number of bins per octave. Defaults to 12 (semitones).

      - tuning : None or float in [-0.5, +0.5]
          Tuning correction parameter, in fractions of a bin.

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - fmax : float > 0
          Maximum frequency bin. Defaults to ``C9 = 4816.01``

      - spread : float > 0
          Spread of each filter, as a fraction of a bin.

    :returns:
      - C : np.ndarray, shape=(ceil(log(fmax/fmin)) * bins_per_octave, 1 + n_fft/2)
          CQT filter bank.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if fmax is None:
        fmax = librosa.midi_to_hz(librosa.note_to_midi('C9'))

    # Apply tuning correction
    correction = 2.0**(float(tuning) / bins_per_octave)

    # How many bins can we get?
    n_filters = int(np.ceil(bins_per_octave * np.log2(float(fmax) / fmin)))

    # What's the shape parameter for our log-normal filters?
    sigma = float(spread) / bins_per_octave

    # Construct the output matrix
    basis = np.zeros( (n_filters, n_fft /2  + 1) )

    # Get log frequencies of bins
    log_freqs = np.log2(librosa.fft_frequencies(sr, n_fft)[1:])

    for i in range(n_filters):
        # What's the center (median) frequency of this filter?
        center_freq = correction * fmin * (2.0**(float(i)/bins_per_octave))

        # Place a log-normal window around center_freq
        # We skip the sqrt(2*pi) normalization because it will wash out below anyway
        basis[i, 1:] = np.exp(-0.5 * ((log_freqs - np.log2(center_freq)) /sigma)**2 - np.log2(sigma) - log_freqs)

        # Normalize each filter
        c_norm = np.sqrt(np.sum(basis[i]**2))
        if c_norm > 0:
            basis[i] = basis[i] / c_norm

    return basis

def constant_q(sr, fmin=None, fmax=None, bins_per_octave=12, tuning=0.0, window=np.hamming, resolution=2, pad=False):
    '''Construct a constant-Q basis.

    :usage:
        >>> # Get the CQT basis for C1 to C9, standard tuning
        >>> basis   = librosa.filters.constant_q(22050)
        >>> CQT     = librosa.cqt(y, sr, basis=basis)

        >>> # Change the windowing function to Hanning instead of Hamming
        >>> basis   = librosa.filters.constant_q(22050, window=np.hanning)

        >>> # Use a longer window for each filter
        >>> basis   = librosa.filters.constant_q(22050, resolution=2)

    :parameters:
      - sr : int > 0
          Audio sampling rate

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - fmax : float > 0
          Maximum frequency bin. Defaults to ``C9 = 4816.01``

      - bins_per_octave : int > 0
          Number of bins per octave

      - tuning : float in [-0.5, +0.5)
          Tuning deviation from A440 in fractions of a bin

      - window : function or None
          Windowing function to apply to filters.
          If None, no window is applied.
          Default is to use a hamming window.

      - resolution : float > 0
          Resolution of filter windows. Larger values use longer windows.

      - pad : boolean
          Zero-pad all filters to have a constant width (equal to the longest filter).

      .. note::
            @phdthesis{mcvicar2013,
              title  = {A machine learning approach to automatic chord extraction},
              author = {McVicar, M.},
              year   = {2013},
              school = {University of Bristol}}

    :returns:
      - filters : list of np.ndarray
          filters[i] is the time-domain representation of the i'th CQT basis.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if fmax is None:
        fmax = librosa.midi_to_hz(librosa.note_to_midi('C9'))

    correction = 2.0**(float(tuning) / bins_per_octave)

    fmin       = correction * fmin
    fmax       = correction * fmax

    # Q should be capitalized here, so we suppress the name warning
    Q = float(resolution) / (2.0**(1./bins_per_octave) - 1) # pylint: disable=invalid-name

    # How many bins can we get?
    n_filters = int(np.ceil(bins_per_octave * np.log2(float(fmax) / fmin)))

    filters = []
    for i in np.arange(n_filters, dtype=float):

        # Length of this filter
        ilen = np.ceil(Q * sr / (fmin * 2.0**(i / bins_per_octave)))

        # Build the filter and normalize
        if window is not None:
            win = window(ilen)
        else:
            win = 1.0

        win = win * np.exp(Q * 1j * np.linspace(0, 2 * np.pi, ilen, endpoint=False))
        win /= np.sqrt(np.sum(np.abs(win)**2))

        filters.append(win)

    if pad:
        max_len = max(map(len, filters))

        for i in range(len(filters)):
            f_len = len(filters[i])
            lpad = (max_len - f_len) / 2
            filters[i] = np.pad(filters[i], (lpad, max_len - f_len - lpad), mode='constant')

    return filters

def cq_to_chroma(n_input, bins_per_octave=12, n_chroma=12, roll=0):
    '''Convert a Constant-Q basis to Chroma.

    :usage:
        >>> # Get a CQT, and wrap bins to chroma
        >>> CQT         = librosa.cqt(y, sr)
        >>> chroma_map  = librosa.filters.cq_to_chroma(CQT.shape[0])
        >>> chromagram  = chroma_map.dot(CQT)

    :parameters:
      - n_input : int > 0
          Number of input components (CQT bins)

      - bins_per_octave : int > 0
          How many bins per octave in the CQT

      - n_chroma : int > 0
          Number of output bins (per octave) in the chroma

      - roll : int
          Number of bins to offset the output by.
          For example, if the 0-bin of the CQT is C, and
          the desired 0-bin for the chroma is A, then roll=-3.

    :returns:
      - cq_to_chroma : np.ndarray, shape=(n_chroma, n_input)
          Transformation matrix: ``Chroma = np.dot(cq_to_chroma, CQT)``

    :raises:
      - ValueError
          If n_input is not an integer multiple of n_chroma
    '''

    # How many fractional bins are we merging?
    n_merge = float(bins_per_octave) / n_chroma

    if np.mod(n_merge, 1) != 0:
        raise ValueError('Incompatible CQ merge: input bins must be an integer multiple of output bins.')

    # Tile the identity to merge fractional bins
    cq_to_ch = np.repeat(np.eye(n_chroma), n_merge, axis=1)

    # How many octaves are we repeating?
    n_octaves = np.ceil(np.float(n_input) / bins_per_octave)

    # Repeat and trim
    cq_to_ch = np.tile(cq_to_ch, n_octaves)[:, :n_input]

    # Apply the roll
    cq_to_ch = np.roll(cq_to_ch, -roll, axis=0)

    return cq_to_ch
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Commonly used filter banks: DCT, Chroma, Mel, CQT"""

import numpy as np
import librosa

def dct(n_filts, n_input):
    """Discrete cosine transform basis

    :usage:
        >>> # Compute MFCCs
        >>> S           = librosa.melspectrogram(y, sr)
        >>> dct_filters = librosa.filters.dct(13, S.shape[0])
        >>> mfcc        = dct_filters.dot(librosa.logamplitude(S))

    :parameters:
      - n_filts   : int
          number of output components
      - n_input   : int
          number of input components

    :returns:
      - D         : np.ndarray, shape=(n_filts, n_input)
          DCT basis vectors

    """

    basis = np.empty((n_filts, n_input))
    basis[0, :] = 1.0 / np.sqrt(n_input)

    samples = np.arange(1, 2*n_input, 2) * np.pi / (2.0 * n_input)

    for i in xrange(1, n_filts):
        basis[i, :] = np.cos(i*samples) * np.sqrt(2.0/n_input)

    return basis

def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
    """Create a Filterbank matrix to combine FFT bins into Mel-frequency bins

    :usage:
        >>> mel_fb = librosa.filters.mel(22050, 2048)

        >>> # Or clip the maximum frequency to 8KHz
        >>> mel_fb = librosa.filters.mel(22050, 2048, fmax=8000)

    :parameters:
      - sr        : int
          sampling rate of the incoming signal
      - n_fft     : int
          number of FFT components
      - n_mels    : int
          number of Mel bands
      - fmin      : float
          lowest frequency (in Hz)
      - fmax      : float
          highest frequency (in Hz)
      - htk       : bool
          use HTK formula instead of Slaney

    :returns:
      - M         : np.ndarray, shape=(n_mels, 1+ n_fft/2)
          Mel transform matrix
    """

    if fmax is None:
        fmax = sr / 2.0

    # Initialize the weights
    size = int(1 + n_fft / 2)
    n_mels = int(n_mels)
    weights = np.zeros((n_mels, size))

    # Center freqs of each FFT bin
    fftfreqs = np.arange(size, dtype=float) * sr / n_fft

    # 'Center freqs' of mel bands - uniformly spaced between limits
    freqs = librosa.mel_frequencies(n_mels, fmin=fmin, fmax=fmax, htk=htk, extra=True)

    # Slaney-style mel is scaled to be approx constant energy per channel
    enorm = 2.0 / (freqs[2:n_mels+2] - freqs[:n_mels])

    for i in xrange(n_mels):
        # lower and upper slopes for all bins
        lower = (fftfreqs - freqs[i]) / (freqs[i+1] - freqs[i])
        upper = (freqs[i+2] - fftfreqs) / (freqs[i+2] - freqs[i+1])

        # .. then intersect them with each other and zero
        weights[i] = np.maximum(0, np.minimum(lower, upper)) * enorm[i]

    return weights

def chroma(sr, n_fft, n_chroma=12, A440=440.0, ctroct=5.0, octwidth=2):
    """Create a Filterbank matrix to convert STFT to chroma

    :usage:
        >>> # Build a simple chroma filter bank
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096)

        >>> # Use quarter-tones instead of semitones
        >>> chroma_fbq  = librosa.filters.chroma(22050, 4096, n_chroma=24)

        >>> # Equally weight all octaves
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096, octwidth=None)

    :parameters:
      - sr        : int
          audio sampling rate
      - n_fft     : int
          FFT window size
      - n_chroma  : int
          number of chroma bins
      - A440      : float
          Reference frequency for A440
      - ctroct    : float
      - octwidth  : float or None
          These parameters specify a dominance window - Gaussian
          weighting centered on ``ctroct`` (in octs, A0 = 27.5Hz) and
          with a gaussian half-width of ``octwidth``.
          Set ``octwidth`` to ``None`` to use a flat weighting.

    :returns:
      - wts       : ndarray, shape=(n_chroma, 1 + n_fft / 2)
          Chroma filter matrix
    """

    wts = np.zeros((n_chroma, n_fft))

    # Get the FFT bins, not counting the DC component
    frequencies = np.linspace(0, sr, n_fft, endpoint=False)[1:]

    fftfrqbins = n_chroma * librosa.hz_to_octs(frequencies, A440)

    # make up a value for the 0 Hz bin = 1.5 octaves below bin 1
    # (so chroma is 50% rotated from bin 1, and bin width is broad)
    fftfrqbins = np.concatenate(([fftfrqbins[0] - 1.5 * n_chroma], fftfrqbins))

    binwidthbins = np.concatenate((np.maximum(fftfrqbins[1:] - fftfrqbins[:-1], 1.0), [1]))

    D = np.tile(fftfrqbins, (n_chroma, 1)) - np.tile(np.arange(0, n_chroma, dtype='d')[:, np.newaxis], (1, n_fft))

    n_chroma2 = np.round(n_chroma / 2.0)

    # Project into range -n_chroma/2 .. n_chroma/2
    # add on fixed offset of 10*n_chroma to ensure all values passed to
    # rem are +ve
    D = np.remainder(D + n_chroma2 + 10*n_chroma, n_chroma) - n_chroma2

    # Gaussian bumps - 2*D to make them narrower
    wts = np.exp(-0.5 * (2*D / np.tile(binwidthbins, (n_chroma, 1)))**2)

    # normalize each column
    wts = librosa.util.normalize(wts, norm=2, axis=0)

    # Maybe apply scaling for fft bins
    if octwidth is not None:
        wts *= np.tile(
            np.exp(-0.5 * (((fftfrqbins/n_chroma - ctroct)/octwidth)**2)),
            (n_chroma, 1))

    # remove aliasing columns, copy to ensure row-contiguity
    return np.ascontiguousarray(wts[:, :(1 + n_fft/2)])

def logfrequency(sr, n_fft, n_bins=96, bins_per_octave=12, tuning=0.0, fmin=None, spread=0.125):
    '''Approximate a constant-Q filterbank for a fixed-window STFT.

    Each filter is a log-normal window centered at the corresponding pitch frequency.

    :usage:
        >>> # Simple log frequency filters
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096)

        >>> # Use a narrower frequency range
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, n_bins=48, fmin=110)

        >>> # Use narrower filters for sparser response: 5% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.05)
        >>> # Or wider: 50% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.5)

    :parameters:
      - sr : int > 0
          audio sampling rate

      - n_fft : int > 0
          FFT window size

      - n_bins : int > 0
          Number of bins.  Defaults to 96 (8 octaves).

      - bins_per_octave : int > 0
          Number of bins per octave. Defaults to 12 (semitones).

      - tuning : None or float in [-0.5, +0.5]
          Tuning correction parameter, in fractions of a bin.

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - spread : float > 0
          Spread of each filter, as a fraction of a bin.

    :returns:
      - C : np.ndarray, shape=(n_bins, 1 + n_fft/2)
          log-frequency filter bank.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    # Apply tuning correction
    correction = 2.0**(float(tuning) / bins_per_octave)

    # What's the shape parameter for our log-normal filters?
    sigma = float(spread) / bins_per_octave

    # Construct the output matrix
    basis = np.zeros((n_bins, 1 + n_fft/2))

    # Get log frequencies of bins
    log_freqs = np.log2(librosa.fft_frequencies(sr, n_fft)[1:])

    for i in range(n_bins):
        # What's the center (median) frequency of this filter?
        center_freq = correction * fmin * (2.0**(float(i)/bins_per_octave))

        # Place a log-normal window around center_freq
        # We skip the sqrt(2*pi) normalization because it will wash out below anyway
        basis[i, 1:] = np.exp(-0.5 * ((log_freqs - np.log2(center_freq)) /sigma)**2 - np.log2(sigma) - log_freqs)

        # Normalize each filter
        c_norm = np.sqrt(np.sum(basis[i]**2))
        if c_norm > 0:
            basis[i] = basis[i] / c_norm

    return basis

def constant_q(sr, fmin=None, n_bins=96, bins_per_octave=12, tuning=0.0, window=None, resolution=2, pad=False):
    '''Construct a constant-Q basis.

    :usage:
        >>> # Get the CQT basis for C1 to C9, standard tuning
        >>> basis   = librosa.filters.constant_q(22050)
        >>> CQT     = librosa.cqt(y, sr, basis=basis)

        >>> # Change the windowing function to Hanning instead of Hamming
        >>> basis   = librosa.filters.constant_q(22050, window=np.hanning)

        >>> # Use a longer window for each filter
        >>> basis   = librosa.filters.constant_q(22050, resolution=2)

    :parameters:
      - sr : int > 0
          Audio sampling rate

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - n_bins : int > 0
          Number of frequencies.  Defaults to 8 octaves (96 bins).

      - bins_per_octave : int > 0
          Number of bins per octave

      - tuning : float in [-0.5, +0.5)
          Tuning deviation from A440 in fractions of a bin

      - window : function or ``None``
          Windowing function to apply to filters.
          If ``None``, no window is applied.
          Default: np.hamming

      - resolution : float > 0
          Resolution of filter windows. Larger values use longer windows.

      - pad : boolean
          Zero-pad all filters to have a constant width (equal to the longest filter).

      .. note::
            @phdthesis{mcvicar2013,
              title  = {A machine learning approach to automatic chord extraction},
              author = {McVicar, M.},
              year   = {2013},
              school = {University of Bristol}}

    :returns:
      - filters : list of np.ndarray, ``len(filters) == n_bins``
          filters[i] is the time-domain representation of the i'th CQT basis.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if window is None:
        window = np.hamming

    correction = 2.0**(float(tuning) / bins_per_octave)

    fmin = correction * fmin

    # Q should be capitalized here, so we suppress the name warning
    Q = float(resolution) / (2.0**(1./bins_per_octave) - 1) # pylint: disable=invalid-name

    filters = []
    for i in np.arange(n_bins, dtype=float):
        # Length of this filter
        ilen = np.ceil(Q * sr / (fmin * 2.0**(i / bins_per_octave)))

        # Build the filter
        win = np.exp(Q * 1j * np.linspace(0, 2 * np.pi, ilen, endpoint=False))

        # Apply the windowing function
        if window is not None:
            win = win * window(ilen)

        # Normalize
        win = librosa.util.normalize(win, norm=2)

        filters.append(win)

    if pad:
        max_len = max(map(len, filters))

        for i in range(len(filters)):
            filters[i] = librosa.util.pad_center(filters[i], max_len)

    return filters

def cq_to_chroma(n_input, bins_per_octave=12, n_chroma=12, roll=0):
    '''Convert a Constant-Q basis to Chroma.

    :usage:
        >>> # Get a CQT, and wrap bins to chroma
        >>> CQT         = librosa.cqt(y, sr)
        >>> chroma_map  = librosa.filters.cq_to_chroma(CQT.shape[0])
        >>> chromagram  = chroma_map.dot(CQT)

    :parameters:
      - n_input : int > 0
          Number of input components (CQT bins)

      - bins_per_octave : int > 0
          How many bins per octave in the CQT

      - n_chroma : int > 0
          Number of output bins (per octave) in the chroma

      - roll : int
          Number of bins to offset the output by.
          For example, if the 0-bin of the CQT is C, and
          the desired 0-bin for the chroma is A, then roll=-3.

    :returns:
      - cq_to_chroma : np.ndarray, shape=(n_chroma, n_input)
          Transformation matrix: ``Chroma = np.dot(cq_to_chroma, CQT)``

    :raises:
      - ValueError
          If n_input is not an integer multiple of n_chroma
    '''

    # How many fractional bins are we merging?
    n_merge = float(bins_per_octave) / n_chroma

    if np.mod(n_merge, 1) != 0:
        raise ValueError('Incompatible CQ merge: input bins must be an integer multiple of output bins.')

    # Tile the identity to merge fractional bins
    cq_to_ch = np.repeat(np.eye(n_chroma), n_merge, axis=1)

    # How many octaves are we repeating?
    n_octaves = np.ceil(np.float(n_input) / bins_per_octave)

    # Repeat and trim
    cq_to_ch = np.tile(cq_to_ch, int(n_octaves))[:, :n_input]

    # Apply the roll
    cq_to_ch = np.roll(cq_to_ch, -roll, axis=0)

    return cq_to_ch
<commit_msg>doc cleanup in filters<commit_after>#!/usr/bin/env python
"""Commonly used filter banks: DCT, Chroma, Mel, CQT"""

import numpy as np
import librosa

def dct(n_filters, n_input):
    """Discrete cosine transform (DCT) basis

    :usage:
        >>> # Compute MFCCs
        >>> S           = librosa.melspectrogram(y, sr)
        >>> dct_filters = librosa.filters.dct(13, S.shape[0])
        >>> mfcc        = dct_filters.dot(librosa.logamplitude(S))

    :parameters:
      - n_filters : int > 0
          number of output components (DCT filters)

      - n_input : int > 0
          number of input components (frequency bins)

    :returns:
      - dct_basis: np.ndarray, shape=(n_filters, n_input)
          DCT basis vectors

    """

    basis = np.empty((n_filters, n_input))
    basis[0, :] = 1.0 / np.sqrt(n_input)

    samples = np.arange(1, 2*n_input, 2) * np.pi / (2.0 * n_input)

    for i in xrange(1, n_filters):
        basis[i, :] = np.cos(i*samples) * np.sqrt(2.0/n_input)

    return basis

def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
    """Create a Filterbank matrix to combine FFT bins into Mel-frequency bins

    :usage:
        >>> mel_fb = librosa.filters.mel(22050, 2048)

        >>> # Or clip the maximum frequency to 8KHz
        >>> mel_fb = librosa.filters.mel(22050, 2048, fmax=8000)

    :parameters:
      - sr        : int > 0
          sampling rate of the incoming signal

      - n_fft     : int > 0
          number of FFT components

      - n_mels    : int > 0
          number of Mel bands to generate

      - fmin      : float >= 0
          lowest frequency (in Hz)

      - fmax      : float >= 0
          highest frequency (in Hz).
          If ``None``, use ``fmax = sr / 2.0``

      - htk       : bool
          use HTK formula instead of Slaney

    :returns:
      - M         : np.ndarray, shape=(n_mels, 1+ n_fft/2)
          Mel transform matrix
    """

    if fmax is None:
        fmax = sr / 2.0

    # Initialize the weights
    size = int(1 + n_fft / 2)
    n_mels = int(n_mels)
    weights = np.zeros((n_mels, size))

    # Center freqs of each FFT bin
    fftfreqs = np.arange(size, dtype=float) * sr / n_fft

    # 'Center freqs' of mel bands - uniformly spaced between limits
    freqs = librosa.mel_frequencies(n_mels, fmin=fmin, fmax=fmax, htk=htk, extra=True)

    # Slaney-style mel is scaled to be approx constant energy per channel
    enorm = 2.0 / (freqs[2:n_mels+2] - freqs[:n_mels])

    for i in xrange(n_mels):
        # lower and upper slopes for all bins
        lower = (fftfreqs - freqs[i]) / (freqs[i+1] - freqs[i])
        upper = (freqs[i+2] - fftfreqs) / (freqs[i+2] - freqs[i+1])

        # .. then intersect them with each other and zero
        weights[i] = np.maximum(0, np.minimum(lower, upper)) * enorm[i]

    return weights

def chroma(sr, n_fft, n_chroma=12, A440=440.0, ctroct=5.0, octwidth=2):
    """Create a Filterbank matrix to convert STFT to chroma

    :usage:
        >>> # Build a simple chroma filter bank
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096)

        >>> # Use quarter-tones instead of semitones
        >>> chroma_fbq  = librosa.filters.chroma(22050, 4096, n_chroma=24)

        >>> # Equally weight all octaves
        >>> chroma_fb   = librosa.filters.chroma(22050, 4096, octwidth=None)

    :parameters:
      - sr        : int > 0
          audio sampling rate

      - n_fft     : int > 0
          number of FFT bins

      - n_chroma  : int > 0
          number of chroma bins

      - A440      : float
          Reference frequency for A440

      - ctroct    : float > 0

      - octwidth  : float or None
          ``ctroct`` and ``octwidth`` specify a dominance window -
          a Gaussian weighting centered on ``ctroct`` (in octs, A0 = 27.5Hz) and
          with a gaussian half-width of ``octwidth``.
          Set ``octwidth`` to ``None`` to use a flat weighting.

    :returns:
      - wts       : ndarray, shape=(n_chroma, 1 + n_fft / 2)
          Chroma filter matrix
    """

    wts = np.zeros((n_chroma, n_fft))

    # Get the FFT bins, not counting the DC component
    frequencies = np.linspace(0, sr, n_fft, endpoint=False)[1:]

    fftfrqbins = n_chroma * librosa.hz_to_octs(frequencies, A440)

    # make up a value for the 0 Hz bin = 1.5 octaves below bin 1
    # (so chroma is 50% rotated from bin 1, and bin width is broad)
    fftfrqbins = np.concatenate(([fftfrqbins[0] - 1.5 * n_chroma], fftfrqbins))

    binwidthbins = np.concatenate((np.maximum(fftfrqbins[1:] - fftfrqbins[:-1], 1.0), [1]))

    D = np.tile(fftfrqbins, (n_chroma, 1)) - np.tile(np.arange(0, n_chroma, dtype='d')[:, np.newaxis], (1, n_fft))

    n_chroma2 = np.round(n_chroma / 2.0)

    # Project into range -n_chroma/2 .. n_chroma/2
    # add on fixed offset of 10*n_chroma to ensure all values passed to
    # rem are +ve
    D = np.remainder(D + n_chroma2 + 10*n_chroma, n_chroma) - n_chroma2

    # Gaussian bumps - 2*D to make them narrower
    wts = np.exp(-0.5 * (2*D / np.tile(binwidthbins, (n_chroma, 1)))**2)

    # normalize each column
    wts = librosa.util.normalize(wts, norm=2, axis=0)

    # Maybe apply scaling for fft bins
    if octwidth is not None:
        wts *= np.tile(
            np.exp(-0.5 * (((fftfrqbins/n_chroma - ctroct)/octwidth)**2)),
            (n_chroma, 1))

    # remove aliasing columns, copy to ensure row-contiguity
    return np.ascontiguousarray(wts[:, :(1 + n_fft/2)])

def logfrequency(sr, n_fft, n_bins=96, bins_per_octave=12, tuning=0.0, fmin=None, spread=0.125):
    '''Approximate a constant-Q filterbank for a fixed-window STFT.

    Each filter is a log-normal window centered at the corresponding pitch frequency.

    :usage:
        >>> # Simple log frequency filters
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096)

        >>> # Use a narrower frequency range
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, n_bins=48, fmin=110)

        >>> # Use narrower filters for sparser response: 5% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.05)
        >>> # Or wider: 50% of a semitone
        >>> logfs_fb = librosa.filters.logfrequency(22050, 4096, spread=0.5)

    :parameters:
      - sr : int > 0
          audio sampling rate

      - n_fft : int > 0
          FFT window size

      - n_bins : int > 0
          Number of bins.  Defaults to 96 (8 octaves).

      - bins_per_octave : int > 0
          Number of bins per octave. Defaults to 12 (semitones).

      - tuning : None or float in [-0.5, +0.5]
          Tuning correction parameter, in fractions of a bin.

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - spread : float > 0
          Spread of each filter, as a fraction of a bin.

    :returns:
      - C : np.ndarray, shape=(n_bins, 1 + n_fft/2)
          log-frequency filter bank.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    # Apply tuning correction
    correction = 2.0**(float(tuning) / bins_per_octave)

    # What's the shape parameter for our log-normal filters?
    sigma = float(spread) / bins_per_octave

    # Construct the output matrix
    basis = np.zeros((n_bins, 1 + n_fft/2))

    # Get log frequencies of bins
    log_freqs = np.log2(librosa.fft_frequencies(sr, n_fft)[1:])

    for i in range(n_bins):
        # What's the center (median) frequency of this filter?
        center_freq = correction * fmin * (2.0**(float(i)/bins_per_octave))

        # Place a log-normal window around center_freq
        # We skip the sqrt(2*pi) normalization because it will wash out below anyway
        basis[i, 1:] = np.exp(-0.5 * ((log_freqs - np.log2(center_freq)) /sigma)**2 - np.log2(sigma) - log_freqs)

        # Normalize each filter
        c_norm = np.sqrt(np.sum(basis[i]**2))
        if c_norm > 0:
            basis[i] = basis[i] / c_norm

    return basis

def constant_q(sr, fmin=None, n_bins=96, bins_per_octave=12, tuning=0.0, window=None, resolution=2, pad=False):
    '''Construct a constant-Q basis.

    :usage:
        >>> # Get the CQT basis for C1 to C9, standard tuning
        >>> basis   = librosa.filters.constant_q(22050)
        >>> CQT     = librosa.cqt(y, sr, basis=basis)

        >>> # Change the windowing function to Hanning instead of Hamming
        >>> basis   = librosa.filters.constant_q(22050, window=np.hanning)

        >>> # Use a longer window for each filter
        >>> basis   = librosa.filters.constant_q(22050, resolution=2)

    :parameters:
      - sr : int > 0
          Audio sampling rate

      - fmin : float > 0
          Minimum frequency bin. Defaults to ``C1 ~= 16.35``

      - n_bins : int > 0
          Number of frequencies.  Defaults to 8 octaves (96 bins).

      - bins_per_octave : int > 0
          Number of bins per octave

      - tuning : float in [-0.5, +0.5)
          Tuning deviation from A440 in fractions of a bin

      - window : function or ``None``
          Windowing function to apply to filters.
          If ``None``, no window is applied.
          Default: np.hamming

      - resolution : float > 0
          Resolution of filter windows. Larger values use longer windows.

      - pad : boolean
          Zero-pad all filters to have a constant width (equal to the longest filter).

      .. note::
            @phdthesis{mcvicar2013,
              title  = {A machine learning approach to automatic chord extraction},
              author = {McVicar, M.},
              year   = {2013},
              school = {University of Bristol}}

    :returns:
      - filters : list of np.ndarray, ``len(filters) == n_bins``
          ``filters[i]`` is the time-domain representation of the ``i``\ th CQT basis.
    '''

    if fmin is None:
        fmin = librosa.midi_to_hz(librosa.note_to_midi('C1'))

    if window is None:
        window = np.hamming

    correction = 2.0**(float(tuning) / bins_per_octave)

    fmin = correction * fmin

    # Q should be capitalized here, so we suppress the name warning
    Q = float(resolution) / (2.0**(1./bins_per_octave) - 1) # pylint: disable=invalid-name

    filters = []
    for i in np.arange(n_bins, dtype=float):
        # Length of this filter
        ilen = np.ceil(Q * sr / (fmin * 2.0**(i / bins_per_octave)))

        # Build the filter
        win = np.exp(Q * 1j * np.linspace(0, 2 * np.pi, ilen, endpoint=False))

        # Apply the windowing function
        if window is not None:
            win = win * window(ilen)

        # Normalize
        win = librosa.util.normalize(win, norm=2)

        filters.append(win)

    if pad:
        max_len = max(map(len, filters))

        for i in range(len(filters)):
            filters[i] = librosa.util.pad_center(filters[i], max_len)

    return filters

def cq_to_chroma(n_input, bins_per_octave=12, n_chroma=12, roll=0):
    '''Convert a Constant-Q basis to Chroma.

    :usage:
        >>> # Get a CQT, and wrap bins to chroma
        >>> CQT         = librosa.cqt(y, sr)
        >>> chroma_map  = librosa.filters.cq_to_chroma(CQT.shape[0])
        >>> chromagram  = chroma_map.dot(CQT)

    :parameters:
      - n_input : int > 0
          Number of input components (CQT bins)

      - bins_per_octave : int > 0
          How many bins per octave in the CQT

      - n_chroma : int > 0
          Number of output bins (per octave) in the chroma

      - roll : int
          Number of bins to offset the output by.
          For example, if the 0-bin of the CQT is C, and
          the desired 0-bin for the chroma is A, then roll=-3.

    :returns:
      - cq_to_chroma : np.ndarray, shape=(n_chroma, n_input)
          Transformation matrix: ``Chroma = np.dot(cq_to_chroma, CQT)``

    :raises:
      - ValueError
          If n_input is not an integer multiple of n_chroma
    '''

    # How many fractional bins are we merging?
    n_merge = float(bins_per_octave) / n_chroma

    if np.mod(n_merge, 1) != 0:
        raise ValueError('Incompatible CQ merge: input bins must be an integer multiple of output bins.')

    # Tile the identity to merge fractional bins
    cq_to_ch = np.repeat(np.eye(n_chroma), n_merge, axis=1)

    # How many octaves are we repeating?
    n_octaves = np.ceil(np.float(n_input) / bins_per_octave)

    # Repeat and trim
    cq_to_ch = np.tile(cq_to_ch, int(n_octaves))[:, :n_input]

    # Apply the roll
    cq_to_ch = np.roll(cq_to_ch, -roll, axis=0)

    return cq_to_ch
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Manage ACL based on the accounts system
"""

import asyncio

import irc3
from irc3.plugins.command import command

class user_based_policy(object):
    """Only allow users with valid settings"""
    def __init__(self, bot):
        self.bot = bot
        self.bot.include('onebot.plugins.users')
        self.log = self.bot.log.getChild(__name__)

    def has_permission(self, mask, permission):
        user = self.bot.get_user(mask.nick)
        perms = []
        if user:
            perms = yield from user.get_setting('permissions', set())

        self.log.debug("Found permissions for %s: %r", mask.nick, perms)

        if 'ignore' in perms and permission is None:
            return False

        if permission in perms or 'all_permissions' in perms:
            return True

        return False

    @asyncio.coroutine
    def __call__(self, predicates, meth, client, target, args, **kwargs):
        permitted = yield from self.has_permission(
            client, predicates.get('permission'))
        if permitted:
            return meth(client, target, args)
        cmd_name = predicates.get('name', meth.__name__)
        self.log.info('Denied access to command %s to user %s',
                      cmd_name, client)
        self.bot.privmsg(
            client.nick,
            'You are not allowed to use the {command} command'.format(
                command=cmd_name))

@irc3.plugin
class ACLPlugin(object):
    """Plugin to provide access control moderation"""

    requires = [
        'irc3.plugins.command',
        'onebot.plugins.users',
        'irc3.plugins.storage',
    ]

    available_permissions = [
        'operator',
        'admin',
        'view',
        'ignore'
    ]

    def __init__(self, bot):
        self.bot = bot
        module = self.__class__.__module__
        self.log = bot.log.getChild(module)
        self.config = bot.config.get(module, {})
        self.log.debug('Config: %r', self.config)
        if 'superadmin' in self.config:
            self.log.info("Giving {} all_permissions".format(
                self.config['superadmin']))
            self.bot.db.set(self.config['superadmin'],
                            permissions=['all_permissions'])

    @command(permission='admin', show_in_help_list=False)
    @asyncio.coroutine
    def acl(self, mask, target, args):
        """Administrate the ACL

            %%acl (add | remove) <user> <permission>
            %%acl --by-id (add | remove) <id> <permission>
        """
        username, permission = args['<user>'], args['<permission>']
        if permission not in self.available_permissions:
            self.bot.privmsg(
                target,
                ('Invalid permission level. Available permissions: '
                 '{permissions}'.format(
                     permissions=', '.join(self.available_permissions))))
            return
        if not args['--by-id']:
            user = self.bot.get_user(username)
            current_permissions = set()
            if not user:
                self.bot.privmsg(
                    target, ("I don't know {user}. "
                             "Please use --by-id".format(user=username)))
                return
            current_permissions = yield from user.get_setting('permissions',
                                                              set())
        else:
            current_permissions = self.bot.db.get(args['<id>'], {}).get(
                'permissions', set())

        if args['add']:
            current_permissions.add(permission)
        elif args['remove'] and permission in current_permissions:
            current_permissions.remove(permission)

        if not args['--by-id']:
            user.set_setting('permissions', current_permissions)
        else:
            if args['<id>'] not in self.bot.db:
                self.bot.db[args['<id>']] = {}
            self.bot.db[args['<id>']]['permissions'] = current_permissions

        self.bot.privmsg(
            target,
            'Updated permissions for {user}'.format(
                user=username or args['<id>']))

    @classmethod
    def reload(cls, old):  # pragma: no cover
        return cls(old.bot)
<commit_msg>Fix permissions<commit_after># -*- coding: utf-8 -*-
"""
Manage ACL based on the accounts system
"""

import asyncio

import irc3
from irc3.plugins.command import command

class user_based_policy(object):
    """Only allow users with valid settings"""
    def __init__(self, bot):
        self.bot = bot
        self.bot.include('onebot.plugins.users')
        self.log = self.bot.log.getChild(__name__)

    def has_permission(self, mask, permission):
        user = self.bot.get_user(mask.nick)
        perms = []
        if user:
            perms = yield from user.get_setting('permissions', set())

        self.log.debug("Found permissions for %s: %r", mask.nick, perms)

        if 'ignore' in perms or permission is None:
            return False

        if permission in perms or 'all_permissions' in perms:
            return True

        return False

    @asyncio.coroutine
    def __call__(self, predicates, meth, client, target, args, **kwargs):
        permitted = yield from self.has_permission(
            client, predicates.get('permission'))
        if permitted:
            return meth(client, target, args)
        cmd_name = predicates.get('name', meth.__name__)
        self.log.info('Denied access to command %s to user %s',
                      cmd_name, client)
        self.bot.privmsg(
            client.nick,
            'You are not allowed to use the {command} command'.format(
                command=cmd_name))

@irc3.plugin
class ACLPlugin(object):
    """Plugin to provide access control moderation"""

    requires = [
        'irc3.plugins.command',
        'onebot.plugins.users',
        'irc3.plugins.storage',
    ]

    available_permissions = [
        'operator',
        'admin',
        'view',
        'ignore'
    ]

    def __init__(self, bot):
        self.bot = bot
        module = self.__class__.__module__
        self.log = bot.log.getChild(module)
        self.config = bot.config.get(module, {})
        self.log.debug('Config: %r', self.config)
        if 'superadmin' in self.config:
            self.log.info("Giving {} all_permissions".format(
                self.config['superadmin']))
            self.bot.db.set(self.config['superadmin'],
                            permissions=['all_permissions'])

    @command(permission='admin', show_in_help_list=False)
    @asyncio.coroutine
    def acl(self, mask, target, args):
        """Administrate the ACL

            %%acl (add | remove) <user> <permission>
            %%acl --by-id (add | remove) <id> <permission>
        """
        username, permission = args['<user>'], args['<permission>']
        if permission not in self.available_permissions:
            self.bot.privmsg(
                target,
                ('Invalid permission level. Available permissions: '
                 '{permissions}'.format(
                     permissions=', '.join(self.available_permissions))))
            return
        if not args['--by-id']:
            user = self.bot.get_user(username)
            current_permissions = set()
            if not user:
                self.bot.privmsg(
                    target, ("I don't know {user}. "
                             "Please use --by-id".format(user=username)))
                return
            current_permissions = yield from user.get_setting('permissions',
                                                              set())
        else:
            current_permissions = self.bot.db.get(args['<id>'], {}).get(
                'permissions', set())

        if args['add']:
            current_permissions.add(permission)
        elif args['remove'] and permission in current_permissions:
            current_permissions.remove(permission)

        if not args['--by-id']:
            user.set_setting('permissions', current_permissions)
        else:
            if args['<id>'] not in self.bot.db:
                self.bot.db[args['<id>']] = {}
            self.bot.db[args['<id>']]['permissions'] = current_permissions

        self.bot.privmsg(
            target,
            'Updated permissions for {user}'.format(
                user=username or args['<id>']))

    @classmethod
    def reload(cls, old):  # pragma: no cover
        return cls(old.bot)
<|endoftext|>


<commit_before>"""// diagnosis.cpp
#include <wiringPi.h>
#include <stdio.h>
#include "PCA9685.h"
#include "Ultrasonic.h"
#include <signal.h>"""
from multiprocessing import Process
import sys
import Adafruit_PCA9685 as pca
import wiringpi as wp
import signal
import sys
import time
import hcsr04sensor.sensor as uls

LOW = 0
HIGH = 1
OUTPUT = wp.OUTPUT
INPUT = wp.INPUT

CAR_DIR_FW  = 0
CAR_DIR_BK   = 1
CAR_DIR_LF  = 2
CAR_DIR_RF   = 3
CAR_DIR_ST = 4

DIR_DISTANCE_ALERT = 20
preMillis = 0

keepRunning = 1

OUT = [5, 0, 1, 2, 3] # 5:front_left_led, 0:front_right_led, 1:rear_right_led, 2:rear_left_led, 3:ultra_trig
IN = [21, 22, 26, 23] # 21:left_IR, 22:center_IR, 26:right_IR, 23:ultra_echo

ULTRASONIC_TRIG	= 3 # TRIG port is to use as output signal
ULTRASONIC_ECHO = 23 # ECHO port is to use as input signal

# An instance of the motor & buzzer
pca9685 =pca.PCA9685()
#Ultrasonic ultra; # An instance of the ultrasonic sensor
ultra = uls.Measurement(ULTRASONIC_TRIG,ULTRASONIC_ECHO)

# distance range: 2cm ~ 5m
# angular range: 15deg
# resolution: 3mm
"""
void setup();
void loop();
void checkUltra();
void intHandler(int dummy);
"""

def setup():
    wp.wiringPiSetup()  # Initialize wiringPi to load Raspbarry Pi PIN numbering scheme

    """
	for(i=0; i<sizeof(OUT); i++){
		pinMode(OUT[i], OUTPUT); // Set the pin as output mode
		wp.digitalWrite(OUT[i], LOW); // Transmit HIGH or LOW value to the pin(5V ~ 0V)
    }"""
    for i in range(len(OUT)):
        wp.pinMode(OUT[i],OUTPUT)
        wp.digitalWrite(OUT[i], LOW)
    for i in range(len(IN)):
        wp.pinMode(IN[i],INPUT)

def check_ultra():
	rawDis=ultra.raw_distance()
	disValue = ultra.distance_metric(rawDis)
	print("Distance:{0}\t Raw dist:{1}",rawDis,disValue)
def action(menu):
   	global curMillis

	if menu==0:
		pca9685.go_forward();
		time.sleep(20);
		pca9685.stop();

	elif menu== 1:
		pca9685.go_back();
		time.sleep(20);
		pca9685.stop();

	elif menu== 2:
		# frount left
		wp.digitalWrite(OUT[0], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[0], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[0], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[0], LOW);

	elif menu== 3:
		#// frount right
		wp.digitalWrite(OUT[1], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[1], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[1], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[1], LOW);

	elif menu== 4:
		#// rear left
		wp.digitalWrite(OUT[3], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[3], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[3], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[3], LOW);

	elif menu== 5:
		# rear right
		wp.digitalWrite(OUT[2], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[2], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[2], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[2], LOW);
	elif menu ==6:
	    #ultrasonic
	    checkUltra();
	elif menu== 9:
		pca9685.go_right();
		time.sleep(20);
		pca9685.stop();
	elif menu== 10:
		pca9685.go_left();
		time.sleep(20);
		pca9685.stop();
	elif menu== 8:
		print("Beeping for 2 seconds\n");
		pca9685.on_buzz();
		time.sleep(20);
		pca9685.off_buzz();

	elif menu== 11:
		print("EXIT\n");
		keepRunning = 0;

	else:
		print("Check the list again\n")

	print("\n")
	menu = -1
def loop():
	"""//  return the cu
	time(el
	time since your arduino started) in milliseconds(1/1000 second)"""
	llinevalue = 0
	clinevalue = 0
	rlinevalue = 0

	print("This is a diagnostic program for your mobile robot.\n")
	print("0: go foward\n1: go backward\n2: front left led\n3: frount right led\n",
		"4: rear left led\n5: rear right led\n6: ultrasonic\n7: IR\n8: buzzer\n9:go right\n10: go left",
		"\n11: Exit the program\n")
	print("Please select one of them: ")
	menu = int(input())
	action(menu)
	menu = -1

"""// obstacle detection and move to another derection.
void checkUltra(){
	float disValue = ultra.ReadDista
	timeter();
    printf("ultrasonic: %f\n",disValue);
"""

def signal_handler(dummy):
	print("SIGNAL INTERRUPT",dummy)
	time.sleep(1000)
	keepRunning = 0;
#sda

def main (**kwargs):
    setup()
    signal.signal(signal.SIGINT, signal_handler)
    while keepRunning:
        loop()
    return 0

main()
<commit_msg>check_ultra<commit_after>"""// diagnosis.cpp
#include <wiringPi.h>
#include <stdio.h>
#include "PCA9685.h"
#include "Ultrasonic.h"
#include <signal.h>"""
from multiprocessing import Process
import sys
import Adafruit_PCA9685 as pca
import wiringpi as wp
import signal
import sys
import time
import hcsr04sensor.sensor as uls

LOW = 0
HIGH = 1
OUTPUT = wp.OUTPUT
INPUT = wp.INPUT

CAR_DIR_FW  = 0
CAR_DIR_BK   = 1
CAR_DIR_LF  = 2
CAR_DIR_RF   = 3
CAR_DIR_ST = 4

DIR_DISTANCE_ALERT = 20
preMillis = 0

keepRunning = 1

OUT = [5, 0, 1, 2, 3] # 5:front_left_led, 0:front_right_led, 1:rear_right_led, 2:rear_left_led, 3:ultra_trig
IN = [21, 22, 26, 23] # 21:left_IR, 22:center_IR, 26:right_IR, 23:ultra_echo

ULTRASONIC_TRIG	= 3 # TRIG port is to use as output signal
ULTRASONIC_ECHO = 23 # ECHO port is to use as input signal

# An instance of the motor & buzzer
pca9685 =pca.PCA9685()
#Ultrasonic ultra; # An instance of the ultrasonic sensor
ultra = uls.Measurement(ULTRASONIC_TRIG,ULTRASONIC_ECHO)

# distance range: 2cm ~ 5m
# angular range: 15deg
# resolution: 3mm
"""
void setup();
void loop();
void checkUltra();
void intHandler(int dummy);
"""

def setup():
    wp.wiringPiSetup()  # Initialize wiringPi to load Raspbarry Pi PIN numbering scheme

    """
	for(i=0; i<sizeof(OUT); i++){
		pinMode(OUT[i], OUTPUT); // Set the pin as output mode
		wp.digitalWrite(OUT[i], LOW); // Transmit HIGH or LOW value to the pin(5V ~ 0V)
    }"""
    for i in range(len(OUT)):
        wp.pinMode(OUT[i],OUTPUT)
        wp.digitalWrite(OUT[i], LOW)
    for i in range(len(IN)):
        wp.pinMode(IN[i],INPUT)

def check_ultra():
	rawDis=ultra.raw_distance()
	disValue = ultra.distance_metric(rawDis)
	print("Distance:{0}\t Raw dist:{1}",rawDis,disValue)
def action(menu):
   	global curMillis

	if menu==0:
		pca9685.go_forward();
		time.sleep(20);
		pca9685.stop();

	elif menu== 1:
		pca9685.go_back();
		time.sleep(20);
		pca9685.stop();

	elif menu== 2:
		# frount left
		wp.digitalWrite(OUT[0], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[0], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[0], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[0], LOW);

	elif menu== 3:
		#// frount right
		wp.digitalWrite(OUT[1], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[1], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[1], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[1], LOW);

	elif menu== 4:
		#// rear left
		wp.digitalWrite(OUT[3], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[3], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[3], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[3], LOW);

	elif menu== 5:
		# rear right
		wp.digitalWrite(OUT[2], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[2], LOW);
		time.sleep(20);
		wp.digitalWrite(OUT[2], HIGH);
		time.sleep(20);
		wp.digitalWrite(OUT[2], LOW);
	elif menu ==6:
	    #ultrasonic
	    check_ultra();
	elif menu== 9:
		pca9685.go_right();
		time.sleep(20);
		pca9685.stop();
	elif menu== 10:
		pca9685.go_left();
		time.sleep(20);
		pca9685.stop();
	elif menu== 8:
		print("Beeping for 2 seconds\n");
		pca9685.on_buzz();
		time.sleep(20);
		pca9685.off_buzz();

	elif menu== 11:
		print("EXIT\n");
		keepRunning = 0;

	else:
		print("Check the list again\n")

	print("\n")
	menu = -1
def loop():
	"""//  return the cu
	time(el
	time since your arduino started) in milliseconds(1/1000 second)"""
	llinevalue = 0
	clinevalue = 0
	rlinevalue = 0

	print("This is a diagnostic program for your mobile robot.\n")
	print("0: go foward\n1: go backward\n2: front left led\n3: frount right led\n",
		"4: rear left led\n5: rear right led\n6: ultrasonic\n7: IR\n8: buzzer\n9:go right\n10: go left",
		"\n11: Exit the program\n")
	print("Please select one of them: ")
	menu = int(input())
	action(menu)
	menu = -1

"""// obstacle detection and move to another derection.
void checkUltra(){
	float disValue = ultra.ReadDista
	timeter();
    printf("ultrasonic: %f\n",disValue);
"""

def signal_handler(dummy):
	print("SIGNAL INTERRUPT",dummy)
	time.sleep(1000)
	keepRunning = 0;
#sda

def main (**kwargs):
    setup()
    signal.signal(signal.SIGINT, signal_handler)
    while keepRunning:
        loop()
    return 0

main()
<|endoftext|>