Search code examples
pythonaudiosignalssignal-processingchirp

How to remove the stationary noise from the chirp signal start from 50Hz to 10KHz using python


we have chirp signal starts from 50Hz and it goes up to 10Hkz with stationary noise mixed in the system output and would like to remove the stationary noise mixed with chirp and to retain original chirp signal(data) and any suggestions would be welcome using python, thanks.

filter/stationary noise reduction approach for the chirp signal (50hz to 10Khz) using python.


Solution

  • Here is some code that demonstrates what I suggested in my comment:

    import scipy.signal
    import numpy as np
    import matplotlib.pyplot as plt
    
    t = np.linspace(0,5, 44100*5)
    w = scipy.signal.chirp(t, f0=50, f1=10000, t1=5, method='linear')
    mu, sigma = 0, .1
    s = np.random.normal(mu, sigma,len(t))
    sig = w+s
    n = 0
    win_len = 512
    hop = 64
    win = np.hanning(win_len)
    denoised = np.zeros([len(t)])
    while n<len(t):
        if n+win_len > len(t):
            # zero pad if we run out of samples
            input = np.zeros([win_len])
            end_pt = len(t)-n-1
            for i in range(0,end_pt):
                input[i]+=sig[n+i]
        else:
            input = sig[n:n+win_len]
        input = input * win # window the signal
        dft = np.fft.fft(input)
        mags = abs(dft)
    
        ft_idx = 0
        # zero out the bins that are only noise
        zero = np.zeros(1, dtype=complex)
        for m in mags:
            if m<40:
                dft[ft_idx] = zero[0]
            ft_idx +=1 
        output = win*np.real(np.fft.ifft(dft))/(win_len/hop)# since the input is real,
        # the idft of the fft will also be real
        # we must take care to also window the idft so
        # that the overlap add is smooth
    
        # take care not to overflow
        if n+win_len > len(t):
            end_pt = len(t)-n-1
            for i in range(0,end_pt):
                denoised[n+i]+=output[i]
        else:
            denoised[n:n+win_len] += output
        n+=hop
    plt.plot(t[0:5000], sig[0:5000])
    plt.plot(t[0:5000], denoised[0:5000])
    plt.show()
    

    Output: enter image description here

    Obviously it is not perfect. For one thing, the signal we keep is both attenuated (due to the brute force thresholding in the magnitude spedtrum) and the peak amplitudes are warbly (a byproduct of the random noise that we keep in the bins we do not attenuate). More work would be needed to get rid of those effects.