예제 #1
0
파일: signal.py 프로젝트: mschachter/LaSP
def bandpass_filter(s,
                    sample_rate,
                    low_freq,
                    high_freq,
                    filter_order=5,
                    rescale=False):
    """
        Bandpass filter a signal s.

        s: the signal
        sample_rate: the sample rate in Hz of the signal
        low_freq: the lower cutoff frequency
        upper_freq: the upper cutoff frequency
        filter_order: the order of the filter...

        Returns the bandpass filtered signal s.
    """

    #create a butterworth filter
    nyq = sample_rate / 2.0
    f = np.array([low_freq, high_freq]) / nyq
    b, a = filter_design.butter(filter_order, f, btype='bandpass')

    #filter the signal
    filtered_s = filtfilt(b, a, s)

    if rescale:
        #rescale filtered signal
        filtered_s /= filtered_s.max()
        filtered_s *= s.max()

    return filtered_s
예제 #2
0
def lowpass(data, in_t, cutoff, order=4):
    """
    data: vector of data
    in_t: sample times
    cutoff: cutoff period in the same units as in_t

    returns vector same as data, but with high frequencies removed
    """

    # Step 1: Determine dt from data (complicated due to TRIM time series precision legacy)
    mean_dt = mean(diff(in_t))

    # print 'Data Time Step: %8.4f'%mean_dt

    # test size of data for vectors only

    Wn = mean_dt / cutoff  # 90 = half # of minutes in 3 hours.

    # print 'Using %1ith Order Butterworth Filter, with %g time-unit cutoff (Wn=%12.6f).'%(order,2*cutoff,Wn)

    B, A = butter(order, Wn)

    data_filtered = filtfilt(B, A, data)

    return data_filtered
예제 #3
0
def lowpass(data,
            in_t=None,
            cutoff=None,
            order=4,
            dt=None,
            axis=-1,
            causal=False):
    """
    data: vector of data
    in_t: sample times
    cutoff: cutoff period in the same units as in_t

    returns vector same as data, but with high frequencies removed
    """

    # Step 1: Determine dt from data or from user if specified
    if dt is None:
        dt = np.median(np.diff(in_t))
    dt = float(dt)  # make sure it's not an int
    cutoff = float(cutoff)

    Wn = dt / cutoff

    B, A = butter(order, Wn)

    if not causal:
        # scipy filtfilt triggers some warning message about tuple
        # indices.
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            data_filtered = filtfilt(B, A, data, axis=axis)
    else:
        data_filtered = lfilter(B, A, data, axis=axis)

    return data_filtered
예제 #4
0
def lowpass(data, in_t, cutoff, order=4):
    """
    data: vector of data
    in_t: sample times
    cutoff: cutoff period in the same units as in_t

    returns vector same as data, but with high frequencies removed
    """

    # Step 1: Determine dt from data (complicated due to TRIM time series precision legacy)
    mean_dt = mean(diff(in_t))

    # print 'Data Time Step: %8.4f'%mean_dt

    # test size of data for vectors only

    Wn = mean_dt / cutoff  # 90 = half # of minutes in 3 hours.

    # print 'Using %1ith Order Butterworth Filter, with %g time-unit cutoff (Wn=%12.6f).'%(order,2*cutoff,Wn)

    B, A = butter(order, Wn)

    data_filtered = filtfilt(B, A, data)

    return data_filtered
예제 #5
0
파일: signal.py 프로젝트: mschachter/LaSP
def bandpass_filter(s, sample_rate, low_freq, high_freq, filter_order=5, rescale=False):
    """
        Bandpass filter a signal s.

        s: the signal
        sample_rate: the sample rate in Hz of the signal
        low_freq: the lower cutoff frequency
        upper_freq: the upper cutoff frequency
        filter_order: the order of the filter...

        Returns the bandpass filtered signal s.
    """


    #create a butterworth filter
    nyq = sample_rate / 2.0
    f = np.array([low_freq, high_freq]) / nyq
    b,a = filter_design.butter(filter_order, f, btype='bandpass')

    #filter the signal
    filtered_s = filtfilt(b, a, s)

    if rescale:
        #rescale filtered signal
        filtered_s /= filtered_s.max()
        filtered_s *= s.max()

    return filtered_s
