Проблема: Модификация STFT из Librosa с использованием DCT

Я пытаюсь сделать кратковременное дискретное косинусное преобразование, используя STFT из Librosa. Однако я не понимаю, почему результат преобразованного-обратного преобразования первоначальной синусоиды получается нечетким, как на первом изображении

преобразованный и преобразованный: преобразованный и преобразованный преобразованный

входная синусоида: входная синусоида

Мой код здесь, и я не вижу проблем с добавлением перекрытия. Кто-нибудь может помочь?

import numpy as np
import librosa.util
import scipy
import matplotlib.pyplot as plt
import librosa.filters
import scipy.fftpack

plt.figure(1)
sampling_rate=8000
x=np.arange(0.01,100,0.01)
data=np.sin(x)
plt.plot(data)
n_fft=256
hop_length=10
window_size=25
window = 'hann'
center = True
pad_mode='reflect'
dtype=np.complex64
length = None


fft_window = librosa.filters.get_window(window,window_size,fftbins=True)
fft_window = librosa.util.pad_center(fft_window,n_fft)
fft_window = fft_window.reshape((-1,1))
if center:
    data = np.pad(data,int(n_fft/2), mode= pad_mode)

y_frames = librosa.util.frame(data, frame_length=n_fft,hop_length=hop_length)

stdct_matrix = np.empty((int(1+n_fft//2),y_frames.shape[1]),dtype=dtype,order='F')
stft_matrix = np.empty((int(1+n_fft//2),y_frames.shape[1]),dtype=dtype,order='F')

n_columns = int(librosa.util.MAX_MEM_BLOCK / (stdct_matrix.shape[0] * stdct_matrix.itemsize))

for bl_s in range(0, stdct_matrix.shape[1], n_columns):
        bl_t = min(bl_s + n_columns, stdct_matrix.shape[1])

        stdct_matrix[:, bl_s:bl_t] = scipy.fftpack.dct(fft_window *
                                            y_frames[:, bl_s:bl_t],
                                            axis=0, norm='ortho')[:stdct_matrix.shape[0]]

        stft_matrix[:, bl_s:bl_t] = scipy.fftpack.fft(fft_window *
                                            y_frames[:, bl_s:bl_t],
                                            axis=0)[:stft_matrix.shape[0]]

i_dtype = np.float32
i_nfft = 2 * (stdct_matrix.shape[0]-1)
idct_window = librosa.filters.get_window(window,window_size,fftbins=True)
idct_window = librosa.util.pad_center(idct_window, i_nfft)

n_frames = stdct_matrix.shape[1]
expected_signal_len = i_nfft + hop_length * (n_frames - 1)
y = np.zeros(expected_signal_len, dtype=dtype)
y_1 = np.zeros(expected_signal_len, dtype=dtype)

for i in range(n_frames):
        sample = i * hop_length
        spec = stdct_matrix[:, i].flatten()
        #spec1= stft_matrix[:,i].flatten()
        spec = np.concatenate((spec, spec[-2:0:-1]), 0)
        #spec1 = np.concatenate((spec1, spec1[-2:0:-1]), 0)
        ytmp = idct_window * scipy.fftpack.idct(spec,norm='ortho').real
        #ytmp1= idct_window * scipy.fftpack.ifft(spec1).real

        y[sample:(sample + i_nfft)] = y[sample:(sample + i_nfft)] + ytmp
        #y_1[sample:(sample + i_nfft)] = y_1[sample:(sample + i_nfft)] + ytmp1


ifft_window_sum = librosa.filters.window_sumsquare(window,n_frames, win_length=window_size, n_fft=n_fft, hop_length=hop_length, dtype=i_dtype)

approx_nonzero_indices = ifft_window_sum > librosa.util.tiny(ifft_window_sum)
y[approx_nonzero_indices] /= ifft_window_sum[approx_nonzero_indices]

if length is None:
    if center:
        y = y[int(n_fft // 2):-int(n_fft // 2)]
else:
    if center:
        start = int(n_fft // 2)
    else:
        start = 0

    y = librosa.util.fix_length(y[start:], length)

plt.figure(2)
plt.plot(y)
plt.show()

0 ответов

Другие вопросы по тегам