141 lines
4.1 KiB
TypeScript
141 lines
4.1 KiB
TypeScript
// state.ts - Peak Holder алгоритм с таймером
|
||
|
||
interface AppState {
|
||
maxPoints: number;
|
||
signalHistory: number[];
|
||
lastBufferSize: number;
|
||
|
||
// Peak Holder параметры
|
||
peakValue: number; // Текущее удерживаемое пиковое значение
|
||
currentValue: number; // Текущее реальное значение (без сглаживания)
|
||
peakTimer: number | null; // Таймер для сброса пика
|
||
peakHoldTime: number; // Время удержания пика в миллисекундах
|
||
}
|
||
|
||
export const state: AppState = {
|
||
maxPoints: 1000,
|
||
signalHistory: [],
|
||
lastBufferSize: 0,
|
||
|
||
peakValue: 0,
|
||
currentValue: 0,
|
||
peakTimer: null,
|
||
peakHoldTime: 3000, // миллисекунды удержания пика
|
||
};
|
||
|
||
/**
|
||
* Основная функция peak holder
|
||
* @param target - новое значение (0-63)
|
||
* @returns значение для отображения (пик, если таймер активен)
|
||
*/
|
||
export function updatePeakHolder(target: number): number {
|
||
// Обновляем текущее значение
|
||
state.currentValue = target;
|
||
|
||
// Если новое значение больше текущего пика
|
||
if (target > state.peakValue) {
|
||
// Устанавливаем новый пик
|
||
state.peakValue = target;
|
||
|
||
// Сбрасываем и перезапускаем таймер
|
||
resetPeakTimer();
|
||
startPeakTimer();
|
||
}
|
||
|
||
// Возвращаем текущий пик для отображения
|
||
return state.peakValue;
|
||
}
|
||
|
||
/**
|
||
* Запуск таймера сброса пика
|
||
*/
|
||
function startPeakTimer(): void {
|
||
if (state.peakTimer !== null) {
|
||
clearTimeout(state.peakTimer);
|
||
}
|
||
|
||
state.peakTimer = window.setTimeout(() => {
|
||
resetPeak();
|
||
}, state.peakHoldTime);
|
||
}
|
||
|
||
/**
|
||
* Сброс таймера пика
|
||
*/
|
||
function resetPeakTimer(): void {
|
||
if (state.peakTimer !== null) {
|
||
clearTimeout(state.peakTimer);
|
||
state.peakTimer = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Сброс пикового значения до текущего уровня
|
||
*/
|
||
function resetPeak(): void {
|
||
state.peakValue = state.currentValue;
|
||
state.peakTimer = null;
|
||
|
||
// Опционально: лог для отладки
|
||
// console.log(`[PeakHolder] Reset to: ${state.peakValue}`);
|
||
}
|
||
|
||
/**
|
||
* Принудительный сброс пика (например, при потере связи)
|
||
*/
|
||
export function forceResetPeak(): void {
|
||
resetPeakTimer();
|
||
state.peakValue = 0;
|
||
state.currentValue = 0;
|
||
}
|
||
|
||
/**
|
||
* Обновление времени удержания пика
|
||
* @param ms - время в миллисекундах
|
||
*/
|
||
export function setPeakHoldTime(ms: number): void {
|
||
state.peakHoldTime = ms;
|
||
}
|
||
|
||
/**
|
||
* Получение текущего состояния пика (для отладки)
|
||
*/
|
||
export function getPeakInfo(): { peak: number; current: number; timerActive: boolean } {
|
||
return {
|
||
peak: state.peakValue,
|
||
current: state.currentValue,
|
||
timerActive: state.peakTimer !== null,
|
||
};
|
||
}
|
||
|
||
// ===== ОСТАВЛЯЕМ СУЩЕСТВУЮЩИЕ ФУНКЦИИ БЕЗ ИЗМЕНЕНИЙ =====
|
||
|
||
export function addSignal(value: number): void {
|
||
state.signalHistory.push(value);
|
||
if (state.signalHistory.length > state.maxPoints) {
|
||
state.signalHistory = state.signalHistory.slice(-state.maxPoints);
|
||
}
|
||
}
|
||
|
||
export function addSignals(values: number[], bufferSize: number): void {
|
||
if (!Array.isArray(values) || values.length === 0) return;
|
||
|
||
const newBytes = bufferSize - state.lastBufferSize;
|
||
|
||
if (newBytes > 0 && newBytes <= values.length) {
|
||
const fresh = values.slice(-newBytes);
|
||
const decoded = fresh.map(b => b & 0x3F);
|
||
state.signalHistory.push(...decoded);
|
||
}
|
||
|
||
state.lastBufferSize = bufferSize;
|
||
|
||
if (state.signalHistory.length > state.maxPoints) {
|
||
state.signalHistory = state.signalHistory.slice(-state.maxPoints);
|
||
}
|
||
}
|
||
|
||
export function resetBufferTracking(): void {
|
||
state.lastBufferSize = 0;
|
||
forceResetPeak(); // Также сбрасываем пик при потере связи
|
||
} |