using System.Collections.Concurrent;
using System.Collections.Generic;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
namespace AcDream.Core.Audio;
///
/// DatCollection-backed cache of decoded waves + SoundTable lookups.
///
///
/// Lazy-loads each Wave / SoundTable on first request, decodes Wave PCM
/// data via , and memoizes the result. Safe to
/// call from any thread — the inner dicts are
/// .
///
///
///
/// Returns null for waves whose format tag isn't PCM (MP3 / ADPCM
/// fall through silently until a compressed-decoder path is wired up).
///
///
public sealed class DatSoundCache
{
private readonly DatCollection _dats;
private readonly ConcurrentDictionary _waves = new();
private readonly ConcurrentDictionary _tables = new();
public DatSoundCache(DatCollection dats)
{
_dats = dats;
}
///
/// Retrieve decoded PCM data for a Wave dat id. Returns null if the
/// wave is missing, malformed, or uses a currently-unsupported format
/// (MP3 / ADPCM).
///
public WaveData? GetWave(uint waveId)
{
if (_waves.TryGetValue(waveId, out var cached)) return cached;
var wave = _dats.Get(waveId);
if (wave is null)
{
_waves[waveId] = null;
return null;
}
var decoded = WaveDecoder.Decode(wave.Header, wave.Data);
_waves[waveId] = decoded;
return decoded;
}
///
/// Retrieve a SoundTable by dat id. Returns null if the table is
/// missing from the dats.
///
public SoundTable? GetSoundTable(uint soundTableId)
{
if (_tables.TryGetValue(soundTableId, out var cached)) return cached;
var table = _dats.Get(soundTableId);
_tables[soundTableId] = table;
return table;
}
///
/// Total number of waves that have been accessed (hit or miss).
/// Useful for diagnostic overlays.
///
public int CachedWaveCount => _waves.Count;
///
/// Total number of SoundTables that have been accessed.
///
public int CachedSoundTableCount => _tables.Count;
}