예제 #6
0
파일: signal.py 프로젝트: mschachter/LaSP
def highpass_filter(s,
                    sample_rate,
                    cutoff_freq,
                    filter_order=5,
                    rescale=False):
    """
        Highpass filter a signal s, with sample rate sample_rate.

        s: the signal
        sample_rate: the sample rate in Hz of the signal
        cutoff_freq: the cutoff frequency of the filter
        filter_order: the order of the filter...

        Returns the low-pass filtered signal s.
    """

    #create a butterworth filter
    nyq = sample_rate / 2.0
    b, a = filter_design.butter(filter_order, cutoff_freq / nyq, btype='high')

    #filter the signal
    filtered_s = filtfilt(b, a, s)

    if rescale:
        #rescale filtered signal
        filtered_s /= filtered_s.max()
        filtered_s *= s.max()

    return filtered_s
예제 #7
0
def lpFiltSpec(fp, fs, nyqf):
    nyqf = float(nyqf)
    ord, wn = filter_design.buttord(fp / nyqf, fs / nyqf, 1, 12, analog=0)
    b, a = butter(ord, wn, btype="lowpass", analog=0, output='ba')
    w, h = freqz(b, a)
    fig = _plt.figure()
    _plt.plot(w * (nyqf / _N.pi), _N.abs(h))
예제 #8
0
파일: signal.py 프로젝트: mschachter/LaSP
def highpass_filter(s, sample_rate, cutoff_freq, filter_order=5, rescale=False):
    """
        Highpass filter a signal s, with sample rate sample_rate.

        s: the signal
        sample_rate: the sample rate in Hz of the signal
        cutoff_freq: the cutoff frequency of the filter
        filter_order: the order of the filter...

        Returns the low-pass filtered signal s.
    """

    #create a butterworth filter
    nyq = sample_rate / 2.0
    b,a = filter_design.butter(filter_order, cutoff_freq / nyq, btype='high')

    #filter the signal
    filtered_s = filtfilt(b, a, s)

    if rescale:
        #rescale filtered signal
        filtered_s /= filtered_s.max()
        filtered_s *= s.max()

    return filtered_s
예제 #9
0
def butter_bandpass_filter_two(data, lowcut, highcut, fs, order=5):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    y = lfilter(b, a, data)
    return y
예제 #10
0
파일: filters.py 프로젝트: wefleenor/stompy
def lowpass(data,
            in_t=None,
            cutoff=None,
            order=4,
            dt=None,
            axis=-1,
            causal=False):
    """
    data: vector of data
    in_t: sample times
    cutoff: cutoff period in the same units as in_t

    returns vector same as data, but with high frequencies removed
    """

    # Step 1: Determine dt from data
    dt = dt or np.median(np.diff(in_t))
    dt = float(dt)
    cutoff = float(cutoff)

    Wn = dt / cutoff

    B, A = butter(order, Wn)

    if not causal:
        data_filtered = filtfilt(B, A, data, axis=axis)
    else:
        data_filtered = lfilter(B, A, data, axis=axis)

    return data_filtered
예제 #11
0
def envelope(signal, fs, env_cutoff=16., env_order=4., full_rect=False):
    '''Extracts the amplitude envelope from a signal using rectification and low-pass filtering
    
        Parameters
        ----------
        signal : array
            The signal to extract the amplitude envelope from
        fs : scalar
            The sampling frequency
        env_cutoff : scalar
            The envelope cutoff frequency [default=16 Hz]
        env_order : scalar
            The order of the envelope filter [must be even number; default=6]
        full_rect : bool
            True for full-wave rectification [default=half-wave rectification]
        
        Returns
        -------
        env : array
            The amplitude envelope of the input signal
    '''
    signal = signal - np.mean(signal) # Remove DC component

    if full_rect:
        rect = np.absolute(signal)
    else:
        rect = np.maximum(signal,0)
    env_b,env_a = filters.butter(env_order/2.,np.float32(env_cutoff)/(np.float32(fs)/2.))
    env = filtfilt(env_b,env_a,rect)

    return env
