PHP Classes

File: digital_circuit_dsp.php

Recommend this page to a friend!
  Packages of Christos Drogidis   Ascoos OS Digital Circuit DSP   digital_circuit_dsp.php   Download  
File: digital_circuit_dsp.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Ascoos OS Digital Circuit DSP
Simulate a digital signal processing circuit
Author: By
Last change: Digital Signal Processing Pipeline
Date: 2 months ago
Size: 16,008 bytes
 

Contents

Class file image Download
<?php /** * @ASCOOS-NAME : Ascoos OS * @ASCOOS-VERSION : 1.0.0 * @ASCOOS-SUPPORT : support@ascoos.com * @ASCOOS-BUGS : https://issues.ascoos.com * * @CASE-STUDY : digital_circuit_dsp.php * @fileNo : ASCOOS-OS-CASESTUDY-SEC02786 * * @desc <English> * Simulates a digital signal processing pipeline: generates a clean 440 Hz sine + noisy version (uniform or Gaussian), * applies FIR & IIR low-pass filters, performs Hann-windowed FFT, estimates SNR improvement, THD, SINAD, ENOB and latency, * exports results to JSON/CSV ? for IoT/embedded DSP prototyping. * @desc <Greek> * ???????????? ????? ???????? ???????????? ???????: ?????????? ?????? ???????????? 440 Hz + ????????? ???? (?????????? ? Gaussian), * ????????? FIR & IIR low-pass ??????, ??????? FFT ?? ???????? Hann, ?????????? ???????? SNR, THD, SINAD, ENOB ??? ???????????, * ?????? ???????????? ?? JSON/CSV ? ??? ????????? IoT/embedded DSP. * * @since PHP 8.3.0+ */ declare(strict_types=1); use ASCOOS\OS\Kernel\Science\Electronics\TDigitalCircuitHandler; $properties = [ 'logs' => [ 'useLogger' => true, 'dir' => $AOS_LOGS_PATH, 'file' => 'dsp_simulation_improved.log' ] ]; try { $dHandler = new TDigitalCircuitHandler([], $properties); // ???????????????????????????????????????????????? // 1. <English> Test signal generation (clean + noisy) // <Greek> ?????????? ???????????? ??????? (?????? + ?????????) // ???????????????????????????????????????????????? $fs = 8000.0; // Sampling frequency (Hz) $N = 1024; // Number of samples (power-of-2 for FFT) $cleanSignal = []; // Pure 440 Hz sine $noisySignal = []; // Sine + noise $timeVector = []; // Time axis $noiseScale = 0.03; // ~30 dB below main tone (for uniform) $noiseStdDev = 0.03; // ~30 dB below main tone (for Gaussian) $noiseType = 'gaussian'; // 'uniform' or 'gaussian' for ($i = 0; $i < $N; $i++) { $t = $i / $fs; $s = sin(2 * M_PI * 440.0 * $t); // 440 Hz sine if ($noiseType === 'gaussian') { // Gaussian noise with stdDev = $noiseStdDev $noise = $dHandler->gaussianNoise($noiseStdDev); } else { // Uniform noise in [-1, 1) then scaled $noise = $noiseScale * ((mt_rand() / mt_getrandmax() - 0.5) * 2.0); } $timeVector[] = $t; $cleanSignal[] = $s; $noisySignal[] = $s + $noise; } // ???????????????????????????????????????????????? // 2. <English> FIR low-pass filtering (3-tap moving average) // <Greek> FIR low-pass ??????????? (3-tap ?????????? ?????) // ???????????????????????????????????????????????? $firCoeffs = [0.25, 0.5, 0.25]; // Simple triangular FIR $firFiltered = $dHandler->applyFIRFilter($firCoeffs, $noisySignal); // Group delay ~ (M-1)/2 samples $firDelaySamples = (count($firCoeffs) - 1) / 2.0; $firDelaySeconds = $firDelaySamples / $fs; // ???????????????????????????????????????????????? // 3. <English> IIR biquad low-pass Butterworth (2nd order @ 1800 Hz) // <Greek> IIR biquad low-pass Butterworth (2?? ????? @ 1800 Hz) // ???????????????????????????????????????????????? $fc = 1800.0; // Cutoff frequency $Q = 1 / sqrt(2); // ?0.7071 ? Butterworth $biquadCoeffs = $dHandler->biquadLowpassCoefficients($fc, $Q, $fs); $iirFiltered = $dHandler->applyBiquadFilter($biquadCoeffs, $noisySignal); // Approximate latency: 1 sample (implementation-dependent) $iirDelaySamples = 1.0; $iirDelaySeconds = $iirDelaySamples / $fs; // ???????????????????????????????????????????????? // 4. <English> Hann-windowed FFT analysis (reducing spectral leakage) // <Greek> ??????? FFT ?? ???????? Hann (?????? spectral leakage) // ???????????????????????????????????????????????? $hannWindow = []; for ($i = 0; $i < $N; $i++) { $hannWindow[] = 0.5 * (1.0 - cos(2.0 * M_PI * $i / ($N - 1))); } $windowedSignal = []; for ($i = 0; $i < $N; $i++) { $windowedSignal[] = $noisySignal[$i] * $hannWindow[$i]; } $fftComplex = $dHandler->fft($windowedSignal, true); // Normalized FFT $fftMagnitude = array_map([$dHandler, 'complexMagnitude'], $fftComplex); // Keep only positive spectrum [0, fs/2] $halfLength = (int)($N / 2) + 1; $fftMags = array_slice($fftMagnitude, 0, $halfLength); $fftFreqs = []; $df = $fs / $N; for ($i = 0; $i < $halfLength; $i++) { $fftFreqs[] = $i * $df; } // Peak frequency detection $maxMag = max($fftMags); $peakIdx = array_search($maxMag, $fftMags, true); $peakFreq = $fftFreqs[$peakIdx] ?? 0.0; // ???????????????????????????????????????????????? // 5. <English> SNR estimation (input vs FIR vs IIR) // <Greek> ???????? SNR (??????? vs FIR vs IIR) // ???????????????????????????????????????????????? $snrInput = $dHandler->SNRdB($cleanSignal, $noisySignal); // SNR before filtering $snrFIR = $dHandler->SNRdB($cleanSignal, $firFiltered); // SNR after FIR $snrIIR = $dHandler->SNRdB($cleanSignal, $iirFiltered); // SNR after IIR $snrFirGain = $snrFIR - $snrInput; $snrIirGain = $snrIIR - $snrInput; // ???????????????????????????????????????????????? // 5b. <English> THD, SINAD, ENOB estimation (from FFT) // <Greek> ???????? THD, SINAD, ENOB ??? FFT // ???????????????????????????????????????????????? $dspMetrics = $dHandler->estimateThdSinadEnob($fftFreqs, $fftMags, 440.0, 5, 1.5); $thdDb = $dspMetrics['thd_db']; $sinadDb = $dspMetrics['sinad_db']; $enob = $dspMetrics['enob_bits']; // ???????????????????????????????????????????????? // 6. <English> Console summary of key results // <Greek> ???????? ??????? ????????????? ???? ??????? // ???????????????????????????????????????????????? echo "DSP Simulation Results / ???????????? DSP\n"; echo "??????????????????????????????????????????\n"; echo "Signal length : $N samples\n"; echo "Sampling rate : {$fs} Hz\n"; echo "Noise type : {$noiseType}\n"; echo "Peak frequency (FFT) : " . round($peakFreq, 1) . " Hz\n"; echo "Max FFT magnitude : " . round($maxMag, 4) . "\n\n"; echo "SNR (input noisy) : " . ($snrInput === INF ? "INF" : round($snrInput, 2)) . " dB\n"; echo "SNR (after FIR) : " . ($snrFIR === INF ? "INF" : round($snrFIR, 2)) . " dB\n"; echo "SNR (after IIR) : " . ($snrIIR === INF ? "INF" : round($snrIIR, 2)) . " dB\n\n"; echo "SNR gain (FIR) : " . (is_nan($snrFirGain) ? "NaN" : round($snrFirGain, 2)) . " dB\n"; echo "SNR gain (IIR) : " . (is_nan($snrIirGain) ? "NaN" : round($snrIirGain, 2)) . " dB\n\n"; echo "THD (approx) : " . (is_nan($thdDb) ? "NaN" : round($thdDb, 2)) . " dB\n"; echo "SINAD (approx) : " . (is_nan($sinadDb) ? "NaN" : round($sinadDb, 2)) . " dB\n"; echo "ENOB (approx) : " . (is_nan($enob) ? "NaN" : round($enob, 3)) . " bits\n\n"; echo "FIR delay : " . round($firDelaySamples, 2) . " samples (" . round($firDelaySeconds * 1e3, 3) . " ms)\n"; echo "IIR delay (approx) : " . round($iirDelaySamples, 2) . " samples (" . round($iirDelaySeconds * 1e3, 3) . " ms)\n\n"; echo "FIR first 5 samples : " . json_encode(array_slice($firFiltered, 0, 5), JSON_NUMERIC_CHECK) . "\n"; echo "IIR biquad coeffs : " . json_encode($biquadCoeffs, JSON_NUMERIC_CHECK) . "\n\n"; // ???????????????????????????????????????????????? // 7. <English> Export full data to JSON // <Greek> ??????? ?????? ????????? ?? JSON // ???????????????????????????????????????????????? $jsonExportPath = $AOS_TMP_DATA_PATH . '/signal_dsp_demo.json'; $dHandler->toJSONFile($jsonExportPath, [ 'fs' => $fs, 'N' => $N, 'time' => $timeVector, 'signals' => [ 'clean' => $cleanSignal, 'noisy' => $noisySignal, 'fir' => $firFiltered, 'iir' => $iirFiltered, ], 'fft' => [ 'freq' => $fftFreqs, 'mag' => $fftMags, 'window' => 'Hann', ], 'snr_db' => [ 'input_noisy' => $snrInput, 'fir' => $snrFIR, 'iir' => $snrIIR, ], 'snr_improvement' => [ 'fir_gain_db' => $snrFirGain, 'iir_gain_db' => $snrIirGain, ], 'latency' => [ 'fir' => [ 'samples' => $firDelaySamples, 'seconds' => $firDelaySeconds, ], 'iir' => [ 'samples' => $iirDelaySamples, 'seconds' => $iirDelaySeconds, ], ], 'dsp_metrics' => [ 'thd_db' => $thdDb, 'sinad_db' => $sinadDb, 'enob_bits' => $enob, ], 'metadata' => [ 'peak_frequency_hz' => $peakFreq, 'generated_at' => date('c'), 'description_en' => 'DSP demo: 440 Hz sine, noise (' . $noiseType . '), FIR/IIR low-pass, Hann FFT, SNR, THD, SINAD, ENOB & latency estimation.', 'description_gr' => 'Demo DSP: ???????????? 440 Hz, ??????? (' . $noiseType . '), FIR/IIR low-pass, FFT Hann, ???????? SNR, THD, SINAD, ENOB & ????????????.', 'filters' => [ 'fir_coeffs' => $firCoeffs, 'iir_cutoff_hz'=> $fc, 'iir_Q' => $Q, 'iir_coeffs' => $biquadCoeffs, ], 'plot_suggestions' => [ 'time-domain: clean vs noisy vs FIR vs IIR', 'frequency-domain: FFT magnitude with 440 Hz peak', 'SNR evolution: input vs FIR vs IIR', 'DSP metrics: THD / SINAD / ENOB vs configuration', ], ], ]); echo "JSON results exported to: $jsonExportPath\n"; // ???????????????????????????????????????????????? // 8. <English> Export selected data to CSV (FFT spectrum & time-domain) // <Greek> ??????? ??????????? ????????? ?? CSV (????? FFT & ??????? ?????) // ???????????????????????????????????????????????? // 8a. FFT spectrum CSV $fftCsvPath = $AOS_TMP_DATA_PATH . '/signal_dsp_fft_spectrum.csv'; $fftHeader = [ 'freq_hz', 'magnitude', ]; $fftRows = []; for ($i = 0; $i < $halfLength; $i++) { $fftRows[] = [ $fftFreqs[$i], $fftMags[$i], ]; } $dHandler->toCSVFile($fftCsvPath, $fftRows, $fftHeader, ','); echo "FFT spectrum exported to: $fftCsvPath\n"; // 8b. Time-domain signals CSV $timeCsvPath = $AOS_TMP_DATA_PATH . '/signal_dsp_time_signals.csv'; $timeHeader = [ 't_seconds', 'clean', 'noisy', 'fir', 'iir', ]; $timeRows = []; for ($i = 0; $i < $N; $i++) { $timeRows[] = [ $timeVector[$i], $cleanSignal[$i], $noisySignal[$i], $firFiltered[$i] ?? null, $iirFiltered[$i] ?? null, ]; } $dHandler->toCSVFile($timeCsvPath, $timeRows, $timeHeader, ','); echo "Time-domain signals exported to: $timeCsvPath\n"; // ???????????????????????????????????????????????? // 9. <English> Logging summary // <Greek> ?????? ??? log // ???????????????????????????????????????????????? $dHandler->logger?->log( sprintf( "DSP simulation completed | N=%d | noise=%s | peak=%.1f Hz | max_mag=%.4f | ". "SNR_in=%.2f dB | SNR_FIR=%.2f dB | SNR_IIR=%.2f dB | ". "THD=%.2f dB | SINAD=%.2f dB | ENOB=%.3f bits | ". "JSON=%s | FFT_CSV=%s | TIME_CSV=%s", $N, $noiseType, $peakFreq, $maxMag, $snrInput, $snrFIR, $snrIIR, $thdDb, $sinadDb, $enob, $jsonExportPath, $fftCsvPath, $timeCsvPath ), $dHandler::DEBUG_LEVEL_INFO ); } catch (Throwable $e) { echo "Error / ??????: " . $e->getMessage() . "\n"; if (isset($dHandler) && $dHandler->logger) { $dHandler->logger->log( "DSP simulation failed: " . $e->getMessage(), $dHandler::DEBUG_LEVEL_ERROR ); } } finally { // ???????????????????????????????????????????????? // 10. <English> Resources Release // <Greek> ???????????? ????? // ???????????????????????????????????????????????? if (isset($dHandler)) { $dHandler->Free(); } }