diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/spectool.cc | 66 |
1 files changed, 8 insertions, 58 deletions
diff --git a/tools/spectool.cc b/tools/spectool.cc index a9d2bd1..93f8f9a 100644 --- a/tools/spectool.cc +++ b/tools/spectool.cc @@ -3,10 +3,9 @@ // Provides both 'analyze' and 'play' modes for spectral data. #include "audio/audio.h" -#include "audio/dct.h" +#include "audio/ola.h" #include "audio/gen.h" #include "audio/synth.h" -#include "audio/window.h" #include "platform/platform.h" #include <stdio.h> #include <string.h> @@ -110,47 +109,15 @@ int analyze_audio(const char* in_path, const char* out_path, bool normalize, } } - // Second pass: Windowing + DCT (OLA v2: Hann window, 50% overlap) - std::vector<float> spec_data; - float window[WINDOW_SIZE]; - hann_window_512(window); - - // Process PCM data with OLA_HOP_SIZE stride (50% overlap) - const size_t hop = OLA_HOP_SIZE; - const size_t num_chunks = (pcm_data.size() > DCT_SIZE) - ? (pcm_data.size() - DCT_SIZE) / hop + 1 - : 1; - for (size_t chunk_idx = 0; chunk_idx < num_chunks; ++chunk_idx) { - const size_t chunk_start = chunk_idx * hop; - const size_t chunk_end = (chunk_start + DCT_SIZE < pcm_data.size()) - ? chunk_start + DCT_SIZE - : pcm_data.size(); - const size_t chunk_size = chunk_end - chunk_start; - - // Copy chunk (with zero-padding if needed) - memcpy(pcm_chunk, pcm_data.data() + chunk_start, - chunk_size * sizeof(float)); - if (chunk_size < DCT_SIZE) { - memset(pcm_chunk + chunk_size, 0, - (DCT_SIZE - chunk_size) * sizeof(float)); - } - - // Apply window - for (int i = 0; i < DCT_SIZE; ++i) { - pcm_chunk[i] *= window[i]; - } - - // Apply FDCT - float dct_chunk[DCT_SIZE]; - fdct_512(pcm_chunk, dct_chunk); - - // Add to spectrogram data - spec_data.insert(spec_data.end(), dct_chunk, dct_chunk + DCT_SIZE); - } + // Second pass: OLA encode (Hann window, 50% overlap) + const int n_pcm = (int)pcm_data.size(); + const int num_frames_enc = ola_num_frames(n_pcm); + std::vector<float> spec_data(num_frames_enc * DCT_SIZE); + ola_encode(pcm_data.data(), n_pcm, spec_data.data(), num_frames_enc); // --- Trim Silent Frames --- const float epsilon = 1e-6f; - int num_frames = spec_data.size() / DCT_SIZE; + int num_frames = num_frames_enc; int first_frame = 0; int last_frame = num_frames; @@ -269,26 +236,9 @@ int decode_to_wav(const char* in_path, const char* out_path) { std::vector<float> pcm; if (ola_mode) { - // IDCT + OLA (no synthesis window). - // Analysis: Hann * FDCT. Since Hann at 50% overlap satisfies - // w[n] + w[n+HOP] = 1, a rectangular synthesis window gives - // perfect reconstruction: output[n] = IDCT(X_k)[j] + IDCT(X_{k-1})[j+HOP] - // = x[n]*w[j] + x[n]*w[j+HOP] = x[n]. const uint32_t total_samples = (uint32_t)header.num_frames * OLA_HOP_SIZE; - pcm.assign(total_samples + OLA_OVERLAP, 0.0f); - - float overlap[OLA_OVERLAP] = {}; - for (int f = 0; f < header.num_frames; ++f) { - float tmp[DCT_SIZE]; - idct_512(spec_data.data() + f * DCT_SIZE, tmp); - // First half: output samples for this frame - for (int j = 0; j < OLA_HOP_SIZE; ++j) - pcm[f * OLA_HOP_SIZE + j] = tmp[j] + overlap[j]; - // Second half: save as overlap for next frame - for (int j = 0; j < OLA_OVERLAP; ++j) - overlap[j] = tmp[OLA_HOP_SIZE + j]; - } pcm.resize(total_samples); + ola_decode(spec_data.data(), header.num_frames, pcm.data()); } else { const uint32_t total_samples = (uint32_t)header.num_frames * DCT_SIZE; pcm.resize(total_samples); |
