summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/spectool.cc66
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);