0
$\begingroup$

I would like to compute a sweeping cutoff filter. I wish to use SciPy. I sliced my wave into x samples slices, in order to apply a different cutoff to each such created "frame". The problem is that the filter, when applied to a slice filters the "clic" at the start of the slice, which creates an artefact for regathered result. I searched stackexchange all over for sweeping filters questions and found nothing. Any Idea on how to get a smooth sweeping without clic?

    #for filter
    from scipy.signal import butter, buttord, lfilter, freqz
    from scipy.signal import freqs

    def truncate_if_outside(data, bitwidth):
        if bitwidth==2:
            max_sample_value=32767
            min_sample_value=-32767
        else:
            print "Only 16 bit accepted by truncate_if_outside function"
    

        for i in range(len(data)):  
            if data[i]>max_sample_value:
                data[i]=max_sample_value;
            if data[i]<min_sample_value:
                data[i]=min_sample_value;
            if math.isnan(data[i]):
                data[i]=0
            data[i]=int(data[i])
            if math.isnan(data[i]):
                data[i]=0
        return data


    def lowpass_filter(integer_data, sample_framerate, sample_bitwidth,threshold):#works with cutoff from 400 and higher

        def butter_lowpass(cutOff, fs, order):
    
            nyq = 0.5 * fs
            normalCutoff = cutOff / nyq
            b, a = butter(order, normalCutoff, btype='low', analog = False)
            return b, a
    
        def butter_lowpass_filter(data, cutOff, fs, order):
            b, a = butter_lowpass(cutOff, fs, order=order)
            y = lfilter(b, a, data)
            return y
    
        result=butter_lowpass_filter(integer_data, threshold, sample_framerate, order=4)#what is order?
        result=truncate_if_outside(result, sample_bitwidth)
        return result

    def sweep_filter(integer_data, start_freq, end_freq, sample_framerate, sample_bitwidth, slice_width):
        num_slice= int(len(integer_data)/ float(slice_width))
        print "nombre de tranche dans cette durée :",num_slice
        new_data=[]
        diff_cutoff=end_freq-start_freq
        for i in range(num_slice):
            current_cutoff=start_freq+((i/float(num_slice))*diff_cutoff)
            print "cutoff",current_cutoff
            print "start:",i*slice_width
            offset_first_sample=(i*slice_width)-1
            offset_last_sample=((i*slice_width)+slice_width)-1

            slice_data=integer_data[offset_first_sample:offset_last_sample]
            slice_data=lowpass_filter(slice_data, sample_framerate, sample_bitwidth, current_cutoff)
            for j in range(len(slice_data)):
                new_data.append(slice_data[j])
        return new_data

Sweep clic signal image

The here filtered signal is a "smoothed noise" which means a random numbers smoothed with exponential curves. There should be no gap in it.

$\endgroup$
1
$\begingroup$

To create a smooth sweeping filter or envelope filter, you can process as in video by "frame". You plan a 30% overlap of each frame with a crossfade. You need to generate two tracks and mix them together to do that.

$\endgroup$
3
  • $\begingroup$ or you can gradually adjust the coefficients, a little with each sample. $\endgroup$ – robert bristow-johnson Jun 26 '18 at 18:45
  • $\begingroup$ finally 100% overlap works better $\endgroup$ – Raphaël Poli Jul 3 '18 at 14:06
  • $\begingroup$ robert: is it possible to filter with a frame of one sample? are you sure? it seems bizarre to me as to detect a frequency there need to be a wave! $\endgroup$ – Raphaël Poli Jul 3 '18 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.