diff options
Diffstat (limited to 'src/audio/spectrogram_resource_manager.cc')
| -rw-r--r-- | src/audio/spectrogram_resource_manager.cc | 89 |
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; |