예제 #12
0
def bpFilt(fpL, fpH, fsL, fsH, nyqf, y):
    nyqf = float(nyqf)
    ord, wn = filter_design.buttord((fpL / nyqf, fpH / nyqf),
                                    (fsL / nyqf, fsH / nyqf),
                                    1,
                                    12,
                                    analog=0)
    b, a = butter(ord, wn, btype="bandpass", analog=0, output='ba')
    fy = filtfilt(b, a, y)
    return fy
예제 #13
0
 def band_pass_filter(self, wavFile):
     rate, sound_samples = read(wavFile)  # f , fs
     sound_samples = np.float64(sound_samples / 32768.0)
     n = 7
     beginFreq = 700.0 / (rate / 2)
     endFreq = 12000.0 / (rate / 2)
     [b, a] = butter(n, [beginFreq, endFreq], 'bandpass')
     filtered = lfilter(b, a, sound_samples)
     filtered = np.int16(filtered * 32768 * 10)
     write(self.__filteredFile, rate, filtered)
     return self.__filteredFile
예제 #14
0
def bpFiltSpec(fpL, fpH, fsL, fsH, nyqf):
    nyqf = float(nyqf)
    ord, wn = filter_design.buttord((fpL / nyqf, fpH / nyqf),
                                    (fsL / nyqf, fsH / nyqf),
                                    1,
                                    12,
                                    analog=0)
    b, a = butter(ord, wn, btype="bandpass", analog=0, output='ba')
    w, h = freqz(b, a)
    fig = _plt.figure()
    _plt.plot(w * (nyqf / _N.pi), _N.abs(h))
예제 #15
0
def lowpass(signal, order, cutoff, sr):
    b, a = butter(order, cutoff / (sr / 2))
    filteredSignal = nans(shape(signal))

    if len(signal) <= 3 * max(len(a), len(b)):
        print "signal too short to be lowpassed: " + str(len(signal))
        return nans(shape(signal))

    for i in range(shape(signal)[1]):
        filteredSignal[:, i] = filtfilt(b, a, signal[:, i])

    return filteredSignal
예제 #16
0
 def low_filter(self, wavFile):
     rate, sound_samples = read(wavFile)
     sound_samples = np.float64(sound_samples / 32768.0)
     pass_freq = 0.2
     stop_freq = 0.3
     pass_gain = 0.5  # permissible loss (ripple) in passband (dB)
     stop_gain = 10.0  # attenuation required in stopband (dB)
     ord, wn = buttord(pass_freq, stop_freq, pass_gain, stop_gain)
     b, a = butter(ord, wn, btype='low')
     filtered = lfilter(b, a, sound_samples)
     filtered = np.int16(filtered * 32768 * 10)
     write(self.__filteredFile, rate, filtered)
     return self.__filteredFile
예제 #17
0
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    """
    Runs a Butterworth bandpass filter on sound data

    :param data: sound data to filter
    :param lowcut: the lowest frequency to accept
    :param highcut: the highest frequency to accept
    :param fs: sampling frequency
    :param order: the order of the filter
    """
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    y = lfilter(b, a, data)
    return y
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    """
    Runs a Butterworth bandpass filter on sound data

    :param data: sound data to filter
    :param lowcut: the lowest frequency to accept
    :param highcut: the highest frequency to accept
    :param fs: sampling frequency
    :param order: the order of the filter
    """
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    y = lfilter(b, a, data)
    return y
예제 #19
0
def butter_pass(cutoff, fs, order=5, btype="low"):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = butter(order, normal_cutoff, btype=btype, analog=False)
    return b, a
예제 #20
0
def butter_bp(lo=0, hi=0, Fs=2.0, ord=3):

    # note: "lo" corresponds to highpass cutoff
    #       "hi" corresponds to lowpass cutoff
    freqs, btype = _bandpass_params(lo, hi)
    return fdesign.butter(ord, 2 * freqs / Fs, btype=btype)
