#include "PhiAudio.h"

/*
 ===========================================================
    PhiAudio.cpp — VERSION SCIENTIFIQUEMENT VERROUILLÉE
    
    PRINCIPE PHYSIQUE:
    Un microphone PDM capte TOUTES les variations de pression
    acoustique dans sa bande passante (20 Hz - 8 kHz typique).
    
    Son vs EMI:
    • Son structuré   → harmoniques dominantes (voix, musique)
    • EMI acoustique  → bruit blanc/rose (secteur, switching)
    
    La distinction est SPECTRALE, pas temporelle.
    Le peak temporel sert uniquement à détecter le silence numérique.
 ===========================================================
*/

int16_t PhiAudio::_pdmBuffer[AUDIO_FFT_SIZE];
volatile bool PhiAudio::_pdmDataReady = false;

PhiAudio::PhiAudio()
: _hpfAudio(0.962f),
  _bufferReady(false),
  _lastGhost(false),
  _lastPeak(0.0f),
  _audioType(TYPE_SILENCE)
{
    for (int i = 0; i < AUDIO_FFT_SIZE; i++) {
        _realBuf[i] = 0.0f;
        _imagBuf[i] = 0.0f;
        _pdmBuffer[i] = 0;
    }
}

void PhiAudio::_onPDMdata() {
    int bytes = PDM.available();
    if (bytes >= AUDIO_FFT_SIZE * 2) {
        PDM.read(_pdmBuffer, AUDIO_FFT_SIZE * 2);
        _pdmDataReady = true;
    }
}

bool PhiAudio::begin() {
    PDM.setBufferSize(AUDIO_FFT_SIZE * 2);
    PDM.onReceive(_onPDMdata);

    if (!PDM.begin(1, AUDIO_FS)) {
        Serial.println("✗ Audio init failed");
        return false;
    }

    Serial.println("✓ PhiAudio (16 kHz, spectral Audio/EMI classification)");
    return true;
}

void PhiAudio::update(bool ghostMode) {
    if (!_pdmDataReady)
        return;

    _pdmDataReady = false;

    // ═══════════════════════════════════════════════════════════════════
    // PEAK TEMPOREL - Usage strict: détection silence numérique
    // ═══════════════════════════════════════════════════════════════════
    // Le peak ne sert QU'À détecter un signal trop faible pour être analysé
    // spectralement (bruit quantification ADC < bruit thermique micro).
    // 
    // Seuil empirique (10/15) correspond au plancher de bruit numérique
    // du PDM MP34DT06JTR à 16 kHz sampling (~-90 dBFS).
    // ═══════════════════════════════════════════════════════════════════
    
    int16_t peak = 0;
    for (int i = 0; i < AUDIO_FFT_SIZE; i++) {
        int16_t v = abs(_pdmBuffer[i]);
        if (v > peak) peak = v;
    }
    _lastPeak = (float)peak;

    // ═══════════════════════════════════════════════════════════════════
    // FILTRAGE HPF - Suppression composante DC + dérive thermique
    // ═══════════════════════════════════════════════════════════════════
    // HPF α=0.962 → fc ≈ 1 Hz @ fs=16kHz
    // Retire offset DC sans affecter secteur 50 Hz (bande EMI pertinente)
    // ═══════════════════════════════════════════════════════════════════
    
    for (int i = 0; i < AUDIO_FFT_SIZE; i++) {
        float x = _pdmBuffer[i] / 32768.0f;
        _realBuf[i] = _hpfAudio.step(x);
    }
    
    // ═══════════════════════════════════════════════════════════════════
    // CLASSIFICATION PRÉLIMINAIRE (basée uniquement sur seuil numérique)
    // ═══════════════════════════════════════════════════════════════════
    // Si peak < seuil → signal sous plancher bruit → TYPE_SILENCE
    // Ce flag sera ÉCRASÉ par PhiScientificModel si analyse spectrale détecte EMI
    // 
    // ghostMode (expérimental) abaisse seuil pour capture bruit ambiant très faible
    // ═══════════════════════════════════════════════════════════════════
    
    int threshold = ghostMode ? 10 : 15;
    
    if (peak < threshold) {
        _audioType = TYPE_SILENCE;
    } else {
        // Signal détectable → classification spectrale déléguée à PhiScientificModel
        _audioType = TYPE_AUDIO;  // Valeur par défaut, sera raffinée par FFT
    }
    
    _lastGhost = false;
    _bufferReady = true;
}