1
$\begingroup$

I am implementing an STFT function for spectrogram of certain audio files. Here's my function:

def stft( input_sound, dft_size, hop_size, zero_pad, window):

    if hop_size != dft_size:
        number_frames = int(np.ceil((len(input_sound) - hop_size) / (dft_size 
        - hop_size)))
    else:
        number_frames = len(input_sound)//dft_size

    matrix = np.zeros(shape = (dft_size//2 +1, number_frames), dtype = 
    complex)

    for i in range(number_frames):
        if hop_size != dft_size:
            block = input_sound[i*(dft_size-hop_size): i*(dft_size- 
            hop_size)+dft_size]
        else:
            block = input_sound[i*(dft_size): i*(dft_size)+dft_size]

        #  pad zeros to have enough samples to compose the last frame
        if len(block) < dft_size:  
            block = np.append(block, np.zeros(dft_size-len(block)))
        # apply window
        block = block*window  
        # take dft
        dft = (np.fft.rfft(block, n=dft_size+zero_pad)) # dft_size/2 + 1

    matrix.T[i] = dft

    return matrix

Here's my inverse STFT function:

def istft( stft_output, dft_size, hop_size, zero_pad, window):

    if dft_size != hop_size:
        length = dft_size*len(stft_output.T) - hop_size*len(stft_output.T) + 
         hop_size
    else:
        length = dft_size*len(stft_output.T)
    output_sound = np.zeros(length)

    for i in range(len(stft_output.T)):
        dft = stft_output.T[i]
        idft = np.fft.irfft(dft, n=dft_size+zero_pad)
        idft = idft*window
        if dft_size != hop_size:
            output_sound[i*(dft_size-hop_size): i*(dft_size- 
            hop_size)+dft_size] += idft
        else:
            output_sound[i*(dft_size): i*(dft_size)+dft_size] += idft

    return output_sound

My Inverse STFT code works as they did reconstruct the sound back. However, my problem is that I can not get it reconstruct perfectly. The audio file I am using right now is a drum clip and its sampling frequency is 11025 Hz with total 28884 samples. The parameters I used is dft_size = 1024, hop_size = 512, window = np.hanning(1024), zero_pad= none.

As I researched online, for hanning window, hop size being 1/2 of its windows length should get you perfectly reconstruction. But I didn't. So I wonder if there is something I coded wrong or I haven't found the right combination of dft size, hop size, and windows yet.

$\endgroup$
  • $\begingroup$ so you're not modifying the frequency-domain data and still not getting perfect reconstruction? $\endgroup$ – robert bristow-johnson Feb 1 at 4:06
  • $\begingroup$ is this Python? $\endgroup$ – robert bristow-johnson Feb 1 at 4:07
  • 1
    $\begingroup$ Yeah, this is done in python. But I just found out that if I didn't apply window when I inversed STFT, the output is nearly perfect. $\endgroup$ – Iloveece Feb 1 at 6:26

Your Answer

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

Browse other questions tagged or ask your own question.