//
// Tiny C wrapper around dr_mp3 + dr_flac. Each function decodes a buffer of
// MP3/FLAC bytes to interleaved s16 PCM. The caller owns the returned
// pointer and must release it with player_decoder_free().
//
// Compiled to a static lib (decoders.a) by lib/build_decoders.sh. The
// metaprogram in build.jai re-runs the script if the .a is missing or the
// sources are newer.
//

#define DR_MP3_IMPLEMENTATION
#define DR_MP3_NO_STDIO
#include "dr_mp3.h"

#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_NO_STDIO
#include "dr_flac.h"

#include <stdint.h>
#include <stdlib.h>

int16_t* player_decode_mp3(
    const void* data, size_t data_size,
    uint32_t* out_channels,
    uint32_t* out_sample_rate,
    uint64_t* out_total_pcm_frames
) {
    drmp3_config config;
    config.channels   = 0;
    config.sampleRate = 0;
    drmp3_uint64 total_frames = 0;

    drmp3_int16* pcm = drmp3_open_memory_and_read_pcm_frames_s16(
        data, data_size,
        &config,
        &total_frames,
        NULL  // default allocator
    );
    if (!pcm) return NULL;

    *out_channels         = config.channels;
    *out_sample_rate      = config.sampleRate;
    *out_total_pcm_frames = total_frames;
    return pcm;
}

int16_t* player_decode_flac(
    const void* data, size_t data_size,
    uint32_t* out_channels,
    uint32_t* out_sample_rate,
    uint64_t* out_total_pcm_frames
) {
    unsigned int channels    = 0;
    unsigned int sample_rate = 0;
    drflac_uint64 total_frames = 0;

    drflac_int16* pcm = drflac_open_memory_and_read_pcm_frames_s16(
        data, data_size,
        &channels,
        &sample_rate,
        &total_frames,
        NULL
    );
    if (!pcm) return NULL;

    *out_channels         = channels;
    *out_sample_rate      = sample_rate;
    *out_total_pcm_frames = total_frames;
    return pcm;
}

void player_decoder_free(void* p) {
    free(p);
}
