// master_gain.cpp — see master_gain.h. Pure math; no LICE/VST3/REAPER includes.

#include "core/instrument/engine/master_gain.h"

#include "core/util/clamp01.h"

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <limits>

namespace reasampler::instrument::engine {

using util::clamp01;

double masterGainMaxLinear() { return std::pow(10.0, kMasterGainMaxDb / 20.0); }

double masterGainDbFromNorm(double norm) {
    norm = clamp01(norm);
    if (norm <= 0.0) return -std::numeric_limits<double>::infinity();
    return kMasterGainMinDb + norm * (kMasterGainMaxDb - kMasterGainMinDb);
}

double masterGainNormFromDb(double db) {
    if (!(db > kMasterGainMinDb)) return 0.0;  // -inf, NaN, and the floor all read 0
    return clamp01((db - kMasterGainMinDb) / (kMasterGainMaxDb - kMasterGainMinDb));
}

double masterGainLinearFromNorm(double norm) {
    norm = clamp01(norm);
    if (norm <= 0.0) return 0.0;  // TRUE silence at the bottom — not an epsilon
    return std::pow(10.0, masterGainDbFromNorm(norm) / 20.0);
}

double masterGainNormFromLinear(double linear) {
    if (!std::isfinite(linear) || linear <= 0.0) return 0.0;
    return masterGainNormFromDb(20.0 * std::log10(linear));
}

void formatMasterGainLabel(double norm, char* buf, std::size_t len) {
    if (!buf || len == 0) return;
    norm = clamp01(norm);
    if (norm <= 0.0) {
        std::snprintf(buf, len, "-inf");
        return;
    }
    const double db = masterGainDbFromNorm(norm);
    std::snprintf(buf, len, "%+.1fdB", db);
}

}  // namespace reasampler::instrument::engine
