Channel Map Module Design (channel_map_v1)
概述
channel_map_v1 是多通道路由映射模块。每个输出通道可配置 N 个输入通道源(顺序列表 + 下拉选择),支持多 Port 输入,支持通道名称编辑。
参数
| 参数 ID | 类型 | 默认值 | 说明 |
|---|---|---|---|
enable |
bool | true | 模块启用/禁用 |
mapOutCount |
int | 20 | 输出通道数 |
mapSrcCount#${outCh} |
int | 0 | 输出通道 outCh 的源槽数量 |
mapSrc#${outCh}_${slotIdx} |
int | -1 | 输出 outCh 第 slotIdx 槽的绝对输入通道索引(-1 = 未分配) |
outputName#${outCh} |
string | '' | 输出通道名称(可编辑) |
绝对通道索引
输入通道按连入 Port 顺序扁平化编号:
Port 0 (2ch): absIdx 0 → P0-Ch0,absIdx 1 → P0-Ch1
Port 1 (4ch): absIdx 2 → P1-Ch0,absIdx 3 → P1-Ch1,absIdx 4 → P1-Ch2,absIdx 5 → P1-Ch3
显示名称优先使用导线(连线)上携带的 channelNames[ch],无名称时显示 P{portIdx}-Ch{chIdx}。
多 Port 输入检测
const inputPorts = computed(() =>
linkStore.connections
.filter(c => c.target.instanceId === instanceId)
.map((c, portIdx) => {
const srcDef = linkStore.getModuleDef(c.source.instanceId)
const srcMod = linkStore.getModule(c.source.instanceId)
const ch = srcMod?.config?.channels ?? srcDef?.outputs?.[0]?.channels ?? 2
return { portIdx, conn: c, channels: ch }
})
)
const availableInputChannels = computed(() => {
const list: { absIdx: number; label: string }[] = []
let absIdx = 0
inputPorts.value.forEach(port => {
for (let ch = 0; ch < port.channels; ch++) {
const wireName = port.conn.channelNames?.[ch]
const displayName = wireName?.trim() || `P${port.portIdx}-Ch${ch}`
list.push({ absIdx, label: `[P${port.portIdx}] ${displayName}` })
absIdx++
}
})
return list
})
UI 布局
┌─ Channel Map 调音 ─────────────────────────────────┐
│ 输出通道数: [20] 输入: 4ch (2 ports) ⚠ 无输入连线 │
├────────────────────────────────────────────────────┤
│ ┌──── Out 1 ─── [1 源] [+ 添加源] [✕清空] ────┐ │
│ │ ① [P0] L (左) ▼ [✕] │ │
│ └────────────────────────────────────────────────┘ │
│ ┌──── Out 2 ─── [0 源] [+ 添加源] [✕清空] ────┐ │
│ │ 无混入源(静音) │ │
│ └────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
- 每个输出通道为独立卡片,可展开源列表
- 「+ 添加源」增加一个槽(初始为"未分配")
- 每个槽:序号圆点 + 下拉框(选择输入通道)+ 「✕」移除按钮
- 「✕清空」一键清空该输出所有源槽(设为静音)
- 头部显示活跃源数量(源 absIdx ≥ 0 的槽数)
- 可选字段:输出通道名称(inline text input,保存至
outputName#${outCh})
操作逻辑
添加源
function addSource(outCh: number) {
const count = getSourceCount(outCh)
setSourceCount(outCh, count + 1) // mapSrcCount#outCh += 1
setMapSrc(outCh, count, -1) // mapSrc#outCh_count = -1 (未分配)
}
移除源(槽位前移)
function removeSource(outCh: number, slotIdx: number) {
const count = getSourceCount(outCh)
for (let i = slotIdx; i < count - 1; i++) {
setMapSrc(outCh, i, getMapSrc(outCh, i + 1)) // 前移
}
setSourceCount(outCh, count - 1)
}
清空输出
持久化
// 输出通道数
linkStore.setParamValue(instanceId, 'mapOutCount', outputCount)
send({ type: 'set_param', instanceId, paramId: 'mapOutCount', value: outputCount })
// 槽数
linkStore.setParamValue(instanceId, `mapSrcCount#${outCh}`, count)
send({ type: 'set_param', instanceId, paramId: `mapSrcCount#${outCh}`, value: count })
// 源映射
linkStore.setParamValue(instanceId, `mapSrc#${outCh}_${slotIdx}`, absInputIdx)
send({ type: 'set_param', instanceId, paramId: `mapSrc#${outCh}_${slotIdx}`, value: absInputIdx })
// 通道名
linkStore.setParamValue(instanceId, `outputName#${outCh}`, name)
send({ type: 'set_param', instanceId, paramId: `outputName#${outCh}`, value: name })
DSP 内存布局
| Offset | Size | 说明 |
|---|---|---|
| 0 | 1 | enable |
| 1 | 4 | mapOutCount |
| 5 | 64 × 4 | srcCount[0..63] (int,每输出通道的源数量) |
| 261 | 64 × 64 × 4 | srcMap[outCh][slotIdx] (int,绝对输入通道索引) |
Total: ~16645 bytes(支持最大 64 输出 × 64 槽)
与旧版差异
| 特性 | 旧版(checkbox 矩阵) | 新版(源列表 + 下拉框) |
|---|---|---|
| 参数 key | mapCell#${outCh}_${inCh} |
mapSrc#${outCh}_${slotIdx} |
| 显示方式 | N×M 表格(列数随输入通道数增加) | 每行独立卡片,槽数可配置 |
| 可读性 | 输入通道多时列过宽 | 始终紧凑,支持命名显示 |
| 顺序语义 | 无(集合) | 有(槽 0 优先级最高) |