コード例 #1
0
    def test_hilbert(self):
        # compare to MATLAB output of reference implementation

        # f=[0 0.3 0.5 1];
        # a=[1 1 0 0];
        # h=remez(11,f,a);
        h = remez(12, [0, 0.3, 0.5, 1], [1, 0], fs=2.)
        k = [
            0.349585548646686, 0.373552164395447, 0.326082685363438,
            0.077152207480935, -0.129943946349364, -0.059355880509749
        ]
        m = minimum_phase(h, 'hilbert')
        assert_allclose(m, k, rtol=5e-3)

        # f=[0 0.8 0.9 1];
        # a=[0 0 1 1];
        # h=remez(20,f,a);
        h = remez(21, [0, 0.8, 0.9, 1], [0, 1], fs=2.)
        k = [
            0.232486803906329, -0.133551833687071, 0.151871456867244,
            -0.157957283165866, 0.151739294892963, -0.129293146705090,
            0.100787844523204, -0.065832656741252, 0.035361328741024,
            -0.014977068692269, -0.158416139047557
        ]
        m = minimum_phase(h, 'hilbert', n_fft=2**19)
        assert_allclose(m, k, rtol=2e-3)
コード例 #2
0
    def test_homomorphic(self):
        # check that it can recover frequency responses of arbitrary
        # linear-phase filters

        # for some cases we can get the actual filter back
        h = [1, -1]
        h_new = minimum_phase(np.convolve(h, h[::-1]))
        assert_allclose(h_new, h, rtol=0.05)

        # but in general we only guarantee we get the magnitude back
        rng = np.random.RandomState(0)
        for n in (2, 3, 10, 11, 15, 16, 17, 20, 21, 100, 101):
            h = rng.randn(n)
            h_new = minimum_phase(np.convolve(h, h[::-1]))
            assert_allclose(np.abs(fft(h_new)), np.abs(fft(h)), rtol=1e-4)
コード例 #3
0
    def test_homomorphic(self):
        # check that it can recover frequency responses of arbitrary
        # linear-phase filters

        # for some cases we can get the actual filter back
        h = [1, -1]
        h_new = minimum_phase(np.convolve(h, h[::-1]))
        assert_allclose(h_new, h, rtol=0.05)

        # but in general we only guarantee we get the magnitude back
        rng = np.random.RandomState(0)
        for n in (2, 3, 10, 11, 15, 16, 17, 20, 21, 100, 101):
            h = rng.randn(n)
            h_new = minimum_phase(np.convolve(h, h[::-1]))
            assert_allclose(np.abs(np.fft.fft(h_new)),
                            np.abs(np.fft.fft(h)), rtol=1e-4)
コード例 #4
0
ファイル: fixes.py プロジェクト: nwilming/mne-python
def minimum_phase(h):
    """Convert a linear-phase FIR filter to minimum phase.

    Parameters
    ----------
    h : array
        Linear-phase FIR filter coefficients.

    Returns
    -------
    h_minimum : array
        The minimum-phase version of the filter, with length
        ``(length(h) + 1) // 2``.
    """
    try:
        from scipy.signal import minimum_phase
    except Exception:
        pass
    else:
        return minimum_phase(h)
    from scipy.fftpack import fft, ifft
    h = np.asarray(h)
    if np.iscomplexobj(h):
        raise ValueError('Complex filters not supported')
    if h.ndim != 1 or h.size <= 2:
        raise ValueError('h must be 1D and at least 2 samples long')
    n_half = len(h) // 2
    if not np.allclose(h[-n_half:][::-1], h[:n_half]):
        warnings.warn(
            'h does not appear to by symmetric, conversion may '
            'fail', RuntimeWarning)
    n_fft = 2**int(np.ceil(np.log2(2 * (len(h) - 1) / 0.01)))
    # zero-pad; calculate the DFT
    h_temp = np.abs(fft(h, n_fft))
    # take 0.25*log(|H|**2) = 0.5*log(|H|)
    h_temp += 1e-7 * h_temp[h_temp > 0].min()  # don't let log blow up
    np.log(h_temp, out=h_temp)
    h_temp *= 0.5
    # IDFT
    h_temp = ifft(h_temp).real
    # multiply pointwise by the homomorphic filter
    # lmin[n] = 2u[n] - d[n]
    win = np.zeros(n_fft)
    win[0] = 1
    stop = (len(h) + 1) // 2
    win[1:stop] = 2
    if len(h) % 2:
        win[stop] = 1
    h_temp *= win
    h_temp = ifft(np.exp(fft(h_temp)))
    h_minimum = h_temp.real
    n_out = n_half + len(h) % 2
    return h_minimum[:n_out]
