Example #1
0
def chuck(samplerate, sig, shift_hz=1000):
    rc_imag = [
        allpass(samplerate, rc)
        for rc in [5.49e-06, 4.75e-05, 2.37e-04, 1.27e-03]
    ]
    rc_real = [
        allpass(samplerate, rc)
        for rc in [2.00e-05, 1.07e-04, 5.36e-04, 4.64e-03]
    ]

    sos_imag = [
        signal.tf2sos(
            polynomial.polymul(rc1[0], rc2[0]),
            polynomial.polymul(rc1[1], rc2[1]),
        )[0] for rc1, rc2 in zip(rc_imag[::2], rc_imag[1::2])
    ]

    sos_real = [
        signal.tf2sos(
            polynomial.polymul(rc1[0], rc2[0]),
            polynomial.polymul(rc1[1], rc2[1]),
        )[0] for rc1, rc2 in zip(rc_real[::2], rc_real[1::2])
    ]

    # plot_response(sys._getframe().f_code.co_name, sos_real, sos_imag)

    real = signal.sosfilt(sos_real, sig)
    imag = signal.sosfilt(sos_imag, sig)

    analytic = 0.5 * (real - 1j * imag)
    return pitch_shift(samplerate, analytic, shift_hz)
Example #2
0
def group_delays(b, a, w, plot=None):
    """
    Compute group delay of analog filter.

    Parameters
    ----------
    b : array_like
        Numerator of a linear filter.
    a : array_like
        Denominator of a linear filter.
    w : array_like
        Angular frequencies in rad/s.
    plot : callable, optional
        A callable that takes two arguments. If given, the return parameters
        `w` and `gd` are passed to plot.

    Returns
    -------
    w : ndarray
        The angular frequencies at which `gd` was computed.
    gd : ndarray
        The group delay in seconds.
    """
    b, a = map(np.atleast_1d, (b, a))
    sos = tf2sos(b, a)
    gd = sos_group_delays(sos, w)[1]
    if plot is not None:
        plot(w, gd)
    return w, gd
def low_pass_filter(signal, fs, end_freq):
    """
    Description
     - Low Pass Filter

    Input
     :param signal:list, 입력 신호
     :param fs: Float, 샘플링 주파수 (sampling frequency)
     :param end_freq: Float, 끝 주파수 (passband)

    Output
     :return list, 필터링된 신호

    Example:
        >>> signal = [0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1]
        >>> fs = 0.1
        >>> end_freq = 0.02
        >>> low_pass_filter(signal, fs, end_freq)
        array([-7.04764275e-05,  1.06577490e+00,  2.14355722e+00,  2.64998306e+00,
                2.14375040e+00,  1.06552842e+00, -1.00019323e-03, -1.06409485e+00,
               -2.13795954e+00, -2.66057414e+00, -2.17495858e+00, -9.99904965e-01])
    """

    n, wn = buttord(2 * end_freq / fs, 4 * end_freq / fs, 1, 10)  # 'Butterworth Filter'의 차수(order) 구하기
    b, a = butter(n, wn, btype='low')  # 'Butterworth Filter'의 a와 b 파라메터 생성
    sos = tf2sos(b, a)  # 2차수(order) 필터 계수의 배열 구하기

    signal = np.array(signal).reshape(-1)  # 1차원 리스트가 아닌 경우를 위해 1차원으로 변환

    filtered_signal = sosfiltfilt(sos, signal)  # A forward-backward digital filter using cascaded second-order sections.

    return filtered_signal
Example #4
0
    def design_filter(self):
        """
        This filter is used to design Biquad Filters

        This creates the A and B coefficients for Biquad IIR filters as used in CSPL
        """

        f0 = self.fc.value()
        Q = self.Q.value()
        gain = self.linear_gain.value()

        biquadType = self.filter_type.value()

        design_function = BIQUAD_DESIGN_LIBRARY[biquadType]
        b_coefficients, a_coefficients = design_function(
            gain, f0, Q, SAMPLERATE)

        # if the filter design results in a numerator and denominator that are equal, then just implement the passthrough filter
        if np.array_equal(b_coefficients, a_coefficients):
            b_coefficients = np.array([1., 0., 0.])
            a_coefficients = np.array([1., 0., 0.])

        self.a = np.array(a_coefficients) / a_coefficients[0]
        self.b = np.array(b_coefficients) / a_coefficients[0]

        assert len(self.a) == 3
        assert len(self.b) == 3

        self.sos = signal.tf2sos(self.b, self.a)
        self.coefficients_changed.emit()
