#pragma once

namespace Xybrid::Data {
    struct AudioFrame {
        // stored as double here for operational precision
        double l = 0;
        double r = 0;

        inline AudioFrame() = default;
        inline AudioFrame(double v) : l(v), r(v) { }
        inline AudioFrame(float v) : AudioFrame(static_cast<double>(v)) { }
        inline AudioFrame(double l, double r) : l(l), r(r) { }
        inline AudioFrame(float l, float r) : l(static_cast<double>(l)), r(static_cast<double>(r)) { }

        inline AudioFrame operator+(AudioFrame o) const { return {l+o.l, r+o.r}; }
        inline void operator+=(AudioFrame o) {
            l += o.l;
            r += o.r;
        }

        inline AudioFrame operator*(AudioFrame o) const { return {l*o.l, r*o.r}; }
        inline void operator*=(AudioFrame o) {
            l *= o.l;
            r *= o.r;
        }
        inline AudioFrame operator*(double m) const { return {l*m, r*m}; }
        inline void operator*=(double m) {
            l *= m;
            r *= m;
        }

        static AudioFrame gainBalanceMult(double gain, double balance = 0.0);
        inline AudioFrame gainBalance(double gain, double balance = 0.0) const { return *this*gainBalanceMult(gain, balance); }
    };

    struct StorageFrame {
        float l = 0;
        float r = 0;
        inline StorageFrame() = default;
        inline StorageFrame(const AudioFrame& o) : l(static_cast<float>(o.l)), r(static_cast<float>(o.r)) { }
        inline operator AudioFrame() const { return AudioFrame(l, r); }
    };
}