예제 #21
0
def butter_bandpass(lowcut, highcut, fs, order=9):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a
예제 #22
0
      format(data_wav.shape[0] / fs_wav))

duration = (data_wav.shape[0] / fs_wav)
print(duration, " Duration")
count_minutes = int(duration/60)
print(count_minutes, " minutes")
bpm=[]
for j in range(1,count_minutes+1):
	print(j,"th iteration")
	data_wav_norm = copy.deepcopy(data_wav)
	data_wav_norm = data_wav_norm[(j-1)*60 * fs_wav: (j)*60 * fs_wav]
	time_wav = np.arange(0, len(data_wav_norm)) / fs_wav


	# Applying Low-pass Butter filter
	b, a = butter(3, 0.9/(fs_wav*0.5), btype = 'low', analog=False)
	filtered = lfilter(b, a, data_wav_norm)
	data_wav_lp = filtered
	print(len(data_wav_lp), "Length")
	data_wav_lp = data_wav_lp/ (2**15)


	#Applying hilbert Transformation to get envelope of the signal
	analytic_signal = hilbert(data_wav_lp)
	amplitude_envelope = np.abs(analytic_signal)
	instantaneous_phase = np.unwrap(np.angle(analytic_signal))


	#getting Properties of the envelope
	peaks, prop = find_peaks(amplitude_envelope,height=[0,0.2], distance=5000)
	peak_graph = prop["peak_heights"]
예제 #23
0
파일: f0.py 프로젝트: cbrown1/psylab
def f0(sig, fs, noisegate=15):
    '''Estimates the fundamental frequency of a signal
        
        Returns an array of estimated instantaneous fundamental frequency 
        (F0) values based on zeros crossings in the input signal. 
        
        Parameters
        ----------
        sig : array
            The input signal.
        fs : array
            The sampling frequency.
        
        Returns
        -------
        y : array
            The pitch track.
    '''

    # Low-pass at 270 Hz (above most F0's)
    b, a = filters.butter(4, 270. / (fs / 2.))
    fsig = filtfilt(b, a, sig)
    b, a = filters.butter(4, 60. / (fs / 2.), btype='high')
    fsig = filtfilt(b, a, fsig)
    # Get zero crossings
    zc = np.array(
        np.where(np.sign(fsig[1:]) != np.sign(fsig[:-1]))).transpose()[:, 0]
    # Compute period at each crossing
    # (actually half-period, since a full period is 2 zero crossings)
    zc2 = np.concatenate((zc, np.zeros((1))))
    zc3 = np.concatenate((np.zeros((1)), zc))
    p = zc2 - zc3
    p[-1] = p[-2]
    # Create new array of periods @ fs
    pfs = np.zeros(fsig.shape)
    # Resample period data (aliased)
    for k in range(zc.shape[0] - 1):
        pfs[zc[k]:zc[k + 1]] = p[k]
    pfs[0:zc[0]] = p[0]
    pfs[zc[-1]:] = p[-2]
    # Convert instantaneous period data to instantaneous frequency data
    ps = ((pfs / (fs / 1000.)) / 1000.)
    # The 2 here corrects for the half-period issue above
    f = (1. / ps) / 2.
    # Smooth the F0 track
    b, a = filters.butter(1, 16. / (fs / 2.))
    f = filtfilt(b, a, f)

    # Voicing
    env = envelope(fsig, fs)
    env = env / np.max(np.abs(env))
    # Noise gate
    env[20 * np.log10(env) < -noisegate] = 0
    env[env > 0] = 1
    #    env2 = env
    #    vonsets = array(where(sign(env[1:]) < sign(env[:-1]))).transpose()[:,0]
    #    print vonsets
    #    print vonsets + vdelay - 1
    #    skip = True
    #    for k in range(vonsets.shape[0]):
    #        if (skip):
    #            env2[vonsets[k]:vonsets[k] + vdelay - 1] = 0
    #            skip = False
    #        else:
    #            skip = True
    # Smooth the transitions
    b, a = filters.butter(1, 16. / (fs / 2.))
    envf = filtfilt(b, a, env)

    return f * np.maximum(envf, 0)
