// Mel spectrogram extractor unifié Kazeia-Engine. // Couvre Whisper (16kHz, 80 mel, log10 + Whisper norm) et Qwen3-TTS speaker encoder // (24kHz, 128 mel, log naturel + clip 1e-5). // // Bit-correct vs librosa/torch reference pour les deux profils. // // Layout sortie : [N_MELS, T] = data[mel * T + frame] (PyTorch [B, C, T] / ggml // ne[0]=T fastest). Compatible directement avec speaker_encoder_encode_waveform() // et Whisper encoder ONNX (qui veut [1, n_mels, n_frames] fp16). #pragma once #include #include #include namespace kazeia_mel { enum class WindowKind { HANN_SYMMETRIC, // torch.hann_window(N) = 0.5*(1-cos(2*pi*n/(N-1))) (TTS) HANN_PERIODIC, // numpy/HF whisper = 0.5*(1-cos(2*pi*n/N)) (STT) }; enum class Compression { LOG_NATURAL, // log(max(mel, eps)) (TTS Qwen3-TTS) LOG10, // log10(max(mel, eps)) (STT Whisper) }; enum class PostNorm { NONE, // pas de post-process (TTS) WHISPER, // clamp à max-8, puis (x+4)/4 (STT Whisper) }; struct MelConfig { int sample_rate = 16000; int n_fft = 400; int hop_size = 160; int win_size = 400; int n_mels = 80; int pad_amount = -1; // -1 -> auto : whisper n_fft/2, tts (n_fft-hop)/2 int fixed_n_frames = 0; // 0 -> variable ; >0 -> pad audio à T fixe (whisper=3000=30s) float clip_eps = 1e-5f; // valeur min avant log WindowKind window = WindowKind::HANN_SYMMETRIC; Compression comp = Compression::LOG_NATURAL; PostNorm post = PostNorm::NONE; }; // Configs pré-faites — utiliser comme défauts puis customiser au besoin. MelConfig config_qwen3_tts_speaker(); // SR=24000, N_FFT=1024, hop=256, n_mels=128, log naturel MelConfig config_whisper(); // SR=16000, N_FFT=400, hop=160, n_mels=80, log10 + WhisperNorm // Charge mel_basis [n_mels, n_fft/2+1] depuis un fichier binaire f32 (librosa pré-calculé // ou mel_filters.json converti). Le caller fournit le path et la lib vérifie la taille // attendue n_mels * (n_fft/2+1). bool load_mel_basis(const char * path, const MelConfig & cfg, std::vector & out); // Compute mel spectrogram. wav = mono f32 [-1..1] @ cfg.sample_rate. mel_basis attendu // dans le layout librosa [n_mels, n_fft/2+1]. Retourne mel [n_mels, T] dans le layout // data[mel * T + frame]. out_T renvoie le nombre de frames calculés. std::vector compute(const std::vector & wav, const std::vector & mel_basis, const MelConfig & cfg, int & out_T); } // namespace kazeia_mel