XiTune 技术架构 v1.0 · AI + 手动调音套装
文档定位
- 产品定位:Xisound L2 层"羲音调音师"——AI 自动 / AI 辅助 / 手动三模式调音套装
- 形态:独立 web app(车载/现场离线场景必须能独立启动),亦支持从 XiStudio deep-link 呼起
- 上游:D0 产品矩阵 V1.1 · D3-FE-ARCH-001 顶层架构 · D3-FE-ARCH-003 共享 UI kit 架构
- 下游:D3-FE-PLAN-007 XiTune v0.9 实现 plan
1. 产品定位与目标
1.1 产品定位
XiTune = 羲音调音师(Y1Q2 v0.9 灯塔 · Y1Q4 v1.0 商用 · Y3H2 v2.0 AI 版)。用户在车载或现场环境做声学调优,需要:
- 离线工作能力(车内网络不稳定)
- 与 XiMic / XiCal 硬件实时联动
- 手动细调 + AI 辅助 + AI 全自动三档可切换
- 多位置声场优化(驾驶员位 / 副驾 / 后排)
- A/B 盲听对比与方案管理
1.2 核心能力
- Session Manager:调音会话管理(新建 / 多工位协同 / 版本归档)
- Measurement:麦采集 / 频响测量 / 时钟对齐
- Auto-Tune Engine:AI 自动调音(XiMind 驱动,Y3H2 GA)
- Manual Tuner:EQ / Dynamic / Delay 手动面板
- A/B Comparator:方案对比 / 盲听
- Report Generator:调音报告 PDF 导出
1.3 版本矩阵
| 版本 | 时点 | 覆盖能力 |
|---|---|---|
| v0.9 灯塔 | Y1Q2 | Session + Measurement + Manual Tuner + A/B 基础 |
| v1.0 商用 | Y1Q4 | 完整 6 大模块 · Report 导出 · 首次服务灯塔 OEM 量产调音 |
| v2.0 AI 版 | Y3H2 | XiMind 驱动全自动调音 + 跨车型知识推荐 |
1.4 与 XiForge 产出的 Tuning UI 的关系
- XiForge 的 Tuning UI Designer 产出
TuningUIDocumentJSON - XiTune 的 Manual Tuner 加载该 JSON → 渲染成调参面板
- 两者通过
@xi/protocol的 TuningUIDocument zod schema 契约解耦 - XiForge 改 UI schema → XiTune 自动适配(前提:同 major 版本)
2. 架构总览
2.1 XiTune 在 Monorepo 中的角色
graph TB
subgraph App["apps/xi-tune(独立 app · web + 可选离线缓存)"]
Router["vue-router"]
Shell["Shell(自有,比 Studio 简)"]
subgraph Modules["6 大功能模块"]
SessionMgr["Session Manager"]
Measurement["Measurement"]
AutoTune["Auto-Tune Engine"]
ManualTuner["Manual Tuner"]
ABCompare["A/B Comparator"]
Report["Report Generator"]
end
end
subgraph Packages["packages/"]
UIKit["@xi/ui-kit"]
Protocol["@xi/protocol"]
StoreCore["@xi/store-core"]
DSPUtils["@xi/dsp-utils"]
AISDK["@xi/ai-sdk"]
end
subgraph Hardware["外部硬件"]
XiMic["XiMic<br/>数字麦"]
XiCal["XiCal<br/>多路采集"]
Amp["XiAmp / 第三方功放"]
end
subgraph Entry["启动入口"]
Direct["独立启动<br/>tune.xisound.com"]
FromStudio["XiStudio<br/>deep-link 呼起"]
end
Entry --> Router
Router --> Shell --> Modules
Measurement --> XiMic
Measurement --> XiCal
ManualTuner --> Amp
AutoTune --> AISDK
Modules --> UIKit
Modules --> Protocol
Modules --> StoreCore
Measurement --> DSPUtils
ManualTuner --> DSPUtils
classDef app fill:#FFF4E6,stroke:#D4A574,stroke-width:3px,color:#1A2332
classDef module fill:#FFFFFF,stroke:#6B7280,stroke-width:1px
classDef pkg fill:#F5F2EA,stroke:#6B7280,stroke-width:1px
classDef hw fill:#F0E6FA,stroke:#9D4EDD,stroke-width:2px
classDef entry fill:#E6F7FF,stroke:#1890FF,stroke-width:2px
class App,Router,Shell app
class SessionMgr,Measurement,AutoTune,ManualTuner,ABCompare,Report module
class UIKit,Protocol,StoreCore,DSPUtils,AISDK pkg
class XiMic,XiCal,Amp hw
class Direct,FromStudio entry
class App,Modules xySgL2; class Packages,Entry xySgL4; class Hardware xySgL1;
2.2 启动场景
场景 A · 独立启动
用户访问 https://tune.xisound.com/(或桌面快捷方式)→ 登录 → 选择/新建 session → 开始调音。
不需要 XiStudio 在线,但登录状态通过 SSO 与 XiStudio 共享。
场景 B · 从 XiStudio 呼起
- XiStudio 用户在某个工程中点"调音"
- Studio 构造
xi://xi-tune/session/new?project=proj001&token=tmpXXX在新 tab 打开 - XiTune 启动时解析 URL,自动用 token 鉴权 + 加载工程上下文 + 预填 session
2.3 技术栈
| 层 | 选型 | 来源 |
|---|---|---|
| 框架 | Vue 3.4+ | D3-FE-ARCH-001 §7 |
| 路由 | vue-router 4 | 同上 |
| 状态 | Pinia 2+ | 同上 |
| UI | @xi/ui-kit(含 EQCurveEditor / SpectrumChart / LevelMeter) | D3-FE-ARCH-003 |
| DSP | @xi/dsp-utils(FFT / biquad / 响度) | 同上 |
| 硬件 | @xi/protocol 的 WebSocket + 后端代理 | 同上 |
| AI | @xi/ai-sdk | 同上 |
| jsPDF + html2canvas | 新引入 | |
| 离线缓存 | Service Worker + IndexedDB | 新引入(Y1Q4 GA 前必须) |
3. 目录结构
apps/xi-tune/
├── src/
│ ├── main.ts
│ ├── App.vue
│ ├── router/
│ │ ├── index.ts # /sessions, /session/:id, /measurement, /tuner, /compare, /report
│ │ ├── guards.ts # deep-link token 换取 + session 加载
│ │ └── intent.ts # intent-based route(intent/auto-tune 等)
│ ├── layouts/
│ │ └── TuneLayout.vue # 简化 Shell(顶部栏 + 主区 + 电平表侧栏)
│ ├── views/
│ │ ├── SessionListView.vue # /sessions
│ │ ├── SessionView.vue # /session/:id(会话主界面)
│ │ ├── MeasurementView.vue # /measurement
│ │ ├── TunerView.vue # /tuner(手动/AI 切换)
│ │ ├── CompareView.vue # /compare(A/B)
│ │ └── ReportView.vue # /report(报告)
│ ├── components/
│ │ ├── session/
│ │ │ ├── SessionCard.vue
│ │ │ ├── SessionCreateModal.vue
│ │ │ └── CollaboratorList.vue
│ │ ├── measurement/
│ │ │ ├── DeviceConnect.vue # XiMic/XiCal 连接
│ │ │ ├── MeasureSetup.vue # 测量配置(扫频/位置)
│ │ │ ├── MeasureRunner.vue # 执行测量
│ │ │ └── MeasureResult.vue # 结果展示(频响图)
│ │ ├── tuner/
│ │ │ ├── TunerModeSwitch.vue # 手动/AI辅助/AI自动
│ │ │ ├── EQPanel.vue # EQ 面板(用 <EQCurveEditor>)
│ │ │ ├── DynamicPanel.vue
│ │ │ ├── DelayPanel.vue
│ │ │ ├── ZonePanel.vue # 多音区
│ │ │ └── DynamicTuningPanel.vue # 加载 XiForge 的 TuningUIDocument
│ │ ├── compare/
│ │ │ ├── ABPlayer.vue # A/B 盲听
│ │ │ └── ScenarioList.vue
│ │ └── report/
│ │ ├── ReportPreview.vue
│ │ └── ReportExporter.vue
│ ├── stores/
│ │ ├── useSessionStore.ts
│ │ ├── useMeasurementStore.ts
│ │ ├── useTunerStore.ts # EQ/Dyn/Delay 参数
│ │ ├── useAutoTuneStore.ts # AI 驱动状态
│ │ ├── useCompareStore.ts
│ │ └── useReportStore.ts
│ ├── services/
│ │ ├── hardwareApi.ts # XiMic/XiCal 硬件通信(经后端)
│ │ ├── ampApi.ts # XiAmp 参数下发
│ │ ├── pdfExport.ts # 报告 PDF 生成
│ │ └── offlineCache.ts # Service Worker 注册 + 缓存策略
│ └── types/
│ ├── Session.ts
│ ├── Measurement.ts
│ └── TuningScenario.ts
├── public/
│ ├── favicon.svg
│ └── manifest.webmanifest # PWA manifest(支持桌面安装)
├── vite.config.ts
├── tsconfig.json
├── package.json
└── README.md
4. 核心模块详细设计
4.1 Session Manager
数据模型:
// types/Session.ts
export interface TuningSession {
id: string
name: string
vehicleInfo: { // 车型信息
make: string
model: string
year: number
cabinType?: string
}
ampInfo: { // 功放信息
deviceId: string
firmwareVersion: string
channelCount: number
}
status: 'draft' | 'measuring' | 'tuning' | 'verified' | 'published'
collaborators: string[] // 多工位协同用户
scenarios: TuningScenario[] // 不同音频风格方案(默认/流行/人声/沉浸...)
activeScenarioId?: string
createdAt: number
updatedAt: number
projectRef?: string // 若从 XiStudio 呼起,关联的 XiStudio 工程 ID
}
export interface TuningScenario {
id: string
name: string
description: string
measurements: MeasurementData[]
tunerState: TunerState // EQ/Dyn/Delay 参数快照
rating?: number // 盲听评分
}
Store API:
export const useSessionStore = defineStore('xi-tune-session', () => {
const sessions = ref<TuningSession[]>([])
const activeSession = ref<TuningSession | null>(null)
const activeScenario = computed(() => /* from activeSession.scenarios */)
async function list(): Promise<TuningSession[]>
async function create(info: CreateSessionParams): Promise<TuningSession>
async function open(id: string): Promise<void>
async function addScenario(scenario: TuningScenario): Promise<void>
async function switchScenario(scenarioId: string): Promise<void>
async function inviteCollaborator(email: string): Promise<void>
async function archive(id: string): Promise<void>
async function save(): Promise<void>
async function loadFromDeepLink(params: DeepLinkParams): Promise<void>
return { sessions, activeSession, activeScenario, ... }
})
多工位协同(v1.0 基础):
- 同一 session 多用户进入 → WebSocket 广播操作事件 → 其他用户实时同步
- 冲突策略:最后写入覆盖 + 操作日志(供回溯)
- 详细:留到 v2.0 设计 CRDT,v1.0 先保证基本可用
4.2 Measurement
流程:
sequenceDiagram
participant User
participant UI as MeasurementView
participant MStore as useMeasurementStore
participant HW as hardwareApi
participant BE as Backend
participant Mic as XiMic/XiCal
User->>UI: 选择位置(驾驶员位)+ 扫频参数
UI->>MStore: startMeasurement(config)
MStore->>HW: connectDevice(micId)
HW->>BE: WS 建立
BE-->>Mic: 激活采集
MStore->>BE: 发送扫频信号
BE-->>Mic: 播放扫频
Mic-->>BE: 录音数据
BE-->>MStore: 实时 FFT 数据(level-meter / fft-snapshot)
MStore-->>UI: 更新 SpectrumChart(实时可视化)
MStore->>MStore: 计算频响曲线(@xi/dsp-utils)
MStore-->>UI: 展示 MeasureResult
UI->>User: 完成 · 可导出 / 下一位置
核心数据:
export interface MeasurementData {
id: string
position: 'driver' | 'passenger' | 'rear-left' | 'rear-right' | 'custom'
customLabel?: string
timestamp: number
signalType: 'sweep' | 'pink-noise' | 'mls' | 'chirp'
rawSamples?: Float32Array // 原始录音(可选存)
frequencyResponse: { // 计算后的频响
freqs: Float32Array
magnitudeDb: Float32Array
phaseDeg: Float32Array
}
thd?: number
snr?: number
roomConditions?: {
temperature?: number
humidity?: number
noiseFloorDb?: number
}
}
4.3 Auto-Tune Engine
Y1Q4 v1.0(规则引擎版):
- 根据测量频响 + 目标曲线(行业标准如 Harman / ISO 等)
- 规则引擎计算 EQ 补偿(反向滤波 + 心理声学平滑)
- 应用到 Manual Tuner 的 EQ Panel(用户可微调)
Y3H2 v2.0(AI 版):
- 调用
@xi/ai-sdk的 Function Calling - AI 分析多位置测量 + 车型 + 目标风格 → 生成完整调音方案(EQ / Dyn / Delay / Zone)
- 支持自然语言调整:"声音再温暖一些" → AI 调整中低频 EQ
- RAG 检索历史优秀方案作为 few-shot
Store API:
export const useAutoTuneStore = defineStore('xi-tune-auto', () => {
const mode = ref<'manual' | 'ai-assist' | 'ai-full'>('manual')
const running = ref(false)
const suggestions = ref<AutoTuneSuggestion[]>([])
async function runRuleBasedTune(measurements: MeasurementData[], targetCurve: string): Promise<TunerState>
async function runAIAssistTune(prompt: string, context: AutoTuneContext): Promise<AutoTuneSuggestion[]>
async function runAIFullTune(session: TuningSession): Promise<TunerState>
function applySuggestion(suggestion: AutoTuneSuggestion): void
return { mode, running, suggestions, ... }
})
4.4 Manual Tuner
三类面板 + 一类动态面板:
- EQ Panel(
<EQPanel>):使用@xi/ui-kit的<EQCurveEditor>+ 多频段编辑 - Dynamic Panel(
<DynamicPanel>):压缩/限幅/门限参数 - Delay Panel(
<DelayPanel>):通道延时(声场校正) - Zone Panel(
<ZonePanel>):多音区独立调音 - Dynamic Tuning Panel(
<DynamicTuningPanel>):加载 XiForge 导出的 TuningUIDocument JSON 动态渲染
TuningUIDocument 渲染器:
<!-- components/tuner/DynamicTuningPanel.vue -->
<template>
<div v-if="doc" class="tuning-layout">
<component
v-for="widget in doc.widgets"
:key="widget.id"
:is="resolveWidgetComponent(widget.type)"
v-bind="widget.props"
:model-value="getBoundValue(widget)"
@update:model-value="onWidgetUpdate(widget, $event)"
/>
</div>
</template>
<script setup lang="ts">
import { z } from 'zod'
import { TuningUIDocumentSchema } from '@xi/protocol'
const props = defineProps<{ uiJson: unknown }>()
const doc = computed(() => {
const parsed = TuningUIDocumentSchema.safeParse(props.uiJson)
return parsed.success ? parsed.data : null
})
// ... 解析 widgets 并绑定到 useTunerStore
</script>
参数下发:
- 用户改动参数 →
useTunerStore.updateParam(key, value) - Store 通过
@xi/protocol的control-command发送到后端 - 后端转发到 XiAmp(或通过 XiCore 固件)实时生效
- 实时反馈:后端回传
audio-engine-event→ Store 更新电平 / 频谱可视化
4.5 A/B Comparator
核心流程:
- 用户保存多个 TuningScenario(每个代表一种调音方案)
- 点击 "A/B 对比" 进入
<CompareView> - 可盲听切换:UI 不显示当前是 A 还是 B(避免视觉偏差)
- 用户评分(1-5 星 + 文字描述)
- 结果保存到 session 的 scenario.rating
实现难点:
- 切换时的无缝衔接(避免参数突变产生爆音)→ 后端做 crossfade
- 盲听状态的显示隐藏 → useCompareStore.blindMode
4.6 Report Generator
报告内容:
- 封面:车型 + 日期 + 调音师
- 测量数据:每个位置的频响曲线图
- 调音方案:最终 EQ / Dyn / Delay / Zone 参数表
- A/B 对比:scenarios 评分
- 附录:原始数据 JSON 导出
技术方案:
- 前端用 HTML + Tailwind 排版报告
html2canvas截取为 canvasjsPDF生成多页 PDF- 离线支持:无需后端即可导出
5. 硬件联动设计(XiMic / XiCal / XiAmp)
5.1 架构选择
纯 web 不能直接访问 USB/串口,因此:
- Y1 方案:前端 ↔ 后端 WebSocket ↔ 硬件代理服务(run on local PC,USB/serial 驱动由代理)
- Y2 Tauri 方案(可选):若离线性要求提高,打包成 Tauri 桌面 app 直接访问硬件
5.2 硬件协议(经 @xi/protocol)
| 消息类型 | 方向 | 用途 |
|---|---|---|
hw-device-list |
BE→FE | 可用设备列表 |
hw-connect |
FE→BE | 连接指定设备 |
hw-start-capture |
FE→BE | 开始采集 |
hw-capture-data |
BE→FE | 采集数据流(Float32 序列化) |
hw-play-signal |
FE→BE | 播放扫频/粉噪 |
hw-status |
BE→FE | 设备状态(采样率/通道数/温度等) |
设计约束:
- 硬件消息走独立 WebSocket 端点
wss://backend/ws/hardware - 与主 audio-engine WebSocket 解耦
6. 离线能力(PWA)
6.1 离线使用场景
- 现场调音 Wi-Fi 不稳
- 灯塔车型在封闭测试场地
6.2 离线策略
| 资源 | 策略 |
|---|---|
| 静态资源(HTML/CSS/JS) | Service Worker cache-first |
| @xi/ui-kit 组件 | 打包到主 bundle |
| Session 数据 | IndexedDB 持久化;重连后增量同步 |
| Measurement 数据 | IndexedDB 本地保存;用户可选择上传时机 |
| 硬件代理 | 本地运行(不依赖云端) |
| AI Copilot | 离线不可用(友好降级提示) |
实现:
vite-plugin-pwa生成 SW- 自定义 IndexedDB wrapper(用
idb库) - 冲突处理:本地 draft 合并到服务端用"最近修改胜出" + 操作日志
7. 路由设计
const routes: RouteRecordRaw[] = [
{
path: '/',
component: TuneLayout,
children: [
{ path: '', redirect: '/sessions' },
{ path: 'sessions', component: SessionListView },
{
path: 'session/:id',
component: SessionContextLayout,
children: [
{ path: '', redirect: 'tuner' },
{ path: 'measurement', component: MeasurementView },
{ path: 'tuner', component: TunerView },
{ path: 'compare', component: CompareView },
{ path: 'report', component: ReportView },
],
},
{ path: 'intent/:intentName', component: IntentHandlerView }, // deep-link 意图分发
],
},
{ path: '/login', component: LoginView },
{ path: '/:pathMatch(.*)*', component: NotFoundView },
]
Intent 支持(来自 XiStudio deep-link):
intent/auto-tune→ 自动新建 session + 执行 AI 调音intent/measure→ 新建 session + 直接进入 Measurement
8. 测试策略
8.1 单元测试
- Store CRUD + 状态转换
- PDF 导出模板测试(快照)
- TuningUIDocument 解析兼容性测试
8.2 e2e 测试
| 场景 | 步骤 |
|---|---|
| 新建 session → 测 3 位置 → 自动调音 → 保存 | 完整核心流程 |
| 加载 XiForge 导出的 TuningUIDocument | 验证动态面板渲染 |
| 离线模式保存 session → 恢复网络 → 同步 | PWA 离线能力 |
| 从 XiStudio deep-link 进入 auto-tune intent | 跨 app 联动 |
| 生成 PDF 报告 | 模板正确性 |
| A/B 盲听切换 | UI 隐藏当前方案 |
8.3 硬件集成测试
- 模拟 XiMic 数据输入验证频响计算
- 硬件代理本地启动 + 断连重连
9. 性能与可用性
9.1 性能基线
- 测量启动延迟:< 500ms
- FFT 实时可视化:60 FPS
- PDF 生成(含 5 张图):< 5s
- 参数调整到声音生效:< 200ms(后端同步延迟占大头)
9.2 可用性
- 所有关键操作有 Undo/Redo(useTunerStore 维护操作栈)
- 误触保护:测量/调音过程中的破坏性操作需二次确认
- 音量保护:切换方案时自动 soft-mute 避免爆音
10. DQ 与风险
10.1 新增 DQ
| DQ 编号 | 问题 | 建议 |
|---|---|---|
| DQ-TUNE-01 | 硬件代理是否与 XiProbe 共用一个 | Y1 分离(各自独立);Y2 评估统一为 XiHW Agent |
| DQ-TUNE-02 | 多工位协同是否启用 CRDT | v1.0 不用(简单 last-write-wins + 日志);v2.0 评估 |
| DQ-TUNE-03 | 报告 PDF 是否云端生成 vs 纯前端 | v1.0 纯前端(离线友好);v2.0 若模板复杂可云端 |
| DQ-TUNE-04 | TuningUIDocument 加载失败的降级策略 | 降级到硬编码的 EQ/Dyn/Delay 三面板 |
10.2 继承的 DQ
- DQ-05(SSO)/ DQ-07(ai-sdk 契约)
10.3 风险
| 风险 | 缓解 |
|---|---|
| 现场 Wi-Fi 不稳导致 WS 断连 | 硬件代理本地运行 + 自动重连 + 离线草稿 |
| 不同车型麦克风位置偏差大 | 支持自定义位置 + 模板车型库 |
| AI 调音方案与主观听感偏差 | AI 模式总有"恢复手动"按钮 + 人工微调 |
| PDF 渲染在低端设备慢 | Web Worker 离屏渲染 + 分步生成 |
11. 版本与变更记录
| 版本 | 日期 | 作者 | 说明 |
|---|---|---|---|
| v1.0 | 2026-05-08 | work-cline | 初稿 · 6 大模块 + 硬件联动 + PWA 离线 + TuningUIDocument 动态加载 |
附录 A · 引用
- D3-FE-ARCH-001 顶层架构(§5.3 XiTune 概览)
- D3-FE-ARCH-003 共享 UI kit 架构(§2 @xi/ui-kit EQCurveEditor / SpectrumChart)
- D3-FE-ARCH-004 实现 plan 总纲(§2.7 PLAN-007)
- D2-P1 XiStudio tech-arch v2.0(deep-link 呼起方)
- D2-P9 XiForge tech-arch(TuningUIDocument 产出方)