Example #5
0
def low_shelving_2nd_cascade(w0,
                             Gb,
                             num_biquad,
                             biquad_per_octave,
                             Q=1 / np.sqrt(2)):
    """Low shelving filter design using cascaded biquad filters.

    Parameters
    ----------
    w0 : float
        Cut-off frequency in radian per second.
    Gb : float
        Gain of each biquad filter in decibel.
    num_biquad : int
        Number of biquad filters.
    Q : float, optional
        Quality factor of each biquad filter.

    Returns
    -------
    sos : array_like
        Array of second-order filter coefficients, must have shape
        ``(n_sections, 6)``. Each row corresponds to a second-order
        section, with the first three columns providing the numerator
        coefficients and the last three providing the denominator
        coefficients.

    """
    sos = np.zeros((num_biquad, 6))
    for m in range(num_biquad):
        wm = w0 * 2**(-(m + 0.5) / biquad_per_octave)
        b, a = low_shelving_2nd_coeff(omega=wm, G=Gb, Q=Q)
        sos[m] = tf2sos(b, a)
    return sos
Example #6
0
def group_delayz(b, a, w, plot=None, fs=2*np.pi):
    """
    Compute the group delay of digital filter.

    Parameters
    ----------
    b : array_like
        Numerator of a linear filter.
    a : array_like
        Denominator of a linear filter.
    w : array_like
        Frequencies in the same units as `fs`.
    plot : callable
        A callable that takes two arguments. If given, the return parameters
        `w` and `gd` are passed to plot.
    fs : float, optional
        The angular sampling frequency of the digital system.

    Returns
    -------
    w : ndarray
        The frequencies at which `gd` was computed, in the same units as `fs`.
    gd : ndarray
        The group delay in seconds.
    """
    b, a = map(np.atleast_1d, (b, a))
    if len(a) == 1:
        # scipy.signal.group_delay returns gd in samples thus scaled by 1/fs
        gd = sig.group_delay((b, a), w=w, fs=fs)[1]
    else:
        sos = sig.tf2sos(b, a)
        gd = sos_group_delayz(sos, w, plot, fs)[1]
    if plot is not None:
        plot(w, gd)
    return w, gd
Example #7
0
    def __init__(self, output_count, dtype, color):
        """
        Parameters
        ----------
        output_count : int
            number of channels to generate
        dtype : str or numpy.dtype or type
            data type to generate
        color : str
            coloration of noise to generate
        """
        super().__init__(output_count=output_count, dtype=dtype)
        color = color.upper()

        # initialize constants
        self._GAIN_FACTOR = 20
        # fmt: off
        self._B_PINK = np.array([0.049922035, -0.095993537, 0.050612699, -0.004408786], dtype=dtype)
        self._A_PINK = np.array([1, -2.494956002, 2.017265875, -0.522189400], dtype=dtype)
        # "Consider designing filters in ZPK format and converting directly to SOS."
        # https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.tf2sos.html
        self._SOS_EM = np.array(
            [[0.0248484318401191, -0.0430465879719351, 0.0185894592446002, 1, -1.83308400613427,
              0.833084457582538],
             [1.09742855358091, -2, 0.902572344822294, 1, -1.84861597668780, 0.849007279800584],
             [1.32049919002049, -2, 1.27062183754708, 1, -1.51266987481441, 0.958710654962438],
             [2, -1.23789744854974, 0.693137522016399, 1, -0.555672516031578, 0.356572277622976],
             [2, -0.127412449936323, 0.451198075878658, 1, -0.0464446484127454, 0.0651312831643292],
             [0.295094951044653, 0.0954033015853709, 0, 1, 0, 0]],
            dtype=dtype
        )
        # fmt: on

        # pick utilized coefficients
        if color == "PINK":
            a = self._A_PINK
            self._sos = tf2sos(b=self._B_PINK, a=self._A_PINK).astype(dtype)
            # "It is generally discouraged to convert from TF to SOS format, since doing so
            # usually will not improve numerical precision errors."
            # https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.tf2sos.html
        elif color in ["EM", "EIGENMIKE"]:
            [_, a] = sos2tf(sos=self._SOS_EM)
            self._sos = self._SOS_EM
        else:
            raise NotImplementedError(
                f'chosen noise generator color "{color}" not implemented yet.'
            )

        # initialize IIR filter delay conditions
        self._last_delays = sosfilt_zi(sos=self._sos).astype(dtype)
        # adjust in middle axis according to output count
        self._last_delays = np.repeat(
            self._last_delays[:, np.newaxis, :], repeats=output_count, axis=1
        )

        # approximate decay time to skip transient response part of IIR filter, according to [1]
        t60_samples = int(np.log(1000.0) / (1.0 - np.abs(np.roots(a)).max())) + 1
        # generate and discard long enough sequence to skip IIR transient response (decay time)
        _ = self.generate_block(block_length=t60_samples)