예제 #24
0
                    if((n-k)>= len(int_resp)):
                        temp += 0
                    else:
                        temp += data_buffer[k%64]*int_resp[n-k]
            data_dump[n%64] = temp;
                        
    
f = open('sample_vishwa.dat', 'r')
data = []
for i in f.readlines():
    data.append(int(i))
data_test = zeros(len(data))
data_test[0] = 1
order, Wn = fd.buttord(0.2, 0.3, 1, 10)
print order, Wn
b, a = fd.butter(order, Wn)
response = sg.lfilter(b, a, data_test)[:256]
int_resp = []
resp_file = open('impulse_response_integer.dat', 'r')
for i in resp_file.readlines():
    int_resp.append(int(i))
#op1 = conv(data[:1024], int_resp)
f.close()
op2 = range(1024)
conv(data)
op1 = convolve(int_resp, data)
clf()
plot(op1, 'r')
plot(op2)
show()
    
예제 #25
0
def hpFilt(fp, fs, nyqf, y, disp=False):
    nyqf = float(nyqf)
    ord, wn = filter_design.buttord(fp / nyqf, fs / nyqf, 1, 12, analog=0)
    b, a = butter(ord, wn, btype="highpass", analog=0, output='ba')
    fy = filtfilt(b, a, y)
    return fy
예제 #26
0
def butterworth(ts, cutoff_period=None, cutoff_frequency=None, order=4):
    """ low-pass butterworth-squared filter on a regular time series.
      
        
    Parameters
    -----------
    
    
    ts : :class:`DataFrame <pandas:pandas.DataFrame>`
        Must be one or two dimensional, and regular.
    
    order: int ,optional
        The default is 4.
        
    cutoff_frequency: float,optional
        Cutoff frequency expressed as a ratio with Nyquist frequency,
        should within the range (0,1). For a discretely sampled system,
        the Nyquist frequency is the fastest frequency that can be resolved by that 
        sampling, which is half the sampling frequency. For example, if the sampling frequency
        is 1 sample/1 hour, the Nyquist frequency is 1 sample/2 hours. If we want a
        36 hour cutoff period, the frequency is 1/36 or 0.0278 cycles per hour. 
        Hence the cutoff frequency argument used here would be
        0.0278/0.5 = 0.056.
                      
    cutoff_period : string  or  :ref:`time_interval<time_intervals>`
         Period corresponding to cutoff frequency. If input as a string, it must 
         be  convertible to a regular interval using the same rules as a pandas frequency..
         cutoff_frequency and cutoff_period can't be specified at the same time.
           
    Returns
    -------
    result : 
        A new regular time series with the same interval as ts.
        
    Raise
    --------
    ValueError
        If input order is not even, or input timeseries is not regular, 
        or neither cutoff_period and cutoff_frequency is given while input
        time series interval is not 15min or 1 hour, or  cutoff_period and cutoff_frequency 
        are given at the same time.
        
    """

    if (order % 2):
        raise ValueError("only even order is accepted")

    #if not ts.is_regular():
    #    raise ValueError("Only regular time series can be filtered.")

    freq = ts.index.freq

    #    if (not (interval in _butterworth_interval)) and (cutoff_period is None) and (cutoff_frequency is None):
    #        raise ValueError("time interval is not supported by butterworth if no cuttoff period/frequency given.")

    if (not (cutoff_frequency is None)) and (not (cutoff_period is None)):
        raise ValueError(
            "cutoff_frequency and cutoff_period can't be specified simultaneously"
        )

    if (cutoff_frequency is None) and (cutoff_period is None):
        raise ValueError(
            "Either cutoff_frequency or cutoff_period must be given")

    cf = cutoff_frequency

    if (cf is None):
        if (not (cutoff_period is None)):
            cutoff_period = pd.tseries.frequencies.to_offset(cutoff_period)
            cf = 2. * freq / cutoff_period
        else:
            cf = butterworth_cutoff_frequencies[interval]

    ## get butter filter coefficients.
    [b, a] = butter(order / 2, cf)
    d2 = filtfilt(b, a, ts.values, axis=0, padlen=90)
    out = ts.copy(deep=True)
    out[:] = d2

    #    prop={}
    #    for key,val in ts.props.items():
    #        prop[key]=val
    #    prop[TIMESTAMP]=INST
    #    prop[AGGREGATION]=INDIVIDUAL
    #    time_interval
    return out
