diff --git a/src/Immersive-clock-monitor/noise-technical.md b/src/Immersive-clock-monitor/noise-technical.md new file mode 100644 index 0000000..42c7419 --- /dev/null +++ b/src/Immersive-clock-monitor/noise-technical.md @@ -0,0 +1,772 @@ +# 沉浸式时钟噪音计算与评分技术文档 + +Immersive Clock 的噪音监测系统不仅仅是一个简单的分贝计,它内置了一个基于心理声学与专注力理论的评分引擎。该引擎旨在客观、多维度地量化环境噪音对学习心流的干扰程度。 + +本文档详细解析了该系统的计算原理、核心指标定义、评分算法及完整的技术架构。 + +## 目录 + +1. [核心理念](#1-核心理念) +2. [系统架构](#2-系统架构) +3. [数据采集层](#3-数据采集层) +4. [数据聚合层](#4-数据聚合层) +5. [评分算法核心](#5-评分算法核心) +6. [数据存储层](#6-数据存储层) +7. [历史报告生成](#7-历史报告生成) +8. [流服务整合](#8-流服务整合) +9. [配置参数体系](#9-配置参数体系) +10. [类型定义](#10-类型定义) + +--- + +## 1. 核心理念 + +### 1.1 设计原则 + +系统认为,并非所有"响声"都是一样的。对于专注力而言: + +- **持续的嗡嗡声**(如嘈杂的人群)比**偶尔的掉笔声**更具破坏性 +- **频繁的打断**(如每分钟都有人说话)比**单次的大声喧哗**更让人烦躁 +- **评分与校准分离**:评分使用原始 DBFS 数据,校准仅影响显示分贝 + +因此,评分系统采用了 **多维度加权扣分制**,满分 100 分,根据环境表现进行扣分。 + +### 1.2 评分与校准分离 + +项目通过"原始数据(用于评分)"与"显示数据(用于展示)"的**严格分层**,杜绝了校准值导致的评分偏差: + +1. **评分只依赖原始 DBFS(设备输出的相对电平)** + - 评分的三项核心指标(`p50Dbfs`、`overRatioDbfs`、`segmentCount`)都来自原始 `dbfs` 统计 + - "超阈时长占比"判定条件固定为:`dbfs > scoreThresholdDbfs`(阈值默认 `-50 dBFS`),与校准无关 + - 这意味着即使用户把"显示分贝基准"调高/调低,评分侧的 `dbfs` 不会变化,因此得分与超阈时长也不会被"调参刷分" + +2. **校准仅影响 Display dB(UI 展示口径),不进入评分链路** + - 校准(`baselineRms` / `baselineDb`)只用于将 `rms` 映射为 `displayDb`,用于实时显示与报告中的"噪音等级分布"等图表展示 + - 这些展示口径变化不会反向影响评分输入,也不会改变切片摘要中的 `raw.*` 字段 + +3. **统计报告中"超阈时长"取自 raw.overRatioDbfs** + - 报告里展示的"超阈时长"是对每个切片 `raw.overRatioDbfs` 按有效采样时长加权汇总得到,仍然完全基于 DBFS + - 相比之下,"噪音等级分布"使用的是 `display.avgDb`(校准后的显示分贝),因此它会随校准变化——这是为了更贴近用户直觉的 dB 区间划分 + +--- + +## 2. 系统架构 + +### 2.1 整体架构图 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 用户界面层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ 实时监控组件 │ │ 噪音报告弹窗 │ │ 噪音历史列表 │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + ↑ + │ 订阅/发布 + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ 流服务层 │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ 噪音流服务 - 订阅管理、生命周期控制、设置热更新 │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + ↑ + │ 帧数据流 + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ 数据聚合层 │ +│ ┌──────────────────┐ ┌────────────────────────────────────┐ │ +│ │ 噪音帧处理器 │ │ 噪音切片聚合器 │ │ +│ │ - RMS/dBFS 计算 │ │ - 切片聚合、统计指标、评分计算 │ │ +│ │ - 50ms/帧 │ │ - 30秒/切片 │ │ +│ └──────────────────┘ └────────────────────────────────────┘ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ 实时环形缓冲区 - 保留固定时长的实时数据 │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + ↑ + │ 音频流 + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ 数据采集层 │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ 麦克风采集 - Web Audio API、滤波器、AnalyserNode │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + ↑ + │ 物理音频 + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ 数据存储层 │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ 切片存储 - localStorage、时间清理、容量限制 │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + ↑ + │ 历史数据 + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ 历史报告层 │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ 历史构建 - 课表关联、加权平均评分、覆盖率计算 │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 模块说明 + +| 模块 | 功能 | +|------|------| +| 类型定义 | 核心类型定义 | +| 常量定义 | 分析参数常量、报告参数常量 | +| 麦克风采集 | 音频采集 | +| 帧处理器 | 帧处理 | +| 切片聚合器 | 切片聚合 | +| 环形缓冲区 | 实时数据 | +| 流服务 | 流管理 | +| 评分引擎 | 评分算法 | +| 切片服务 | 存储服务 | +| 历史构建 | 历史报告 | +| 设置管理 | 设置管理 | + +--- + +## 3. 数据采集层 + +### 3.1 麦克风采集 + +#### 3.1.1 Web Audio API 使用 + +系统使用 Web Audio API 获取麦克风输入,构建完整的音频处理链路: + +``` +麦克风 → MediaStream → MediaStreamAudioSourceNode + → 高通滤波器 (80Hz) → 低通滤波器 (8000Hz) + → AnalyserNode (FFT Size 2048) +``` + +#### 3.1.2 音频滤波器配置 + +| 滤波器类型 | 截止频率 | 作用 | +|-----------|---------|------| +| 高通滤波器 | 80 Hz | 过滤低频噪音(如空调嗡嗡声) | +| 低通滤波器 | 8000 Hz | 过滤高频噪音(如电子设备啸叫) | + +#### 3.1.3 AnalyserNode 配置 + +```typescript +analyser.fftSize = 2048; // FFT 窗口大小 +analyser.smoothingTimeConstant = 0; // 无平滑,实时响应 +``` + +#### 3.1.4 权限处理与错误处理 + +```typescript +// 麦克风权限请求配置 +{ + audio: { + echoCancellation: false, // 禁用回声消除 + noiseSuppression: false, // 禁用降噪 + autoGainControl: false, // 禁用自动增益 + }, + video: false +} +``` + +**浏览器兼容性说明:** +- 部分浏览器/设备可能忽略上述约束设置 +- 建议在 UI 中提示用户实际生效的约束 +- 需要测试矩阵验证:Chrome/Firefox/Safari/Edge/iOS Safari/Android WebView + +**错误处理:** +- `NotAllowedError` / `SecurityError` → 权限拒绝 +- `AudioContext not supported` → 浏览器不支持 + +--- + +### 3.2 帧处理器 + +#### 3.2.1 采样频率 + +- **帧间隔**:50ms(约 20 fps) +- **数据来源**:AnalyserNode.getFloatTimeDomainData() + +#### 3.2.2 RMS(均方根)计算 + +RMS 是衡量音频信号强度的标准方法: + +**公式:** +$$ \text{RMS} = \sqrt{\frac{1}{N} \sum_{i=1}^{N} x_i^2} $$ + +#### 3.2.3 dBFS(分贝满刻度)转换 + +dBFS 是数字音频的标准分贝单位,范围 -100 到 0 dB: + +**公式:** +$$ \text{dBFS} = 20 \times \log_{10}(\text{RMS}) $$ + +**范围限制:** +- 最小值:-100 dBFS(静音) +- 最大值:0 dBFS(满刻度) + +#### 3.2.4 峰值检测 + +峰值用于检测突发噪音,在 RMS 计算过程中同时记录峰值。 + +--- + +## 4. 数据聚合层 + +### 4.1 切片聚合器 + +#### 4.1.1 切片时长 + +- **默认切片时长**:30 秒 +- **可配置范围**:≥ 1 秒 + +#### 4.1.2 统计指标计算 + +切片聚合器为每个切片计算以下统计指标: + +| 指标 | 说明 | 计算方法 | +|------|------|---------| +| avgDbfs | 平均分贝 | 能量平均(线性域 RMS 平均后转回 dBFS) | +| maxDbfs | 最大分贝 | 所有帧 dBFS 的最大值 | +| p50Dbfs | 中位数分贝 | 线性域分位数(RMS 域计算后转回 dBFS) | +| p95Dbfs | 95分位数分贝 | 线性域分位数(RMS 域计算后转回 dBFS) | +| overRatioDbfs | 超阈值比例 | 超阈值时长 / 采样时长 | +| segmentCount | 事件段数量 | 独立噪音事件次数 | +| sampledDurationMs | 采样时长 | 有效采样时间(排除缺口) | +| gapCount | 缺口数量 | 数据缺口次数 | +| maxGapMs | 最大缺口时长 | 最长数据缺口时长 | + +#### 4.1.3 能量平均计算(avgDbfs) + +**公式:** +$$ \text{avgDbfs} = 20 \times \log_{10}\left(\sqrt{\frac{1}{N} \sum_{i=1}^{N} 10^{\text{dBFS}_i / 10}}\right) $$ + +**物理意义:** 在线性域(RMS)上做平均,符合能量守恒定律 + +#### 4.1.4 线性域分位数计算 + +**公式:** +$$ \text{quantileDbfs} = 20 \times \log_{10}(Q_{\text{RMS}}(p)) $$ + +其中 $Q_{\text{RMS}}(p)$ 是 RMS 域的分位数,使用线性插值计算: +$$ Q_{\text{RMS}}(p) = x_{\lfloor i \rfloor} \times (1 - w) + x_{\lceil i \rceil} \times w $$ + +- $i = (n-1) \times p$ +- $w = i - \lfloor i \rfloor$ + +**物理意义:** 在线性域(RMS)上计算分位数,符合能量统计的严谨性 + +#### 4.1.5 超阈值比例计算(时间加权) + +**公式:** +$$ \text{overRatioDbfs} = \frac{\text{超阈值时长}}{\text{采样时长}} $$ + +**物理意义:** 使用实际时长而非帧数计算比例,更精确 + +#### 4.1.6 事件段检测与合并算法 + +事件段检测用于识别独立的噪音事件: + +**合并规则:** +- **合并窗口**:500ms(默认) +- 如果两次超阈值事件间隔 ≤ 500ms,合并为同一事件段 +- 否则计为新的独立事件段 + +**示例:** +``` +时间轴: 0ms 200ms 400ms 600ms 800ms 1000ms +状态: [噪音] [噪音] [安静] [噪音] [噪音] [安静] +合并后: └─────── 事件段1 ───────┘ └── 事件段2 ──┘ +``` + +#### 4.1.7 显示分贝映射(校准机制) + +显示分贝用于用户界面展示,支持校准: + +**公式(有校准):** +$$ \text{displayDb} = \text{baselineDb} + 20 \times \log_{10}\left(\frac{\text{rms}}{\text{baselineRms}}\right) $$ + +**公式(无校准):** +$$ \text{displayDb} = 20 \times \log_{10}\left(\frac{\text{rms}}{10^{-3}}\right) + 60 $$ + +**范围限制:** 20 dB ~ 100 dB + +**校准流程说明:** +1. 使用标准声源(如 60 dB 的白噪音) +2. 测量对应的 RMS 值 +3. 设置为 baselineRms +4. 设置对应的显示分贝为 baselineDb + +#### 4.1.8 缺口检测与采样时长统计 + +**缺口阈值:** `max(1000ms, frameMs × 5)` = **1000ms**(默认) + +当检测到数据缺口时,会触发切片完成并记录缺口信息。 + +#### 4.1.9 无效帧过滤 + +低于 -90 dBFS 的帧被视为静音/无效信号,不参与统计。 + +**常量说明:** +- `INVALID_DBFS_THRESHOLD = -90`:统计意义上的"静音"阈值 +- `DBFS_MIN_POSSIBLE = -100`:物理最小可表示值(用于 clamp) +- `DBFS_MAX_POSSIBLE = 0`:物理最大可表示值(用于 clamp) + +--- + +### 4.2 实时环形缓冲区 + +#### 4.2.1 数据结构设计 + +环形缓冲区使用固定容量数组实现,通过起始索引和当前长度管理数据。 + +#### 4.2.2 时间窗口裁剪策略 + +**裁剪规则:** 移除时间戳早于 `当前时间 - retentionMs` 的数据点 + +--- + +## 5. 评分算法核心 + +### 5.1 三大核心指标 + +评分引擎从以下三个维度对噪音数据进行分析: + +#### A. 持续噪音水平 (Sustained Level) + +- **定义**:剔除突发噪音后的环境"底噪"水平 +- **算法**:使用时段内所有帧的中位数电平 (`p50Dbfs`) +- **意义**:反映环境本身是否安静。如果环境中有持续的风扇声或交谈声,该指标会升高 + +#### B. 超阈值时长占比 (Over Threshold Ratio) + +- **定义**:原始 `DBFS` 超过评分阈值(`scoreThresholdDbfs`)的时间比例 +- **算法**:`超阈值时长 / 采样时长`(超标判定:`dbfs > scoreThresholdDbfs`) +- **意义**:反映环境的"纯净度"。即使是 0.1 秒的尖叫也会被精确计入,无法被平均值掩盖 + +> **提示**:评分阈值(`scoreThresholdDbfs`,单位 dBFS)与"界面报警/提示音"使用的显示分贝阈值(`maxLevelDb`,单位 dB)不是同一个概念;前者只用于评分,后者用于判定 noisy/quiet 与提示音触发。 + +#### C. 打断次数密度 (Interruption Density) + +- **定义**:单位时间内(每分钟)发生的独立噪音事件次数 +- **智能合并算法**: + - 系统设有 **500ms** (默认) 的合并窗口 + - 如果两次响声间隔小于该窗口(如拉椅子的一连串声音),会被合并为 **1 次打断** + - 只有间隔较长的响声才会被计为新的打断 +- **意义**:反映环境的干扰频率。频繁的打断(如断断续续的说话声)比连续的噪音更易打断心流 + +### 5.2 评分引擎 + +#### 5.2.1 三维度评分模型 + +评分系统从三个维度对噪音进行评估: + +| 维度 | 权重 | 指标 | 满扣分条件 | +|------|------|------|-----------| +| **持续噪音** | 40% | p50Dbfs | 中位数超过阈值 6 dBFS | +| **超阈时长** | 30% | overRatioDbfs | 超阈时间占比 30% | +| **打断频次** | 30% | segmentCount | 6 次/分钟 | + +#### 5.2.2 评分公式 + +**总惩罚系数:** +$$ \text{TotalPenalty} = 0.40 \times P_{\text{sustained}} + 0.30 \times P_{\text{time}} + 0.30 \times P_{\text{segment}} $$ + +**最终得分:** +$$ \text{Score} = 100 \times (1 - \text{TotalPenalty}) $$ + +#### 5.2.3 惩罚系数计算 + +##### A. 持续噪音惩罚 + +**公式:** +$$ P_{\text{sustained}} = \text{clamp}_{[0,1]}\left(\frac{\text{p50Dbfs} - \text{threshold}}{6}\right) $$ + +**满扣分条件:** `p50Dbfs - threshold ≥ 6 dBFS` + +##### B. 超阈时长惩罚 + +**公式:** +$$ P_{\text{time}} = \text{clamp}_{[0,1]}\left(\frac{\text{overRatioDbfs}}{0.3}\right) $$ + +**满扣分条件:** `overRatioDbfs ≥ 30%` + +##### C. 打断频次惩罚 + +**公式:** +$$ P_{\text{segment}} = \text{clamp}_{[0,1]}\left(\frac{\text{segmentCount} / \text{minutes}}{\text{maxSegmentsPerMin}}\right) $$ + +**满扣分条件:** `segmentsPerMin ≥ 6 次/分钟` + +#### 5.2.4 权重解读 + +- **持续噪音 (40%)**:持续底噪仍会明显拉低分数 +- **超阈时长 (30%)**:只要大部分时间安静,偶尔的噪音仍可被容忍 +- **打断频次 (30%)**:强调"被频繁打断"对心流的破坏,提升对碎片化干扰的惩罚力度 + +#### 5.2.5 边界条件处理 + +- DBFS 范围限制:-100 到 0 dB +- 惩罚系数范围限制:0 到 1 +- 评分范围限制:0 到 100 分 + +#### 5.2.6 有效时长处理 + +优先使用采样有效时长,不存在时回退到物理时长。 + +#### 5.2.7 评分示例 + +**场景 1:安静环境** +- p50Dbfs = -60 dBFS, threshold = -50 dBFS +- overRatioDbfs = 0.05 (5%) +- segmentCount = 1, duration = 30s + +``` +sustainedPenalty = clamp01((-60 - (-50)) / 6) = clamp01(-10/6) = 0 +timePenalty = clamp01(0.05 / 0.3) = 0.167 +segmentPenalty = clamp01((1/0.5) / 6) = clamp01(2/6) = 0.333 + +TotalPenalty = 0.4×0 + 0.3×0.167 + 0.3×0.333 = 0.15 +Score = 100 × (1 - 0.15) = 85 分 +``` + +**场景 2:嘈杂环境** +- p50Dbfs = -45 dBFS, threshold = -50 dBFS +- overRatioDbfs = 0.40 (40%) +- segmentCount = 8, duration = 30s + +``` +sustainedPenalty = clamp01((-45 - (-50)) / 6) = clamp01(5/6) = 0.833 +timePenalty = clamp01(0.40 / 0.3) = 1.0 +segmentPenalty = clamp01((8/0.5) / 6) = clamp01(16/6) = 1.0 + +TotalPenalty = 0.4×0.833 + 0.3×1.0 + 0.3×1.0 = 0.933 +Score = 100 × (1 - 0.933) = 6.7 分 +``` + +--- + +## 6. 数据存储层 + +### 6.1 切片服务 + +#### 6.1.1 localStorage 存储策略 + +存储键:`noise-slices` + +**隐私说明:** +- 存储内容:时间戳、噪音统计(不包含音频数据) +- 风险:可能泄露位置/日程信息 +- 建议:在 UI 中提供"清除历史"功能 + +#### 6.1.2 时间窗口清理 + +**默认保留时长:** 14 天 +**可配置范围:** 1 ~ 365 天 + +使用新切片的结束时间作为基准计算 cutoff,确保新切片不会被清理。 + +#### 6.1.3 容量限制 + +**容量上限:** 本地存储配额的 90% + +#### 6.1.4 数据规范化与校验 + +**精度控制:** +- dBFS:3 位小数 +- overRatioDbfs:4 位小数 +- 显示分贝:2 位小数 +- 评分:1 位小数 + +--- + +## 7. 历史报告生成 + +### 7.1 历史构建器 + +#### 7.1.1 与课表关联逻辑 + +**关联规则:** +1. 按日期分组切片 +2. 对每个日期的每个课时,查找重叠的切片 +3. 计算该课时的平均评分 + +#### 7.1.2 时段平均评分计算(加权平均) + +**公式:** +$$ \text{avgScore} = \frac{\sum_{i} \text{score}_i \times \text{effectiveMs}_i}{\sum_{i} \text{effectiveMs}_i} $$ + +其中: +$$ \text{effectiveMs}_i = \text{sampledDurationMs}_i \times \frac{\text{overlapMs}_i}{\text{sliceMs}_i} $$ + +#### 7.1.3 覆盖率计算 + +**公式:** +$$ \text{coverageRatio} = \frac{\text{totalMs}}{\text{periodMs}} $$ + +**含义:** 课时内有效采样时长占课时总时长的比例 + +#### 7.1.4 日期时间处理 + +**时区说明:** +- 使用本地时区 +- 内部存储使用 UTC 时间戳 +- 对外展示使用本地时间 + +**日期格式:** `YYYY-MM-DD` +**时间格式:** `HH:MM` + +#### 7.1.5 跨天课时处理 + +如果结束时间 ≤ 开始时间,则课时跨越到次日。 + +#### 7.1.6 报告中的图表 + +在噪音统计报告中,您可以直观地看到这些数据: + +- **评分走势图**:展示了 `Score` 随时间的变化,帮助您回顾专注状态 +- **噪音等级分布**:将每一帧归类为安静/正常/吵闹/极吵,直观展示时间占比 +- **扣分归因**:直接显示上述三个维度的扣分比例,告诉您为什么分低(是因为一直吵,还是因为总被打断) +- **打断次数密度**:展示每分钟被干扰的次数 + +--- + +## 8. 流服务整合 + +### 8.1 噪音流服务 + +#### 8.1.1 订阅/发布模式 + +**模式:** 观察者模式 +- 多个组件可同时订阅 +- 最后一个订阅者取消时自动停止采集 + +#### 8.1.2 生命周期管理 + +流服务支持启动、停止和重启操作,自动管理采集资源的生命周期。 + +#### 8.1.3 预热帧处理 + +**目的:** 丢弃麦克风启动后的不稳定数据(约 500ms) + +#### 8.1.4 设置热更新响应 + +**需要重启的参数:** +- frameMs +- sliceSec +- scoreThresholdDbfs +- segmentMergeGapMs +- maxSegmentsPerMin + +**无需重启的参数:** +- maxLevelDb +- showRealtimeDb +- alertSoundEnabled +- avgWindowSec +- baselineDb + +#### 8.1.5 时间加权平均 + +**公式:** +$$ \text{avg} = \frac{\sum_{i} v_i \times (t_{i+1} - t_i)}{\sum_{i} (t_{i+1} - t_i)} $$ + +--- + +## 9. 配置参数体系 + +### 9.1 常量定义 + +#### 9.1.1 分析参数 + +```typescript +NOISE_ANALYSIS_SLICE_SEC = 30; // 切片时长 30 秒 +NOISE_ANALYSIS_FRAME_MS = 50; // 帧间隔 50ms +NOISE_SCORE_THRESHOLD_DBFS = -50; // 评分阈值 -50dBFS +NOISE_SCORE_SEGMENT_MERGE_GAP_MS = 500; // 事件段合并间隔 500ms +NOISE_SCORE_MAX_SEGMENTS_PER_MIN = 6; // 每分钟最大事件段数 6 +NOISE_REALTIME_CHART_SLICE_COUNT = 1; // 实时图表切片数 1 +``` + +#### 9.1.2 报告参数 + +```typescript +DEFAULT_NOISE_REPORT_RETENTION_DAYS = 14; // 默认保留 14 天 +MIN_NOISE_REPORT_RETENTION_DAYS = 1; // 最小保留 1 天 +MAX_NOISE_REPORT_RETENTION_DAYS_FALLBACK = 365; // 最大保留 365 天 +``` + +### 9.2 设置管理 + +#### 9.2.1 固定参数 + +为保证评分口径稳定,避免用户通过调整参数"刷分",以下参数固定为程序内常量: +- sliceSec +- frameMs +- scoreThresholdDbfs +- segmentMergeGapMs +- maxSegmentsPerMin + +#### 9.2.2 可配置参数 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| maxLevelDb | number | 55 | 最大允许噪音级别(显示分贝) | +| baselineDb | number | 40 | 手动基准显示分贝 | +| showRealtimeDb | boolean | true | 是否显示实时分贝 | +| avgWindowSec | number | 1 | 噪音平均时间窗(秒) | +| alertSoundEnabled | boolean | false | 超阈值提示音开关 | + +--- + +## 10. 类型定义 + +### 10.1 核心类型 + +#### 10.1.1 噪音帧采样 + +```typescript +interface NoiseFrameSample { + t: number; // 时间戳 + rms: number; // 均方根值 + dbfs: number; // 分贝值 (dBFS) + peak?: number; // 峰值 +} +``` + +#### 10.1.2 噪音切片原始统计 + +```typescript +interface NoiseSliceRawStats { + avgDbfs: number; // 平均分贝 + maxDbfs: number; // 最大分贝 + p50Dbfs: number; // 中位数分贝 + p95Dbfs: number; // 95分位数分贝 + overRatioDbfs: number; // 超阈值比例 + segmentCount: number; // 事件段数量 + sampledDurationMs?: number; // 采样时长 + gapCount?: number; // 缺口数量 + maxGapMs?: number; // 最大缺口时长 +} +``` + +#### 10.1.3 噪音切片显示统计 + +```typescript +interface NoiseSliceDisplayStats { + avgDb: number; // 平均显示分贝 + p95Db: number; // 95分位数显示分贝 +} +``` + +#### 10.1.4 噪音评分明细 + +```typescript +interface NoiseScoreBreakdown { + sustainedPenalty: number; // 持续噪音惩罚 + timePenalty: number; // 时间惩罚 + segmentPenalty: number; // 事件段惩罚 + thresholdsUsed: { + scoreThresholdDbfs: number; // 使用的评分阈值 + segmentMergeGapMs: number; // 使用的合并间隔 + maxSegmentsPerMin: number; // 使用的最大事件段数 + }; + sustainedLevelDbfs: number; // 持续电平 + overRatioDbfs: number; // 超阈值比例 + segmentCount: number; // 事件段数量 + minutes: number; // 时长(分钟) + durationMs?: number; // 物理时长 + sampledDurationMs?: number; // 采样时长 + coverageRatio?: number; // 覆盖率 +} +``` + +#### 10.1.5 噪音切片摘要 + +```typescript +interface NoiseSliceSummary { + start: number; // 开始时间戳 + end: number; // 结束时间戳 + frames: number; // 帧数 + raw: NoiseSliceRawStats; // 原始统计 + display: NoiseSliceDisplayStats; // 显示统计 + score: number; // 评分 + scoreDetail: NoiseScoreBreakdown; // 评分明细 +} +``` + +#### 10.1.6 实时数据点 + +```typescript +interface NoiseRealtimePoint { + t: number; // 时间戳 + dbfs: number; // 分贝值 (dBFS) + displayDb: number; // 显示分贝 +} +``` + +#### 10.1.7 噪音流快照 + +```typescript +interface NoiseStreamSnapshot { + status: NoiseStreamStatus; // 流状态 + realtimeDisplayDb: number; // 实时显示分贝 + realtimeDbfs: number; // 实时分贝 (dBFS) + maxLevelDb: number; // 最大允许级别 + showRealtimeDb: boolean; // 是否显示实时分贝 + alertSoundEnabled: boolean; // 提示音开关 + ringBuffer: NoiseRealtimePoint[]; // 环形缓冲区快照 + latestSlice: NoiseSliceSummary | null; // 最新切片 +} +``` + +#### 10.1.8 噪音流状态 + +```typescript +type NoiseStreamStatus = + | "initializing" // 初始化中 + | "quiet" // 安静 + | "noisy" // 嘈杂 + | "permission-denied" // 权限拒绝 + | "error"; // 错误 +``` + +--- + +## 附录 + +### A. 术语表 + +| 术语 | 英文 | 说明 | +|------|------|------| +| 均方根 | RMS (Root Mean Square) | 衡量音频信号强度的标准方法 | +| 分贝满刻度 | dBFS (Decibels relative to Full Scale) | 数字音频的标准分贝单位,范围 -100 到 0 dB | +| 显示分贝 | Display dB | 用于用户界面展示的分贝值,范围 20 到 100 dB | +| 切片 | Slice | 固定时间窗口(默认 30 秒)内的噪音数据聚合 | +| 帧 | Frame | 单次音频采样(默认 50ms) | +| 事件段 | Segment | 独立的噪音事件,通过合并窗口(500ms)合并 | + +### B. 参数固定策略 + +为保证统计口径稳定,当前版本将"分析与评分"的高级参数固定为程序内常量: + +| 参数 | 值 | 说明 | +|------|-----|------| +| frameMs | 50ms | 约 20fps | +| sliceSec | 30s | 切片时长 | +| scoreThresholdDbfs | -50 dBFS | 评分阈值 | +| segmentMergeGapMs | 500ms | 事件段合并间隔 | +| maxSegmentsPerMin | 6 | 每分钟最大事件段数 | + +### C. 技术栈 + +- **音频处理**:Web Audio API +- **数据存储**:localStorage +- **前端框架**:React 18 +- **构建工具**:Vite 5 +- **类型系统**:TypeScript 5.4 + +