Example #8
0
 def reconstruction(self, v):
     out = np.zeros(v.shape[0])
     for index, filter in enumerate(self.H):
         print("For filter %i, with coefficents\n%s\n" % (index, filter))
         sos = signal.tf2sos(filter.num, filter.den)
         noise = signal.sosfilt(sos, v[:, index])
         out = out + (-1.)**(index) * noise
     return out
 def __init__(self,
              name,
              input_signal,
              b=[1., 1.],
              a=[1., 1., 1.],
              **kwargs):
     super().__init__(name, **kwargs)
     self._input = input_signal
     self._sos = sp.tf2sos(b, a)
Example #10
0
def applyThiran(sig, order=12, oversample=8):
    out = []
    for fraction in np.linspace(0, 1, oversample, endpoint=False)[1:]:
        b, a = thiranAllpass(order, fraction)
        sos = signal.tf2sos(b, a)
        out.append(signal.sosfilt(sos, sig))
    delay = order // 2
    index = np.linspace(-delay, len(sig) - delay, len(out), endpoint=False)
    return out, index
Example #11
0
 def design_filter(self):
     R = self.R.value()
     Rleak = self.Rleak.value()
     L = self.L.value()
     Zs = signal.lti([(R + Rleak) * L, R * Rleak], [L, Rleak])
     Zd = Zs.to_discrete(1 / SAMPLERATE)
     self.b = Zd.num
     self.a = Zd.den
     self.sos = signal.tf2sos(self.b, self.a)
     self.coefficients_changed.emit()
Example #12
0
def mcnulty(samplerate, sig, shift_hz=1000):
    rc_real = [
        allpass(samplerate, rc) for rc in [
            9.31e-06,
            4.2723e-05,
            0.0001836,
            0.00078146,
            0.003333,
            0.026055,
        ]
    ]
    rc_imag = [
        allpass(samplerate, rc) for rc in [
            2.6676e-06,
            2.08e-05,
            8.87e-05,
            0.00038064,
            0.0016049999999999999,
            0.007412,
        ]
    ]

    sos_real = [
        signal.tf2sos(
            polynomial.polymul(rc1[0], rc2[0]),
            polynomial.polymul(rc1[1], rc2[1]),
        )[0] for rc1, rc2 in zip(rc_real[::2], rc_real[1::2])
    ]
    sos_imag = [
        signal.tf2sos(
            polynomial.polymul(rc1[0], rc2[0]),
            polynomial.polymul(rc1[1], rc2[1]),
        )[0] for rc1, rc2 in zip(rc_imag[::2], rc_imag[1::2])
    ]

    # plot_response(sys._getframe().f_code.co_name, sos_real, sos_imag)

    real = signal.sosfilt(sos_real, sig)
    imag = signal.sosfilt(sos_imag, sig)

    analytic = 0.5 * (real - 1j * imag)
    return pitch_shift(samplerate, analytic, shift_hz)
