Reputation: 11
I am using Non-negative Matrix Factorization (NMF) on an audio file of a working motor to decompose it into five NMF components. I need to explore the quefrency/cepstral domain of each component, but I am unsure how to proceed.
Since the NMF components are computed after applying the Short-Time Fourier Transform (STFT) to the original signal and are represented as a 2D matrix, I am uncertain about how to transform them into the quefrency domain.
I attempted to generate a cepstrogram for one of my NMF components using the following code:
# STFT Parameters
n_fft = 2048
hop_length = 256
win_length = n_fft
window = 'hann'
# Compute STFT
S = librosa.stft(y, n_fft=n_fft, hop_length=hop_length, win_length=win_length, window=window)
X, X_phase = librosa.magphase(S)
# Normalization
X_norm = librosa.util.normalize(X)
# NMF Calculation
n_components = 5
model = NMF(n_components=n_components, init='random', beta_loss='kullback-leibler', solver='mu', max_iter=3000, tol=1e-5, l1_ratio=0.8)
W = model.fit_transform(X_norm)
H = model.components_
# Compute the cepstrogram from log magnitude spectrum
c = np.outer(W[:, 4], H[4]) #c is already a absolute value
# Compute log magnitude
log_magnitude = np.log(c + 1e-10) # Add small value to avoid log(0)
# Compute cepstrum using IFFT
cepstrum = np.fft.ifft(log_magnitude, axis=0).real # Compute real cepstrum across time frames
# Number of unique cepstral coefficients
NUP = cepstrum.shape[0] // 2 # Keep only the first half
# Extract the meaningful part of the cepstrum
C = cepstrum[:NUP, :]
# Compute quefrency and time vectors
q = np.arange(NUP) / sr # Quefrency (s)
t = np.arange(C.shape[1]) * (hop_length / sr) # Time (s)
# ===== APPLY CONDITIONING =====
q_mask = q > 0.0005 # Ignore quefrencies below 0.5 ms
C = C[q_mask, :] # Filter cepstrum coefficients
q = q[q_mask] * 1000 # Convert quefrency from seconds to milliseconds
plt.figure(figsize=(10, 6))
plt.imshow(C, aspect='auto', origin='lower', extent=[t[0], t[-1], q[0], q[-1]])
plt.xlabel('Time (s)')
plt.ylabel('Quefrency (ms)')
plt.title('Cepstrogram from STFT (Magnitude Spectrum)')
plt.colorbar(label='Amplitude')
plt.show()
I need to determine whether this approach is correct. If it is, how can I extract quefrency domain features such as Linear Frequency Cepstral Coefficients (LFCC), Constant Q Cepstral Coefficients (CQCC), Teager Energy Cepstral Coefficients (TECC), and Gabor Filterbank Cepstral Coefficients (GTFB)?
Upvotes: 0
Views: 29