Invertible STFT and ISTFT in Python

后端 未结 10 1941
自闭症患者
自闭症患者 2020-12-02 07:57

Is there any general-purpose form of short-time Fourier transform with corresponding inverse transform built into SciPy or NumPy or whatever?

There\'s the pyplot

相关标签:
10条回答
  • 2020-12-02 08:19

    Neither of the above answers worked well OOTB for me. So I modified Steve Tjoa's.

    import scipy, pylab
    import numpy as np
    
    def stft(x, fs, framesz, hop):
        """
         x - signal
         fs - sample rate
         framesz - frame size
         hop - hop size (frame size = overlap + hop size)
        """
        framesamp = int(framesz*fs)
        hopsamp = int(hop*fs)
        w = scipy.hamming(framesamp)
        X = scipy.array([scipy.fft(w*x[i:i+framesamp]) 
                         for i in range(0, len(x)-framesamp, hopsamp)])
        return X
    
    def istft(X, fs, T, hop):
        """ T - signal length """
        length = T*fs
        x = scipy.zeros(T*fs)
        framesamp = X.shape[1]
        hopsamp = int(hop*fs)
        for n,i in enumerate(range(0, len(x)-framesamp, hopsamp)):
            x[i:i+framesamp] += scipy.real(scipy.ifft(X[n]))
        # calculate the inverse envelope to scale results at the ends.
        env = scipy.zeros(T*fs)
        w = scipy.hamming(framesamp)
        for i in range(0, len(x)-framesamp, hopsamp):
            env[i:i+framesamp] += w
        env[-(length%hopsamp):] += w[-(length%hopsamp):]
        env = np.maximum(env, .01)
        return x/env # right side is still a little messed up...
    
    0 讨论(0)
  • 2020-12-02 08:22

    Found another STFT, but no corresponding inverse function:

    http://code.google.com/p/pytfd/source/browse/trunk/pytfd/stft.py

    def stft(x, w, L=None):
        ...
        return X_stft
    
    • w is a window function as an array
    • L is the overlap, in samples
    0 讨论(0)
  • 2020-12-02 08:25

    A fixed version of basj's answer.

    import scipy, numpy as np
    import matplotlib.pyplot as plt
    
    def stft(x, fftsize=1024, overlap=4):
        hop=fftsize//overlap
        w = scipy.hanning(fftsize+1)[:-1]      # better reconstruction with this trick +1)[:-1]  
        return np.vstack([np.fft.rfft(w*x[i:i+fftsize]) for i in range(0, len(x)-fftsize, hop)])
    
    def istft(X, overlap=4):   
        fftsize=(X.shape[1]-1)*2
        hop=fftsize//overlap
        w=scipy.hanning(fftsize+1)[:-1]
        rcs=int(np.ceil(float(X.shape[0])/float(overlap)))*fftsize
        print(rcs)
        x=np.zeros(rcs)
        wsum=np.zeros(rcs)
        for n,i in zip(X,range(0,len(X)*hop,hop)): 
            l=len(x[i:i+fftsize])
            x[i:i+fftsize] += np.fft.irfft(n).real[:l]   # overlap-add
            wsum[i:i+fftsize] += w[:l]
        pos = wsum != 0
        x[pos] /= wsum[pos]
        return x
    
    a=np.random.random((65536))
    b=istft(stft(a))
    plt.plot(range(len(a)),a,range(len(b)),b)
    plt.show()
    
    0 讨论(0)
  • 2020-12-02 08:25

    If you have access to a C binary library that does what you want, then use http://code.google.com/p/ctypesgen/ to generate a Python interface to that library.

    0 讨论(0)
  • 2020-12-02 08:26

    I think scipy.signal has what you are looking for. It has reasonable defaults, supports multiple window types, etc...

    http://docs.scipy.org/doc/scipy-0.17.0/reference/generated/scipy.signal.spectrogram.html

    from scipy.signal import spectrogram
    freq, time, Spec = spectrogram(signal)
    
    0 讨论(0)
  • 2020-12-02 08:32

    I also found this on GitHub, but it seems to operate on pipelines instead of normal arrays:

    http://github.com/ronw/frontend/blob/master/basic.py#LID281

    def STFT(nfft, nwin=None, nhop=None, winfun=np.hanning):
        ...
        return dataprocessor.Pipeline(Framer(nwin, nhop), Window(winfun),
                                      RFFT(nfft))
    
    
    def ISTFT(nfft, nwin=None, nhop=None, winfun=np.hanning):
        ...
        return dataprocessor.Pipeline(IRFFT(nfft), Window(winfun),
                                      OverlapAdd(nwin, nhop))
    
    0 讨论(0)
提交回复
热议问题