Example #13
0
    def receive_stages(self, b, a):
        self.sos = np.array(ss.tf2sos(b, a, pairing='keep_odd'))
        for it in range(0, len(self.sos)):
            self.stages_list.append(False)
            tempObject = stageControl(self, self.stages_list, it)
            tempItem = QtWidgets.QListWidgetItem()
            tempItem.setSizeHint(tempObject.sizeHint())
            self.ui.FilterList.addItem(tempItem)
            self.ui.FilterList.setItemWidget(tempItem, tempObject)

        self.manage_plot()  #Ploteamos las etapas
def make_digital_filter(N, rp, rs, Wn, btype='low'):
    finish = False
    WnAdd = Wn
    rpAdd = rp
    rsAdd = rs
    fullArray = []
    try:
        while (finish == False):
            if (WnAdd < 0.5):
                WnAdd = WnAdd + 0.001
            elif (abs(rpAdd - rp) / rp < 0.05):
                rpAdd = rpAdd + 0.01
            elif (abs(rsAdd - rs) / rs < 0.05):
                rsAdd = rsAdd + 0.01
            else:
                raise Exception(
                    "There is no filters with these characteristics.")
            b, a = signal.ellip(N, rpAdd, rsAdd, WnAdd, btype, analog=False)
            sos = signal.tf2sos(b, a)
            #print sos
            w, h = signal.sosfreqz(sos, worN=1000000)
            #plot_2nd_order_from_sos(sos)
            makeCallibration(sos)
            #plot_2nd_order_from_sos(sos)
            #print "sos"
            print sos
            w, h = signal.sosfreqz(sos, worN=1000000)
            #plot_sosfreqz(w,h)

            #fullArray = getCoefficientsForElliptic(sos, True)
            fullArray = getCoefficients(sos)

            #print fullArray
            try:
                new_sos = getSosFromCoefficients(fullArray)
                #new_sos = getSosFromCoefficientsForElliptic(fullArray)
                finish = True
            except ValueError as e:
                pass
    except Exception as e:
        print e
        print "There is no filters with these characteristics."
        return

    w, h = signal.sosfreqz(sos, worN=1000000)
    #plot_sosfreqz(w,h)
    print "new_sos"
    print new_sos
    print "general_coefficients"
    fullArrayRounded = getRoundCoefficients(fullArray)
    getKeysFromKoefArray(fullArrayRounded)
    w, h = signal.sosfreqz(new_sos, worN=1000000)
    plot_sosfreqz(w, h)
Example #15
0
def high_shelving_1st_cascade(w0, Gb, num_biquad, biquad_per_octave):
    """High shelving filter design using cascaded biquad filters.

    - see low_shelving_2nd_cascade()
    - under construction for code improvement

    """
    sos = np.zeros((num_biquad, 6))
    for m in range(num_biquad):
        wm = w0 * 2**(-(m + 0.5) / biquad_per_octave)
        b, a = high_shelving_1st_coeff(omega=wm, G=Gb)
        sos[m] = tf2sos(b, a)
    return sos
Example #16
0
def _normalized_sos(coeff):
    # Subfunction to re-normalize the coefficients of the incoming LPC (FIR) coefficients to unity based on the noise
    # gain np.sqrt(np.sum(coeff**2))

    impulse = np.zeros(129)
    impulse[64] = 1
    sos = signal.tf2sos(1, coeff)
    filtsig1 = signal.sosfilt(sos, impulse)
    lpc_noise_gain = np.sqrt(np.sum(filtsig1**2))

    gainmatrix = np.ones([sos.shape[0], sos.shape[1]])
    gainmatrix[0, 0] = 1 / lpc_noise_gain
    soscoeff = sos * gainmatrix

    return soscoeff