コード例 #5
0
ファイル: fixes.py プロジェクト: adykstra/mne-python
def minimum_phase(h):
    """Convert a linear-phase FIR filter to minimum phase.

    Parameters
    ----------
    h : array
        Linear-phase FIR filter coefficients.

    Returns
    -------
    h_minimum : array
        The minimum-phase version of the filter, with length
        ``(length(h) + 1) // 2``.
    """
    try:
        from scipy.signal import minimum_phase
    except Exception:
        pass
    else:
        return minimum_phase(h)
    from scipy.fftpack import fft, ifft
    h = np.asarray(h)
    if np.iscomplexobj(h):
        raise ValueError('Complex filters not supported')
    if h.ndim != 1 or h.size <= 2:
        raise ValueError('h must be 1D and at least 2 samples long')
    n_half = len(h) // 2
    if not np.allclose(h[-n_half:][::-1], h[:n_half]):
        warnings.warn('h does not appear to by symmetric, conversion may '
                      'fail', RuntimeWarning)
    n_fft = 2 ** int(np.ceil(np.log2(2 * (len(h) - 1) / 0.01)))
    # zero-pad; calculate the DFT
    h_temp = np.abs(fft(h, n_fft))
    # take 0.25*log(|H|**2) = 0.5*log(|H|)
    h_temp += 1e-7 * h_temp[h_temp > 0].min()  # don't let log blow up
    np.log(h_temp, out=h_temp)
    h_temp *= 0.5
    # IDFT
    h_temp = ifft(h_temp).real
    # multiply pointwise by the homomorphic filter
    # lmin[n] = 2u[n] - d[n]
    win = np.zeros(n_fft)
    win[0] = 1
    stop = (len(h) + 1) // 2
    win[1:stop] = 2
    if len(h) % 2:
        win[stop] = 1
    h_temp *= win
    h_temp = ifft(np.exp(fft(h_temp)))
    h_minimum = h_temp.real
    n_out = n_half + len(h) % 2
    return h_minimum[:n_out]
コード例 #6
0
    def test_hilbert(self):
        # compare to MATLAB output of reference implementation

        # f=[0 0.3 0.5 1];
        # a=[1 1 0 0];
        # h=remez(11,f,a);
        h = remez(12, [0, 0.3, 0.5, 1], [1, 0], fs=2.)
        k = [0.349585548646686, 0.373552164395447, 0.326082685363438,
             0.077152207480935, -0.129943946349364, -0.059355880509749]
        m = minimum_phase(h, 'hilbert')
        assert_allclose(m, k, rtol=1e-3)

        # f=[0 0.8 0.9 1];
        # a=[0 0 1 1];
        # h=remez(20,f,a);
        h = remez(21, [0, 0.8, 0.9, 1], [0, 1], fs=2.)
        k = [0.232486803906329, -0.133551833687071, 0.151871456867244,
             -0.157957283165866, 0.151739294892963, -0.129293146705090,
             0.100787844523204, -0.065832656741252, 0.035361328741024,
             -0.014977068692269, -0.158416139047557]
        m = minimum_phase(h, 'hilbert', n_fft=2**19)
        assert_allclose(m, k, rtol=1e-3)