예제 #27
0
def butterworth(ts, order=4, cutoff_period=None, cutoff_frequency=None):
    """ low-pass butterworth-squared filter on a regular time series.
      
        
    Parameters
    -----------
    
    
    ts : :class:`~vtools.data.timeseries.TimeSeries`
        Must has data of one dimension, and regular.
    
    order: int ,optional
        The default is 4.
        
    cutoff_frequency: float,optional
        Cutoff frequency expressed as a ratio of a Nyquist frequency,
        should within the range (0,1). For example, if the sampling frequency
        is 1 hour, the Nyquist frequency is 1 sample/2 hours. If we want a
        36 hour cutoff period, the frequency is 1/36 or 0.0278 cycles per hour. 
        Hence the cutoff frequency argument used here would be
        0.0278/0.5 = 0.056.
                      
    cutoff_period : string  or  :ref:`time_interval<time_intervals>`
         Period of cutting off frequency. If input as a string, it must 
         be  convertible to :ref:`Time interval<time_intervals>`.
         cutoff_frequency and cutoff_period can't be specified at the same time.
           
    Returns
    -------
    result : :class:`~vtools.data.timeseries.TimeSeries`
        A new regular time series with the same interval of ts.
        
    Raise
    --------
    ValueError
        If input order is not even, or input timeseries is not regular, 
        or neither cutoff_period and cutoff_frequency is given while input
        time series interval is not 15min or 1 hour, or  cutoff_period and cutoff_frequency 
        are given at the same time.
        
    """

    if (order % 2):
        raise ValueError("only even order is accepted")

    if not ts.is_regular():
        raise ValueError("Only regular time series can be filtered.")

    interval = ts.interval

    if (not (interval in _butterworth_interval)) and (
            cutoff_period is None) and (cutoff_frequency is None):
        raise ValueError(
            "time interval is not supported by butterworth if no cuttoff period/frequency given."
        )

    if (not (cutoff_frequency is None)) and (not (cutoff_period is None)):
        raise ValueError(
            "cutoff_frequency and cutoff_period can't be specified simultaneously"
        )

    cf = cutoff_frequency
    if (cf is None):
        if (not (cutoff_period is None)):
            ## convert it to ticks
            if not (is_interval(cutoff_period)):
                cutoff_period = parse_interval(cutoff_period)
            cutoff_frequency_in_ticks = 1.0 / float(ticks(cutoff_period))
            nyquist_frequency = 0.5 / float(ticks(interval))
            cf = cutoff_frequency_in_ticks / nyquist_frequency
        else:
            cf = butterworth_cutoff_frequencies[interval]

    ## get butter filter coefficients.
    [b, a] = butter(order / 2, cf)
    #    d1=lfilter(b, a, ts.data,0)
    #    d1=d1[len(d1)::-1]
    #    d2=lfilter(b,a,d1,0)
    #    d2=d2[len(d2)::-1]
    d2 = filtfilt(b, a, ts.data, axis=0)

    prop = {}
    for key, val in ts.props.items():
        prop[key] = val
    prop[TIMESTAMP] = INST
    prop[AGGREGATION] = INDIVIDUAL
    time_interval
    return rts(d2, ts.start, ts.interval, prop)