Example #17
0
def convert2SOS(myFilter):
    
    SOSarray = tf2sos(myFilter.num, myFilter.den)
    
    SOSnumber,_ = SOSarray.shape
    
    SOSoutput = np.empty(shape=(SOSnumber,3))
    
    for index in range(SOSnumber):
        SOSoutput[index][:] = SOSarray[index][3::]
        
        if SOSoutput[index][2]==0:
            SOSoutput[index] = np.roll(SOSoutput[index],1)
        
    return SOSoutput
Example #18
0
def testApply():
    samplerate = 44100
    duration = 1  # seconds
    frequency = 100

    time = np.linspace(0, duration, duration * samplerate)
    phase = (frequency * time)

    saw = signal.sawtooth(phase, 1.0)

    coef = thiran(16, 16.5)
    print(coef)
    sos = signal.tf2sos(*coef)
    sig = signal.sosfilt(sos, saw)
    print(f"Converge?: {np.all(np.isfinite(sig))}")
    soundfile.write("out.wav", sig, samplerate, subtype="FLOAT")
Example #19
0
def lowShelf(w0, Q, A):
    #Low Shelf
    #H(s) = A * ((s^2 + sqrt(A)*s/Q + A) / (A*(s^2) + sqrt(A)*s/Q + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = A * ((A + 1) - (A - 1) * COSW0 + (2 * math.sqrt(A) * alpha))
    b1 = 2 * A * ((A - 1) - ((A + 1) * COSW0))
    b2 = A * ((A + 1) - (A - 1) * COSW0 - (2 * math.sqrt(A) * alpha))
    a0 = (A + 1) + ((A - 1) * COSW0) + (2 * math.sqrt(A) * alpha)
    a1 = -2 * ((A - 1) + ((A + 1) * COSW0))
    a2 = (A + 1) + ((A - 1) * COSW0) - (2 * math.sqrt(A) * alpha)

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #20
0
def bandpass(w0, Q):
    #BPF using peak gain Q
    #H(s) = s / (s^2 + s/q + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = Q * alpha  #= SINW0/2
    b1 = 0
    b2 = -b0
    a0 = a + alpha
    a1 = -2 * COSW0
    a2 = 1 - alpha

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #21
0
def peaking(w0, Q, A):
    #Peaking EQ, modeled from:
    #H(s) = (s^2 + s*A/Q + 1) / ( s^2 + s/(A*Q) + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = 1 + (alpha * A)
    b1 = -2 * COSW0
    b2 = 1 - (alpha * A)
    a0 = 1 + (alpha / A)
    a1 = -2 * COSW0
    a2 = 1 - (alpha / A)

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #22
0
def highpass(w0, Q):
    #HPF, modeled from:
    #H(s) = (s^2) / ((s^2) + (s/Q) + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = (1 + COSW0) / 2
    b1 = -(1 + COSW0)
    b2 = b0
    a0 = 1 + alpha
    a1 = -2 * COSW0
    a2 = 1 - alpha

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
def get_session_encoding_models(session_info, models=None):
    """
    Loops and computes traditional scores open-field scores for each unit, these include:
        -> speed score: correlation between firing rate and speed
        -> head angle score: correlation between firing rate and head angle
        -> head directation score: correlation between firing rate and head direction
        -> border score:
        -> spatial information:
        -> grid score:
    :param SubjectSessionInfo session_info: instance of class SubjectInfo for a particular subject
    :return: dict: with all the scores
    """
    # get data
    fr = session_info.get_fr()

    # smooth data to match behavior time smoothness
    sos_coefs = signal.tf2sos(session_info.task_params['filter_coef_'], 1)
    fr2 = signal.sosfiltfilt(sos_coefs, fr, axis=1)

    spikes = session_info.get_binned_spikes()
    of_dat = SimpleNamespace(**session_info.get_track_data())
    task_params = session_info.task_params

    sem = spatial_funcs.AllSpatialEncodingModels(x=of_dat.x,
                                                 y=of_dat.y,
                                                 speed=of_dat.sp,
                                                 ha=of_dat.ha,
                                                 hd=of_dat.hd,
                                                 neural_data=fr2,
                                                 n_jobs=10,
                                                 **task_params)
    if models is None:
        sem.get_models()
    else:
        if isinstance(models, str):
            models = [models]
        for model in models:
            model_method = f"get_{model}_model"
            if hasattr(sem, model_method):
                getattr(sem, model_method)()
            else:
                print(f"Encoding model for {model} does not exists.")

    sem.get_scores()
    return sem