コード例 #7
0
def construct_fir_filter(rate, frequencies, gains, order, phase, window,
                         design):
    """ Construct coeffs of FIR filter.

    Args:
        rate (float): Nominal sampling rate of the input data.
        order (int): Filter order
        frequencies (list): Transition frequencies in Hz.
        design (str|'firwin2'): Design of the transfert function of the filter.
        phase (str|`linear`): Phase response ("zero", "zero-double" or "minimum").
        window (float|`hamming`): The window to use in FIR design, ("hamming", "hann", or "blackman").

    Returns:
        array h. FIR coeffs.

    Notes:

        Adapted from mne.filters, see the documentation of:

        * `mne.filters <https://martinos.org/mne/stable/generated/mne.filter.construct_fir_filter.html>`_
        * `scipy.signal.firwin2 <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.firwin2.html>`_



    """
    nyq = rate / 2.
    if design == 'firwin2':
        from scipy.signal import firwin2 as design
    else:
        # not implemented yet
        raise ValueError(
            'firwin, remez and firls have not been implemented yet ')

    # issue a warning if attenuation is less than this
    min_att_db = 12 if phase == 'minimum' else 20

    if frequencies[0] != 0 or frequencies[-1] != nyq:
        raise ValueError(
            'freq must start at 0 and end an Nyquist (%s), got %s' %
            (nyq, frequencies))
    gains = np.array(gains)

    if window == "kaiser":
        diffs = np.diff(frequencies)
        width = min(diffs[diffs > 0])
        beta = signal.kaiser_beta(signal.kaiser_atten(order, width / nyq))
        window = ("kaiser", beta)

    # check zero phase length
    N = int(order)
    if N % 2 == 0:
        if phase == 'zero':
            LOGGER.info('filter_length must be odd if phase="zero", '
                        'got %s' % N)
            N += 1
        elif phase == 'zero-double' and gains[-1] == 1:
            N += 1
    # construct symmetric (linear phase) filter
    if phase == 'minimum':
        h = design(N * 2 - 1, frequencies, gains, fs=rate, window=window)
        h = signal.minimum_phase(h)
    else:
        h = design(N, frequencies, gains, fs=rate, window=window)
    assert h.size == N
    att_db, att_freq = _filter_attenuation(h, frequencies, gains)
    if phase == 'zero-double':
        att_db += 6
    if att_db < min_att_db:
        att_freq *= rate / 2.
        LOGGER.info('Attenuation at stop frequency %0.1fHz is only %0.1fdB. '
                    'Increase filter_length for higher attenuation.' %
                    (att_freq, att_db))
    return h
コード例 #8
0
 def minphase(r):
     return signal.minimum_phase(r, method='hilbert', n_fft=8192)
コード例 #9
0
# whereby each sample :math:`t` is filtered only using time points that came
# after it.
#
# Note that the delay is variable (whereas for linear/zero-phase filters it
# is constant) but small in the pass-band. Unlike zero-phase filters, which
# require time-shifting backward the output of a linear-phase filtering stage
# (and thus becoming non-causal), minimum-phase filters do not require any
# compensation to achieve small delays in the pass-band. Note that as an
# artifact of the minimum phase filter construction step, the filter does
# not end up being as steep as the linear/zero-phase version.
#
# We can construct a minimum-phase filter from our existing linear-phase
# filter with the :func:`scipy.signal.minimum_phase` function, and note
# that the falloff is not as steep:

h_min = signal.minimum_phase(h)
plot_filter(h_min, sfreq, freq, gain, 'Minimum-phase', flim=flim)

# %%
# .. _tut-effect-on-signals:
#
# Applying FIR filters
# --------------------
#
# Now lets look at some practical effects of these filters by applying
# them to some data.
#
# Let's construct a Gaussian-windowed sinusoid (i.e., Morlet imaginary part)
# plus noise (random and line). Note that the original clean signal contains
# frequency content in both the pass band and transition bands of our
# low-pass filter.
コード例 #10
0
            rec_cfir_t = np.abs(lfilter(b_cfir_t, [1], x_test))[d:]

            corrs_fir[k, j] = np.corrcoef(rec_fir, tar)[0, 1]

            saf = SWAnalyticFilter2(fs, band, d * 2, n_fft)
            chunked = np.zeros((len(x_test), d * 2))
            for l in range(d * 2, len(x_test)):
                chunked[l, :] = x_test[l - 2 * d:l]

            rec_hilbert = np.abs(saf.apply(x_test))
            #rec = np.abs(saf.apply(x_test))[d:]
            corrs_hilbert[k, j] = np.corrcoef(rec_hilbert[d:], tar)[0, 1]
            if d > 0:
                tar1 = np.abs(y_test)
                b_fir_band = minimum_phase(
                    firwin(d, band / fs * 2, pass_zero=False))
                b_fir_smooth = minimum_phase(firwin(d, 2 / fs * 2))
                rec_fir = lfilter(b_fir_smooth, [1],
                                  np.abs(lfilter(b_fir_band, [1], x_test)))
                corr_delays = np.arange(1, 300)
                cross_corr = np.array([
                    np.corrcoef(tar1[:-d1], rec_fir[d1:])[0][1]
                    for d1 in corr_delays
                ])
                opt_delay = corr_delays[np.argmax(cross_corr)]
                min_phase_delays[k, j] = opt_delay
                corrs_min_phase[k, j] = np.max(cross_corr)

        else:
            tar = np.abs(y_test)[-d:]
            rec_cfir_f = np.abs(lfilter(b_cfir_f, [1], x_test))[:d]
