summaryrefslogtreecommitdiff
path: root/src/audio/spectrogram_resource_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/spectrogram_resource_manager.cc')
-rw-r--r--src/audio/spectrogram_resource_manager.cc89
1 files changed, 77 insertions, 12 deletions
diff --git a/src/audio/spectrogram_resource_manager.cc b/src/audio/spectrogram_resource_manager.cc
index c0fb0a3..f182869 100644
--- a/src/audio/spectrogram_resource_manager.cc
+++ b/src/audio/spectrogram_resource_manager.cc
@@ -3,11 +3,17 @@
#include "spectrogram_resource_manager.h"
#include "audio/audio.h"
+#include "audio/dct.h"
#include "procedural/generator.h"
#include "util/debug.h"
#include <cstring>
#include <vector>
+#if !defined(STRIP_ALL)
+#include "audio/mp3_sample.h"
+#include "audio/window.h"
+#endif
+
void SpectrogramResourceManager::init() {
for (int i = 0; i < MAX_SPECTROGRAM_RESOURCES; ++i) {
resources_[i].owned_data = nullptr;
@@ -32,10 +38,13 @@ void SpectrogramResourceManager::shutdown() {
}
void SpectrogramResourceManager::reset() {
- // Clear state but keep registrations (useful for seeking)
- // Don't free memory, just mark as unloaded
+ // Clear state and free owned memory, keep registrations
for (int i = 0; i < MAX_SPECTROGRAM_RESOURCES; ++i) {
if (resources_[i].state == LOADED) {
+ if (resources_[i].owned_data) {
+ delete[] resources_[i].owned_data;
+ resources_[i].owned_data = nullptr;
+ }
resources_[i].state = REGISTERED;
}
}
@@ -50,7 +59,9 @@ void SpectrogramResourceManager::register_asset(int sample_id,
Resource& resource = resources_[sample_id];
resource.asset_id = asset_id;
- resource.state = REGISTERED;
+ if (resource.state == UNREGISTERED) {
+ resource.state = REGISTERED;
+ }
#if defined(DEBUG_LOG_ASSETS)
DEBUG_ASSETS("[ResourceMgr] Registered asset sample_id=%d, asset_id=%d\n",
@@ -67,7 +78,9 @@ void SpectrogramResourceManager::register_procedural(int sample_id,
Resource& resource = resources_[sample_id];
resource.asset_id = AssetId::ASSET_LAST_ID; // Mark as procedural
resource.proc_params = params;
- resource.state = REGISTERED;
+ if (resource.state == UNREGISTERED) {
+ resource.state = REGISTERED;
+ }
#if defined(DEBUG_LOG_ASSETS)
DEBUG_ASSETS("[ResourceMgr] Registered procedural sample_id=%d, freq=%.2f\n",
@@ -184,12 +197,19 @@ void SpectrogramResourceManager::try_evict_lru(float current_time) {
void SpectrogramResourceManager::load_asset(Resource* resource) {
size_t size;
const uint8_t* data = GetAsset(resource->asset_id, &size);
+ if (data == nullptr || size == 0) {
+ return;
+ }
- if (data == nullptr || size < sizeof(SpecHeader)) {
-#if defined(DEBUG_LOG_ASSETS)
- DEBUG_ASSETS("[ResourceMgr ERROR] Failed to load asset %d\n",
- (int)resource->asset_id);
+#if !defined(STRIP_ALL)
+ // MP3 assets: decode to spectrogram via OLA analysis
+ if (GetAssetType(resource->asset_id) == AssetType::MP3) {
+ load_mp3(resource, data, size);
+ return;
+ }
#endif
+
+ if (size < sizeof(SpecHeader)) {
return;
}
@@ -201,12 +221,57 @@ void SpectrogramResourceManager::load_asset(Resource* resource) {
resource->spec.num_frames = header->num_frames;
resource->spec.version = header->version;
resource->owned_data = nullptr; // Asset data is not owned
+}
-#if defined(DEBUG_LOG_ASSETS)
- DEBUG_ASSETS("[ResourceMgr] Loaded asset %d: %d frames\n",
- (int)resource->asset_id, header->num_frames);
-#endif
+#if !defined(STRIP_ALL)
+void SpectrogramResourceManager::load_mp3(Resource* resource,
+ const uint8_t* data, size_t size) {
+ Mp3Decoder* dec = mp3_open(data, size);
+ if (!dec)
+ return;
+
+ float window[DCT_SIZE];
+ hann_window_512(window);
+
+ std::vector<float> spec_data;
+ float pcm_buf[DCT_SIZE];
+ float pcm_chunk[DCT_SIZE];
+ float dct_chunk[DCT_SIZE];
+
+ memset(pcm_buf, 0, sizeof(pcm_buf));
+
+ for (;;) {
+ memmove(pcm_buf, pcm_buf + OLA_HOP_SIZE, OLA_HOP_SIZE * sizeof(float));
+ const int decoded = mp3_decode(dec, OLA_HOP_SIZE, pcm_buf + OLA_HOP_SIZE);
+ if (decoded < OLA_HOP_SIZE) {
+ memset(pcm_buf + OLA_HOP_SIZE + decoded, 0,
+ (OLA_HOP_SIZE - decoded) * sizeof(float));
+ }
+
+ for (int i = 0; i < DCT_SIZE; ++i)
+ pcm_chunk[i] = pcm_buf[i] * window[i];
+ fdct_512(pcm_chunk, dct_chunk);
+ spec_data.insert(spec_data.end(), dct_chunk, dct_chunk + DCT_SIZE);
+
+ if (decoded == 0)
+ break;
+ }
+
+ mp3_close(dec);
+ if (spec_data.empty())
+ return;
+
+ const int num_frames = (int)(spec_data.size() / DCT_SIZE);
+ resource->owned_data = new float[spec_data.size()];
+ memcpy(resource->owned_data, spec_data.data(),
+ spec_data.size() * sizeof(float));
+
+ resource->spec.spectral_data_a = resource->owned_data;
+ resource->spec.spectral_data_b = resource->owned_data;
+ resource->spec.num_frames = num_frames;
+ resource->spec.version = SPEC_VERSION_V2_OLA;
}
+#endif
void SpectrogramResourceManager::load_procedural(Resource* resource) {
int note_frames = 0;