Example #24
0
def printSos(order=12, oversample=5):
    for fraction in np.linspace(0, 1, oversample, endpoint=False)[1:]:
        print(fraction)
        b, a = thiran(order, order + fraction)
        sos = signal.tf2sos(b, a)
        print("{")
        for section in sos:
            text = "  {"

            for idx, value in enumerate(section):
                if idx == 3:
                    continue
                if idx != len(section) - 1:
                    text += f"Sample({value}), "
                else:
                    text += f"Sample({value})"
            print(text + "},")
        print("}")
Example #25
0
def lowShelf(w0, Q, A):
    #WROTE AND TESTED THIS FUNCTION, LEFT IT UNUSED IN FINAL IMPLEMENTATION
    #Low Shelf, modeled from:
    #H(s) = A * ((s^2 + sqrt(A)*s/Q + A) / (A*(s^2) + sqrt(A)*s/Q + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = A * ((A + 1) - (A - 1) * COSW0 + (2 * math.sqrt(A) * alpha))
    b1 = 2 * A * ((A - 1) - ((A + 1) * COSW0))
    b2 = A * ((A + 1) - (A - 1) * COSW0 - (2 * math.sqrt(A) * alpha))
    a0 = (A + 1) + ((A - 1) * COSW0) + (2 * math.sqrt(A) * alpha)
    a1 = -2 * ((A - 1) + ((A + 1) * COSW0))
    a2 = (A + 1) + ((A - 1) * COSW0) - (2 * math.sqrt(A) * alpha)

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #26
0
def bandpass(w0, Q):
    #WROTE THIS FUNCTION, LEFT IT UNUSED IN FINAL IMPLEMENTATION
    #BPF, modeled from:
    #H(s) = s / (s^2 + s/q + 1)
    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = Q * alpha  #= SINW0/2
    b1 = 0
    b2 = -b0
    a0 = a + alpha
    a1 = -2 * COSW0
    a2 = 1 - alpha

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #27
0
def lowpass(w0, Q):
    #LPF, modeled from:
    #H(s) = 1/(s^2 + s/Q + 1)

    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = (1 - COSW0) / 2
    b1 = 1 - COSW0
    b2 = b0
    a0 = 1 + alpha
    a1 = -2 * COSW0
    a2 = 1 - alpha

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
Example #28
0
    def signal(self):
        """
        Deliver the signal.

        Returns
        -------
        Array of floats
            The resulting signal as an array of length :attr:`~SignalGenerator.numsamples`.
        """
        rnd_gen = RandomState(self.seed)
        ma = self.handle_empty_coefficients(self.ma)
        ar = self.handle_empty_coefficients(self.ar)
        sos = tf2sos(ma, ar)
        ntaps = ma.shape[0]
        sdelay = round(0.5 * (ntaps - 1))
        wnoise = self.rms * rnd_gen.standard_normal(
            self.numsamples +
            sdelay)  # create longer signal to compensate delay
        return sosfilt(sos, x=wnoise)[sdelay:]
Example #29
0
def lowpass(w0, Q):
    #RETURNS SOS that can be used in SOSFILT
    #LPF
    #H(s) = 1/(s^2 + s/Q + 1)

    COSW0 = math.cos(w0)
    alpha = math.sin(w0) / (2 * Q)

    b0 = (1 - COSW0) / 2
    b1 = 1 - COSW0
    b2 = b0
    a0 = 1 + alpha
    a1 = -2 * COSW0
    a2 = 1 - alpha

    num = [b0, b1, b2]
    den = [a0, a1, a2]
    sos = signal.tf2sos(num, den)
    return sos