예제 #28
0
def vocoder_overlap(signal, fs, channel_n, channel_width, flo, fhi):
    '''Prototype vocoder where channel width is independent of channel spacing

        That is, channels are not necessarily contiguous

        The channel_width parameter is in octaves, and channel cfs are
        logarithmically spaced from flo to fhi

        E.g., the following set of parameters would yield contiguous bands from 88 to 11314 Hz:
        psylab.signal.vocoder_overlap(sig,fs,6,1,125,8000)

        vocoder_overlap(signal, fs, channel_n, channel_width, flo, fhi)
    '''
    signal = signal - np.mean(signal)
    cfs = np.float32(np.round(np.linspace(flo, fhi, channel_n)))
    cfs = logspace(flo, fhi, channel_n)

    cw = np.float32(channel_width / 2.)
    nyq = np.float32(fs / 2.)
    envfilter = 400.
    print("Channel width: {:} Oct".format(channel_width))
    noisecarrier = np.random.randn(len(signal))
    noisecarrier = noisecarrier / max(np.abs(noisecarrier))
    summed_carriers = np.zeros(len(signal))

    for cf in cfs:
        lo = np.round(cf * (2.**-cw))
        hi = np.round(cf * (2.**cw))

        print("  lo {:}; cf {:}; hi {:}".format(lo, cf, hi))

        [b_band_hp, a_band_hp] = filters.butter(3, (lo / nyq), btype='high')
        [b_band_lp, a_band_lp] = filters.butter(3, (hi / nyq))

        [b_wind_hp, a_wind_hp] = filters.butter(1, (cf / nyq), btype='high')
        [b_wind_lp, a_wind_lp] = filters.butter(1, (cf / nyq))

        [b_env, a_env] = filters.butter(2,
                                        min((.5 * (hi - lo)), envfilter) / nyq)

        # Filter signal into sub-band
        Sig_band = lfilter(b_band_hp, a_band_hp, signal)
        Sig_band = lfilter(b_band_lp, a_band_lp, Sig_band)

        # Apply window to shape band
        Sig_band = lfilter(b_wind_hp, a_wind_hp, Sig_band)
        Sig_band = lfilter(b_wind_lp, a_wind_lp, Sig_band)

        # Extract envelope
        rms_Sig_band = np.sqrt(np.mean(Sig_band**2))
        Sig_env_band = lfilter(b_env, a_env, np.maximum(Sig_band, 0))

        # Prefilter, modulate carrier
        Mod_carrier = filtfilt(b_band_hp, a_band_hp, noisecarrier)
        Mod_carrier = filtfilt(b_band_lp, a_band_lp,
                               Mod_carrier) * Sig_env_band

        # Post filter
        Mod_carrier_filt = lfilter(b_band_hp, a_band_hp, Mod_carrier)
        Mod_carrier_filt = lfilter(b_band_lp, a_band_lp, Mod_carrier_filt)
        summed_carriers += Mod_carrier / np.sqrt(np.mean(Mod_carrier**
                                                         2)) * rms_Sig_band
    return summed_carriers * (np.sqrt(np.mean(signal**2)) /
                              np.sqrt(np.mean(summed_carriers**2)))
