def find_xdb_bin(wnd, power=.5, res=1500):
    """
  A not so fast way to find the x-dB cutoff frequency "bin" index.

  Parameters
  ----------
  wnd:
    The window itself as an iterable.
  power:
    The power value (squared amplitude) where the x-dB value should lie,
    using ``x = dB10(power)``.
  res :
    Zero-padding factor. 1 for no zero-padding, 2 for twice the length, etc..
  """
    spectrum = dB20(rfft(wnd, res * len(wnd)))
    root_at_xdb = spectrum - spectrum[0] - dB10(power)
    return next(i for i, el in enumerate(zcross(root_at_xdb)) if el) / res
def find_xdb_bin(wnd, power=.5, res=1500):
  """
  A not so fast way to find the x-dB cutoff frequency "bin" index.

  Parameters
  ----------
  wnd:
    The window itself as an iterable.
  power:
    The power value (squared amplitude) where the x-dB value should lie,
    using ``x = dB10(power)``.
  res :
    Zero-padding factor. 1 for no zero-padding, 2 for twice the length, etc..
  """
  spectrum = dB20(rfft(wnd, res * len(wnd)))
  root_at_xdb = spectrum - spectrum[0] - dB10(power)
  return next(i for i, el in enumerate(zcross(root_at_xdb)) if el) / res
from audiolazy import sHz, dB10, ZFilter, pi, ControlStream, white_noise, chunks, AudioIO, xrange, z
from scipy.signal import butter, buttord
import numpy as np
from time import sleep
import sys

rate = 44100
s, Hz = sHz(rate)
kHz = 1e3 * Hz
tol = 100 * Hz
freq = 2 * kHz

wp = freq - tol  # Bandpass frequency in rad/sample (from zero)
ws = freq + tol  # Bandstop frequency in rad/sample (up to Nyquist frequency)
order, new_wp_divpi = buttord(wp / pi, ws / pi, gpass=dB10(0.6), gstop=dB10(0.4))
ssfilt = butter(order, new_wp_divpi, btype="lowpass")
filt_low = ZFilter(ssfilt[0].tolist(), ssfilt[1].tolist())

## That can be done without scipy using the equation directly:
# filt_low = ((2.90e-4 + 1.16e-3 * z ** -1 + 1.74e-3 * z ** -2
#                     + 1.16e-3 * z ** -3 + 2.90e-4 * z ** -4) /
#            (1       - 3.26    * z ** -1 + 4.04    * z ** -2
#                     - 2.25    * z ** -3 +  .474   * z ** -4))

wp = np.array([freq + tol, 2 * freq - tol])  # Bandpass range in rad/sample
ws = np.array([freq - tol, 2 * freq + tol])  # Bandstop range in rad/sample
order, new_wp_divpi = buttord(wp / pi, ws / pi, gpass=dB10(0.6), gstop=dB10(0.4))
ssfilt = butter(order, new_wp_divpi, btype="bandpass")
filt_high = ZFilter(ssfilt[0].tolist(), ssfilt[1].tolist())
1 (DC level) and -1 (Nyquist).
"""

from __future__ import print_function
from audiolazy import sHz, ZFilter, dB10, resonator, pi
from scipy.signal import butter, buttord
import pylab

# Example
rate = 44100
s, Hz = sHz(rate)
wp = pylab.array([100 * Hz, 240 * Hz])  # Bandpass range in rad/sample
ws = pylab.array([80 * Hz, 260 * Hz])  # Bandstop range in rad/sample

# Let's use wp/pi since SciPy defaults freq from 0 to 1 (Nyquist frequency)
order, new_wp_divpi = buttord(wp / pi, ws / pi, gpass=dB10(.6), gstop=dB10(.4))
ssfilt = butter(order, new_wp_divpi, btype="bandpass")
filt_butter = ZFilter(ssfilt[0].tolist(), ssfilt[1].tolist())

# Some debug information
new_wp = new_wp_divpi * pi
print("Butterworth filter order:", order)  # Should be 3
print("Bandpass ~3dB range (in Hz):", new_wp / Hz)

# Resonator using only the frequency and bandwidth from the Butterworth filter
freq = new_wp.mean()
bw = new_wp[1] - new_wp[0]
filt_reson = resonator.z_exp(freq, bw)

# Plots with MatPlotLib
kwargs = {
def processing_loss(wnd):
    """ Positive number with the ENBW (processing loss) in dB. """
    return dB10(enbw(wnd))
def processing_loss(wnd):
  """ Positive number with the ENBW (processing loss) in dB. """
  return dB10(enbw(wnd))
def find_xdb_bin(wnd, power=.5, res=1500):
  """ A not so fast way to find the x-dB cutoff frequency "bin" index """
  spectrum = dB20(rfft(wnd, res * len(wnd)))
  root_at_xdb = spectrum - spectrum[0] - dB10(power)
  return next(i for i, el in enumerate(zcross(root_at_xdb)) if el) / res