def band_pass_filter(signal, fs, start_freq, end_freq, margin_rate):
    """
    Description
     - High Pass Filter

    Input
     :param signal:list, 입력 신호
     :param fs: Float, 샘플링 주파수 (sampling frequency)
     :param start_freq: Float, 시작 주파수 (passband)
     :param end_freq: Float, 끝 주파수 (passband)
     :param margin_rate: Float, 마진율

    Output
     :return list, 필터링된 신호

    Example
     > signal = [0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1]
     > fs = 0.1
     > start_freq = 0.001
     > end_freq = 0.003
     > band_pass_filter(signal, fs, start_freq, end_freq, 0.08)
       [0.63095463  0.95862525  1.23888854  1.41245392  1.44684504  1.36618891
        1.22107957  1.05946482  0.92849059  0.87631723  0.92292086  1.02981141]
    """

    #
    fn = fs / 2
    wp = np.divide([start_freq, end_freq], fn)
    ws = np.divide([start_freq * margin_rate, end_freq / margin_rate], fn)

    n, wn = buttord(wp, ws, 1, 10)  # 'Butterworth Filter'의 차수(order) 구하기
    b, a = butter(n, wn, btype='band')  # 'Butterworth Filter'의 a와 b 파라메터 생성
    sos = tf2sos(b, a)

    signal = np.array(signal).reshape(-1)
    filtered_signal = sosfiltfilt(sos, signal)

    return filtered_signal
def output_filter(B, A, name, show_response = False, emit_test_ir = False, impulse_resp_length = 64):

	sos = signal.tf2sos(B, A)

	if show_response:
		B, A = signal.sos2tf(sos)
		w, h = signal.freqz(B, A, worN=2**12)
		plt.title('Digital filter frequency response')
		plt.semilogx(w*fs/(2.0*np.pi), 20 * np.log10(abs(h)), label = 'A_orig')
		plt.ylim(-50, 20)
		plt.ylabel('Amplitude [dB]', color='b')
		plt.xlabel('Frequency [rad/sample]')
		plt.grid()
		plt.show()

	filter_q = 31
	max_q_adjust = 0
	for bq in range(len(sos)):
		sos[bq] /= sos[bq][3]
		abs_sum = sum(abs(sos[bq])) - 1.0
		m = int(np.ceil(np.log2(abs_sum))) #TODO check this works for -ve abs_sums 
		max_q_adjust = max(max_q_adjust, m)

	max_q_adjust -= 1	#to take advantage of 64 bit maccs
	filter_q -= max_q_adjust

	#TODO check for -ve max_q_adjust

	sos_quantised = np.zeros(np.shape(sos))

	int_max = np.int64(int32_max) / 2**max_q_adjust
	print 'const int32_t filter_coeffs_' + name + '[] = {'
	for bq in range(len(sos)):
		print '\t',
		for i in range(3):
			v = np.int32(np.float64(int_max) * sos[bq][i])
			print str(v) + ', ' ,
			sos_quantised[bq][i] = np.float64(v) / np.float64(int_max)
		for i in range(4, 6):
			v = int(np.float64(int_max) * -sos[bq][i])
			sos_quantised[bq][i] = np.float64(-v) / np.float64(int_max)
			print str(v) + ', ' ,
		print
		sos_quantised[bq][3] = 1.0
	print '};'
	print 'const uint32_t num_sections_' + name + ' = ' + str(len(sos)) + ';'
	print 'const uint32_t q_format_' + name + ' = ' + str(filter_q) + ';'
	print 'int32_t filter_state_'+ name +'[' +str(len(sos)) + '*DSP_NUM_STATES_PER_BIQUAD] = {0};'
	d = np.zeros(impulse_resp_length)
	d[0] = 1

	B_q, A_q = signal.sos2tf(sos_quantised)
	filter_impulse_response =  signal.lfilter(B_q, A_q, d)

	if emit_test_ir:
		print 'const unsigned impulse_resp_length_' + name + ' = ' + str(impulse_resp_length)+';'
		print 'const int32_t expected_ir_' + name + '[' + str(impulse_resp_length) + '] = {'
		for i in range(impulse_resp_length):
			s = str(int(int32_max * filter_impulse_response[i])) + ', '
			if i%8 == 7:
				print s
			else:
				print s,
		print '};'

	return