Source code for acoustics.bands

"""
Bands
=====

"""
import numpy as np
#from acoustics.decibel import dbsum
import acoustics
from acoustics.standards.iec_61672_1_2013 import (NOMINAL_OCTAVE_CENTER_FREQUENCIES,
                                                  NOMINAL_THIRD_OCTAVE_CENTER_FREQUENCIES)

OCTAVE_CENTER_FREQUENCIES = NOMINAL_OCTAVE_CENTER_FREQUENCIES
THIRD_OCTAVE_CENTER_FREQUENCIES = NOMINAL_THIRD_OCTAVE_CENTER_FREQUENCIES


[docs]def octave(first, last): """ Generate a Numpy array for central frequencies of octave bands. There are more information on how to calculate 'real' bands in http://blog.prosig.com/2006/02/17/standard-octave-bands/ Parameters ---------- first : scalar First octave centerfrequency. last : scalar Last octave centerfrequency. Returns ------- octave_bands : array An array of centerfrequency octave bands. """ #octave_bands = OCTAVE_CENTER_FREQUENCIES #low = np.where(octave_bands == first)[0] #high = np.where(octave_bands == last)[0] #return octave_bands[low: high+1] return acoustics.signal.OctaveBand(fstart=first, fstop=last, fraction=1).nominal
[docs]def octave_low(first, last): """Lower cornerfrequencies of octaves.""" return octave(first, last) / np.sqrt(2.0)
#return acoustics.signal.OctaveBand(fstart=first, fstop=last, fraction=1).lower
[docs]def octave_high(first, last): """Upper cornerfrequencies of octaves.""" return octave(first, last) * np.sqrt(2.0)
#return acoustics.signal.OctaveBand(fstart=first, fstop=last, fraction=1).upper
[docs]def third(first, last): """ Generate a Numpy array for central frequencies of third octave bands. Parameters ---------- first : scalar First third octave centerfrequency. last : scalar Last third octave centerfrequency. Returns ------- octave_bands : array An array of centerfrequency third octave bands. """ #third_oct_bands = THIRD_OCTAVE_CENTER_FREQUENCIES #low = np.where(third_oct_bands == first)[0] #high = np.where(third_oct_bands == last)[0] #return third_oct_bands[low: high+1] return acoustics.signal.OctaveBand(fstart=first, fstop=last, fraction=3).nominal
[docs]def third_low(first, last): """Lower cornerfrequencies of third-octaves.""" return third(first, last) / 2.0**(1.0 / 6.0)
#return acoustics.signal.OctaveBand(fstart=first, fstop=last, fraction=3).lower
[docs]def third_high(first, last): """Higher cornerfrequencies of third-octaves.""" return third(first, last) * 2.0**(1.0 / 6.0)
#return Octaveband(fstart=first, fstop=last, fraction=3).upper
[docs]def third2oct(levels, axis=None): """ Calculate Octave levels from third octave levels. :param levels: Array containing third octave levels. :type: :class:`np.ndarray` :param axis: Axis over which to perform the summation. :type axis: :class:`int` :returns: Third octave levels :rtype: :class:`np.ndarray` .. note:: The number of elements along the summation axis should be a factor of 3. """ levels = np.array(levels) axis = axis if axis is not None else levels.ndim - 1 try: assert levels.shape[axis] % 3 == 0 except AssertionError: raise ValueError("Wrong shape.") shape = list(levels.shape) shape[axis] = shape[axis] // 3 shape.insert(axis + 1, 3) levels = np.reshape(levels, shape) return np.squeeze(acoustics.decibel.dbsum(levels, axis=axis + 1))
def _check_band_type(freqs): """Check if an array contains octave or third octave bands values sorted or unsorted. """ octave_bands = octave(16, 16000) third_oct_bands = third(12.5, 20000) def _check_sort(freqs, bands): index = np.where(np.in1d(bands, freqs))[0] band_pos = index - index[0] return (band_pos == np.arange(band_pos.size)).all() if np.in1d(freqs, octave_bands).all(): is_sorted = _check_sort(freqs, octave_bands) band_type = "octave" if is_sorted else "octave-unsorted" elif np.in1d(freqs, third_oct_bands).all(): is_sorted = _check_sort(freqs, third_oct_bands) band_type = "third" if is_sorted else "third-unsorted" else: band_type = None return band_type