天气组件、倒计时组件微调。引入浏览器组件。
This commit is contained in:
lincube
2026-03-04 03:41:59 +08:00
parent e8276c4d1e
commit 3d22c04a04
31 changed files with 3258 additions and 576 deletions

771
noise.md Normal file
View File

@@ -0,0 +1,771 @@
# 沉浸式时钟噪音计算与评分技术文档
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 dBUI 展示口径),不进入评分链路**
- 校准(`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 数据规范化与校验
**精度控制:**
- dBFS3 位小数
- overRatioDbfs4 位小数
- 显示分贝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