コード例 #11
0
# Create an optimal linear-phase filter, then convert it to minimum phase:

from scipy.signal import remez, minimum_phase, freqz, group_delay
import matplotlib.pyplot as plt
freq = [0, 0.2, 0.3, 1.0]
desired = [1, 0]
h_linear = remez(151, freq, desired, Hz=2.)

# Convert it to minimum phase:

h_min_hom = minimum_phase(h_linear, method='homomorphic')
h_min_hil = minimum_phase(h_linear, method='hilbert')

# Compare the three filters:

fig, axs = plt.subplots(4, figsize=(4, 8))
for h, style, color in zip((h_linear, h_min_hom, h_min_hil), ('-', '-', '--'),
                           ('k', 'r', 'c')):
    w, H = freqz(h)
    w, gd = group_delay((h, 1))
    w /= np.pi
    axs[0].plot(h, color=color, linestyle=style)
    axs[1].plot(w, np.abs(H), color=color, linestyle=style)
    axs[2].plot(w, 20 * np.log10(np.abs(H)), color=color, linestyle=style)
    axs[3].plot(w, gd, color=color, linestyle=style)
for ax in axs:
    ax.grid(True, color='0.5')
    ax.fill_between(freq[1:3], *ax.get_ylim(), color='#ffeeaa', zorder=1)
axs[0].set(xlim=[0, len(h_linear) - 1], ylabel='Amplitude', xlabel='Samples')
axs[1].legend(['Linear', 'Min-Hom', 'Min-Hil'], title='Phase')
for ax, ylim in zip(axs[1:], ([0, 1.1], [-150, 10], [-60, 60])):
コード例 #12
0
fs = 500
t = np.arange(fs * 2) / fs
signal = ((np.sin(2 * np.pi * 10 * t) + 0.2) - 0.2 *
          (np.cos(2 * np.pi * 20 * t) + 0.25)) * np.sin(2 * np.pi * t * 3 / 4)
signal[(t < 1 / 3 * 2) | (t > 2 / 3 * 2)] = 0
noise_spec = np.fft.rfft(
    np.random.normal(size=2 * fs)) * 1 / (1 + np.arange(fs + 1)**1)
noise_spec[:10] = 0
noise = np.fft.irfft(noise_spec) * 12
x = signal + noise

n_taps = fs // 2
band = [8, 12]
freq = [0, band[0], band[0], band[1], band[1], fs / 2]
gain = [0, 0, 1, 1, 0, 0]
b1 = sg.minimum_phase(sg.firwin2(n_taps * 2, freq, gain, fs=fs))
b = sg.firwin2(n_taps, freq, gain, fs=fs)

y = sg.lfilter(b, 1, x)
y1 = sg.lfilter(b1, 1, x)
# plt.semilogy(*sg.welch(y))


def setup_gca(ax, bottom=False):
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['top'].set_visible(False)
    if bottom: ax.spines['bottom'].set_visible(False)
    ax.get_yaxis().set_visible(False)
    ax.set_ylim(-1.4, 1.4)
    #ax.get_xaxis().set_visible(False)
コード例 #13
0
"""plt.plot(time, audio_normalised)
plt.show()"""


def butter_highpass(cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
    return b, a


def butter_highpass_filter(data, cutoff, fs, order=5):
    b, a = butter_highpass(cutoff, fs, order=order)
    y = signal.filtfilt(b, a, data)
    return y


#Plot autocorrelation
def autocorr(x):
    x = butter_highpass_filter(x, 10, 1000)
    result = sg.correlate(x, x, mode='full', method="fft")
    return result


a = autocorr(audio_normalised)
"""plt.plot(range(0, len(a)//2+1), a[len(a)//2:]/a[len(a)//2])
plt.show()"""

ceps = minimum_phase(audio_normalised)
plt.plot(range(len(ceps)), ceps)
plt.show()
コード例 #14
0
ファイル: hrtf_writer.py プロジェクト: camlorn/libaudioverse
 def minphase(r):
     return signal.minimum_phase(r, method = 'hilbert', n_fft= 8192)