예제 #29
0
def vocoder(signal, fs, channels, inlo, inhi, **kwargs):
    '''Implements an envelope vocoder

        Vocodes the input signal using specified parameters.

        You can specify a different frequency range for both input
        (analysis) and output, for a given number of channels (the output
        frequency range values default to input values). Both input and output
        channels are distributed contiguously on a log scale across the
        respective frequency ranges. Carriers can be pure tones (at the
        arithmetic center of each band) or noise bands (which are as wide as
        the output channel). The envelope cutoff frequency defaults to 400 Hz,
        but is never more than half the output-channel bandwidth.

        Parameters
        ----------
        signal : array
            The input signal
        fs : scalar
            The sampling frequency
        channels : scalar
            The number of vocoder channels
        inlo : scalar
            Low-side (start) frequency of the analysis channels
        inhi : scalar
            High-side (end) frequency of the analysis channels

        Kwargs
        ------
        outlo : scalar
            Low-side (start) frequency of the output channels [ default = inlo ]
        outhi : scalar
            High-side (end) frequency of the output channels [ default = inhi ]
        compression_ratio : scalar
            Compression ration: input / output [ default = 1 ]
        gate : scalar
            A gate to apply to each envelope. Values below gate are set to 0 [ default = 0 ]
        envfilter : scalar
            Low-pass cutoff frequency of the envelope extraction filter [ default = 400 ]
        noise : bool
            False for sinusoidal carriers [ default ]
            True for noise band carriers
        sumchannels : bool
            False to return a 2-d array in which each output channel is a column
            True to return a 1-d array containing the summed output channels. The rms
            will be equated to the rms of the input [ default ]
        order : int
            The filter order to use [ default = 3 ]

        Returns
        -------
        y : array
            The vocoded signal

        Notes
        -----
        Depends on tone.py
'''

    outlo = kwargs.get('outlo', inlo)
    outhi = kwargs.get('outhi', inhi)
    envfilter = kwargs.get('envfilter', 400)
    noise = kwargs.get('noise', False)
    sumchannels = kwargs.get('sumchannels', True)
    ord = kwargs.get('order', 3)
    compression_ratio = kwargs.get('compression_ratio', 1)
    gate = kwargs.get('gate', None)

    if noise:
        noisecarrier = np.random.randn(len(signal))
        noisecarrier = noisecarrier / max(np.abs(noisecarrier))
    signal = signal - np.mean(signal)
    nyq = np.float32(fs / 2.)
    ininterval = np.log10(
        np.float32(inhi) / np.float32(inlo)) / np.float32(channels)
    outinterval = np.log10(
        np.float32(outhi) / np.float32(outlo)) / np.float32(channels)
    if sumchannels:
        carriers = np.zeros(len(signal))
    else:
        carriers = np.zeros((len(signal), channels))

    ret = np.zeros((len(signal), channels))
    for i in range(channels):
        # Estimate filters
        finhi = np.float32(inlo) * 10.**(ininterval * (i + 1))
        finlo = np.float32(inlo) * 10.**(ininterval * i)
        fouthi = np.float32(outlo) * 10.**(outinterval * (i + 1))
        foutlo = np.float32(outlo) * 10.**(outinterval * i)
        fcarrier = .5 * (fouthi + foutlo)
        [b_sub_hp, a_sub_hp] = filters.butter(ord, (finlo / nyq), btype='high')
        [b_sub_lp, a_sub_lp] = filters.butter(ord, (finhi / nyq))

        [b_env, a_env
         ] = filters.butter(2,
                            min((.5 * (fouthi - foutlo)), envfilter) / nyq)
        [b_out_hp, a_out_hp] = filters.butter(ord, (foutlo / nyq),
                                              btype='high')
        [b_out_lp, a_out_lp] = filters.butter(ord, (fouthi / nyq))

        ## Filter input
        Sig_sub = lfilter(b_sub_hp, a_sub_hp, signal)
        Sig_sub = lfilter(b_sub_lp, a_sub_lp, Sig_sub)
        #        ret[:,i] = Sig_sub.copy()
        rms_Sig_sub = np.sqrt(np.mean(Sig_sub**2))
        Sig_env_sub = lfilter(b_env, a_env, np.maximum(Sig_sub, 0))
        peak = Sig_env_sub.max()
        Sig_env_sub /= compression_ratio
        Sig_env_sub += peak - Sig_env_sub.max()
        if gate is not None:
            db = 20 * np.log10(Sig_env_sub / peak)
            Sig_env_sub[db < gate] = 0
        if noise:
            Mod_carrier = filtfilt(b_out_hp, a_out_hp, noisecarrier)
            Mod_carrier = filtfilt(b_out_lp, a_out_lp,
                                   Mod_carrier) * Sig_env_sub
        else:
            Mod_carrier = tone(np.ones(len(signal)) * fcarrier, fs,
                               1) * Sig_env_sub

        ## Filter output
        Mod_carrier_filt = lfilter(b_out_hp, a_out_hp, Mod_carrier)
        Mod_carrier_filt = lfilter(b_out_lp, a_out_lp, Mod_carrier_filt)
        if sumchannels:
            carriers += Mod_carrier_filt / np.sqrt(np.mean(Mod_carrier_filt**
                                                           2)) * rms_Sig_sub
        else:
            carriers[:, i] = Mod_carrier_filt / np.sqrt(
                np.mean(Mod_carrier_filt**2)) * rms_Sig_sub


#    return ret
    if sumchannels:
        return carriers * (np.sqrt(np.mean(signal**2)) /
                           np.sqrt(np.mean(carriers**2)))
    else:
        return carriers