AWE 自定义模块数据结构分析
源码路径:
../source/dspc_xisnd/分析目标:awe_modXisndDemomInstance及其依赖的所有 AWE 框架结构体 用途:作为前端数据模型重新设计的参考依据
一、整体架构概览
AudioWeaver (AWE) 框架采用 C 语言模拟面向对象,核心结构体嵌套关系如下:
awe_modXisndDemomInstance ← 具体算法模块实例
└── ModuleInstanceDescriptor ← 所有模块的通用实例基类(32 bytes)
└── ModInstanceDescriptor ← 最基础的对象实例头(12 bytes)
└── pModClassDescriptor → ModClassModule ← 类描述符(vtable,40 bytes)
└── pWires[] → WireInstance ← 输入/输出/临时 wire(每条 wire 独立描述音频流格式)
└── m_pBoundPin → IOPinDescriptor ← 绑定的硬件 I/O pin
内存堆内独立分配:
├── TuningBuffer (80,000 words) ← 在线调音缓冲区
└── AlgoMem (3,000,116 words) ← 算法全部工作内存
└── adsp_v1_platform ← 算法平台对象(布局在 AlgoMem 起始处)
├── ptr_FunTab → adsp_audio_vtbl_t ← 算法 vtable
└── ptr_Param → HandlWrapper ← 初始化参数包装
├── mFmtInput → MediaFmt ← 输入流格式
└── mFmtOutput → MediaFmt ← 输出流格式
二、awe_modXisndDemomInstance 结构体详解
2.1 头文件定义(include/ModXisndDemom.h,最新版本)
typedef struct _awe_modXisndDemomInstance {
ModuleInstanceDescriptor instance; // 基类,32 bytes
INT32 enable; // 算法使能标志
UINT32 VehicleCfg; // 车型配置
UINT32 AlgoChanNum; // 算法处理通道数
UINT32 NumOutChan; // 输出通道数
UINT32 MemSize_Algo; // 算法内存大小(单位: word)
UINT32 MemSize_Arch; // 架构内存大小(单位: word)
UINT32 MemSize_Tune; // 调音内存大小(单位: word)
UINT32* TuningBuffer; // 在线调音缓冲区指针
UINT32* AlgoMem; // 算法全量内存指针
} awe_modXisndDemomInstance;
注:
output/release/customModule/include/ModXisndDemom.h是旧版导出文件,字段名不同(xisndVehicleCfg、xisndMemSize_algo等)且缺少AlgoChanNum/NumOutChan两个字段。应以include/ModXisndDemom.h为准。
2.2 完整字段说明
| 序号 | 字段名 | 类型 | 属性 | 说明 |
|---|---|---|---|---|
| 0 | enable |
INT32 | 公开 | 算法使能(0=关闭,1=开启) |
| 1 | VehicleCfg |
UINT32 | 公开 | 车型配置,通过 Param ID=0x16670006 传递 |
| 2 | AlgoChanNum |
UINT32 | 公开 | 算法处理通道数,通过 Param ID=0x16670002 传递 |
| 3 | NumOutChan |
UINT32 | 公开 | 输出通道数 |
| 4 | MemSize_Algo |
UINT32 | 公开 | 算法核心内存需求,单位 word |
| 5 | MemSize_Arch |
UINT32 | 公开 | 架构/平台适配内存,单位 word |
| 6 | MemSize_Tune |
UINT32 | 公开 | 调音参数内存,单位 word |
| 7 | TuningBuffer |
UINT32* | 私有 | 在线调音缓冲区,分配 80,000 words |
| 8 | AlgoMem |
UINT32* | 私有 | 算法全量内存,分配 3,000,116 words |
ClassModule_PackArgCounts(7, 2) → 7 个公开参数 + 2 个私有参数(指针),共 9 个字段。
2.3 变量掩码(MASK / OFFSET)
每个可 Set/Get 的字段都有对应的掩码,用于 awe_modXisndDemomSet(mask) 的 switch-case 选择:
#define MASK_XisndDemom_enable 0x00000100 // OFFSET: 0x08
#define MASK_XisndDemom_VehicleCfg 0x00000200 // OFFSET: 0x09
#define MASK_XisndDemom_AlgoChanNum 0x00000400 // OFFSET: 0x0A
#define MASK_XisndDemom_NumOutChan 0x00000800 // OFFSET: 0x0B
#define MASK_XisndDemom_MemSize_Algo 0x00001000 // OFFSET: 0x0C
#define MASK_XisndDemom_MemSize_Arch 0x00002000 // OFFSET: 0x0D
#define MASK_XisndDemom_MemSize_Tune 0x00004000 // OFFSET: 0x0E
#define MASK_XisndDemom_TuningBuffer 0x00008000 // OFFSET: 0x0F(在线调音读写)
#define MASK_XisndDemom_AlgoMem 0x00010000 // OFFSET: 0x10
#define SETALLMASK 0xFFFFFF00 // 触发全量初始化(模块构造后调用)
TuningBuffer 的 Set 比较特殊:通过缓冲区内容区分读写命令:
- COMMAND_HEADER_WRITE = 0x44332211 → 写参数
- COMMAND_HEADER_READ = 0xAABBCCDD → 读参数
2.4 类 ID
三、ModuleInstanceDescriptor 通用基类(32 bytes)
所有 AWE 模块实例的第一个成员,称为"基类"(C 语言继承)。
typedef struct _ModuleInstanceDescriptor {
ModInstanceDescriptor instanceDescriptor; // 偏移 0,12 bytes
struct _LayoutInstance *pOwner; // 偏移 12,所属 Layout
WireInstance **pWires; // 偏移 16,wire 数组指针
void (*pProcessFunc)(void *pInstance); // 偏移 20,当前处理函数
UINT32 packedFlags; // 偏移 24,控制标志
UINT32 profileTime; // 偏移 28,性能计数(cycles × 256)
} ModuleInstanceDescriptor; // 32 bytes
packedFlags 位域布局
| 位范围 | 宏/含义 | 说明 |
|---|---|---|
| [7:0] | nInWires (via PackFlags) |
输入 wire 数量(最多 255) |
| [15:8] | nOutWires |
输出 wire 数量(最多 255) |
| [23:16] | nScratchWires |
临时 wire 数量 |
| [25:24] | MODULE_ACTIVE_MASK | 模块状态:00=Active, 01=Bypass, 10=Mute, 11=Inactive |
| [27] | MODULE_GENERAL_DEFERRED_SET | 延迟 Set 标志(在主线程中执行) |
| [31:28] | MODULE_GENERAL_MASK | 通用标志位(模块自定义) |
// Wire 数量打包
#define ClassModule_PackFlags(nIn, nOut, nScratch) \
((((nScratch) & 0xff) << 16) | (((nOut) & 0xff) << 8) | ((nIn) & 0xff))
// 模块状态常量
#define MODULE_ACTIVE 0x00000000
#define MODULE_BYPASS 0x01000000
#define MODULE_MUTE 0x02000000
#define MODULE_INACTIVE 0x03000000
四、ModInstanceDescriptor 最基础对象头(12 bytes)
typedef struct _ModInstanceDescriptor {
struct _ModInstanceDescriptor *pNextInstance; // 偏移 0,链表指针(遍历所有模块实例)
const ModClassModule *pModClassDescriptor; // 偏移 4,指向类描述符(vtable)
UINT32 nUniqueInstanceID; // 偏移 8,唯一实例 ID
} ModInstanceDescriptor; // 12 bytes
nUniqueInstanceID 是每个模块实例在 AWE 中全局唯一的 ObjectID,上位机通过该 ID 定位并操作具体模块。
五、ModClassModule 类描述符(vtable,40 bytes)
typedef struct _ModClassModule {
ModClassDescriptor modClassDescriptor; // 偏移 0,8 bytes(含 Constructor + classID)
void (*pProcessFunc)(void *pInstance); // 偏移 8,实时处理函数
void (*pBypassFunc)(void *pInstance); // 偏移 12,Bypass 函数
UINT32 (*pSet)(void *pInstance, UINT32 mask); // 偏移 16,Set 参数函数
UINT32 (*pGet)(void *pInstance, UINT32 mask); // 偏移 20,Get 参数函数
UINT32 nModuleVersion; // 偏移 24,模块版本号
UINT32 nPackedParameters; // 偏移 28,打包的参数数量(公开|私有)
UINT32 bitVectorFloat[2]; // 偏移 32,浮点参数位向量(64位)
} ModClassModule; // 40 bytes
本模块的函数表:
// awe_modXisndDemomClass 初始化
.Constructor = awe_modXisndDemomConstructor
.pProcessFunc = awe_modXisndDemomProcess
.pBypassFunc = awe_modXisndDemomBypass
.pSet = awe_modXisndDemomSet
.pGet = awe_modXisndDemomGet
.nPackedParameters = ClassModule_PackArgCounts(7, 2) // = 0x00020007
六、WireInstance 音频信号线(Wire)
Wire 是连接两个模块 Pin 之间的音频数据流描述对象,包含完整的流格式信息。
typedef struct _WireInstance {
InstanceDescriptor instanceDescriptor; // 基础实例头
Sample *buffer; // 采样缓冲区指针
float sampleRate; // 采样率(Hz)
UINT32 wireInfo1; // 打包的流格式信息 1
UINT32 wireInfo2; // 打包的流格式信息 2
UINT32 wireInfo3; // 打包的流格式信息 3
IOPinDescriptor *m_pBoundPin; // 绑定的硬件 pin(可为 NULL)
} WireInstance;
wireInfo1 位域
| 位范围 | 宏名 | 位宽 | 说明 |
|---|---|---|---|
| [9:0] | NUM_CHANNELS | 10 | 通道数(0~1023) |
| [26:10] | MAX_BLOCKSIZE | 17 | 最大 block 大小(0~131071) |
| [27] | IS_COMPLEX | 1 | 是否为复数信号 |
| [31:28] | SAMPLE_SIZE_BYTES | 4 | 每采样字节数(0~15) |
#define INFO1_PROPS(channels, maxBlockSize, complex, nSizeBytes) \
((channels & 0x3FF) | ((maxBlockSize & 0x1FFFF) << 10) | \
((complex & 1) << 27) | ((nSizeBytes & 0xF) << 28))
wireInfo2 位域
| 位范围 | 宏名 | 位宽 | 说明 |
|---|---|---|---|
| [16:0] | BLOCK_SIZE | 17 | 当前 block 大小(0~131071) |
| [22:17] | DATA_TYPE | 6 | 数据类型枚举(float32/fract32/int16 等) |
wireInfo3 位域
| 位范围 | 宏名 | 位宽 | 说明 |
|---|---|---|---|
| [9:0] | NUM_ROWS | 10 | 矩阵行数 |
| [19:10] | NUM_COLUMNS | 10 | 矩阵列数 |
| [20] | IS_IPC | 1 | 跨核 IPC 传输标志 |
| [21] | IS_PRIVATE | 1 | 私有 wire(不可被外部模块访问) |
| [22] | IS_CLOCK_MASTER | 1 | 是否为时钟主源 |
Wire 读取便利宏
ClassWire_GetChannelCount(W) // 通道数
ClassWire_GetBlockSize(W) // 当前 block 大小
ClassWire_GetMaxBlockSize(W) // 最大 block 大小
ClassWire_GetDataType(W) // 数据类型
ClassWire_GetSampleRate(W) // 采样率(float)
ClassWire_GetNumSamples(W) // 总采样数 = blockSize × channels
ClassWire_GetComplex(W) // 是否复数
ClassWire_GetNSampleSize(W) // 每采样字节数
ClassWire_GetIPC(W) // IPC 标志
ClassWire_GetPrivate(W) // 私有标志
ClassWire_GetClockMaster(W) // 时钟主源标志
七、IOPinDescriptor 硬件 I/O Pin
Pin 是硬件输入/输出端口的描述,Wire 绑定到 Pin 后才能与实际硬件交互。
| 字段 | 偏移 | 说明 |
|---|---|---|
| instanceDescriptor | 0 | 基础实例头(12 bytes) |
| pOrigBuffer | 12 | Wire 分配的原始采样缓冲区 |
| pSecondBuffer | 16 | 双缓冲第二缓冲区 |
| sampleRate | 20 | 采样率(float) |
| wireInfo1 | 24 | 同 Wire 格式(通道/maxBlockSize/复数/采样宽) |
| wireInfo2 | 28 | 同 Wire 格式(blockSize/dataType) |
| wireInfo3 | 32 | 同 Wire 格式(rows/cols/IPC/private/clockMaster) |
| ctrlFlags | 36 | 双缓冲控制标志 |
| nBoundWires | 40 | 绑定的 wire 数量 |
| boundWires[1] | 44 | 绑定 wire 数组(CoreWireDescr) |
| m_pinName[2] | 52 | Pin 名称(64位,ASCII 编码) |
| tmpCtrlFlags | 60 | 临时控制标志 |
| m_pin_flags | 64 | PIN_PUMP_MASK_FIRST / PIN_EXPORT_ONCE |
八、算法平台封装结构体
这是 xisnd 算法层自定义的 C++ 风格封装(通过 C 实现),存放在 AlgoMem 堆内存中。
adsp_v1_platform(8 bytes)
struct adsp_v1_platform {
const adsp_audio_vtbl_t* ptr_FunTab; // 算法函数表指针
HandlWrapper* ptr_Param; // 初始化/运行参数
};
adsp_audio_vtbl_t(16 bytes,算法 vtable)
struct adsp_audio_vtbl_t {
adi_adsp_err_t (*end) (adsp_v1_platform*, ...); // 销毁/关闭
adi_adsp_err_t (*process) (adsp_v1_platform*, pIn[], pOut[]);// 实时处理
adi_adsp_err_t (*set_param) (adsp_v1_platform*, param_id, buf);// 设置参数
adi_adsp_err_t (*get_param) (adsp_v1_platform*, param_id, buf);// 获取参数
};
HandlWrapper(44 bytes + 2×MediaFmt 指针)
typedef struct HandlWrapper_ {
unsigned int vehicleCfg; // 车型配置(来自 S->VehicleCfg)
unsigned int enable; // 使能(来自 S->enable)
unsigned int AlgoChanNum; // 算法通道数(来自 S->AlgoChanNum)
unsigned int AlgoMemSize; // 总算法内存 = MemSize_Algo + MemSize_Arch
unsigned int TunMemSize; // 调音内存(来自 S->MemSize_Tune)
unsigned int POTMemSize; // POT 内存大小
MediaFmt* mFmtInput; // 输入流格式
MediaFmt* mFmtOutput; // 输出流格式
void* pAlgoMem; // 算法核心内存指针
void* pTunMem; // 调音缓冲区指针(= S->TuningBuffer)
void* pPOTMem; // POT 内存指针
} HandlWrapper;
MediaFmt(28 bytes,音频流格式)
typedef struct MediaFmt_ {
unsigned int num_port; // 端口数(通常为 1)
unsigned int num_chan; // 通道数(来自 Wire)
unsigned int is_interLeaved; // 是否交织格式(1=交织)
unsigned int fmt_stream; // 流格式枚举(见 API_STREAM_FORMAT)
unsigned int num_bytePerSmp; // 每采样字节数(来自 Wire)
unsigned int num_smpPerCh; // 每通道采样数(= blockSize)
float smp_rate; // 采样率(来自 Wire)
} MediaFmt;
API_STREAM_FORMAT 枚举:
| 值 | 含义 |
|---|---|
| 0 | 16 bits |
| 1 | 24 bits |
| 2 | 32 bits |
| 3 | 32 bits with 27-factor scale |
| 4 | Float(float32) |
九、内存布局分析
9.1 AlgoMem 内存布局(初始化时 Set mask=0xFFFFFFFF)
AlgoMem (UINT32*, 3,000,116 words = ~11.4 MB)
├── [0] adsp_v1_platform (8 bytes)
├── [2] adsp_audio_vtbl_t (16 bytes)
├── [6] HandlWrapper (44 bytes)
├── [17] MediaFmt (Input) (28 bytes)
├── [24] MediaFmt (Output) (28 bytes)
└── [31..] 算法核心内存 (pAlgoMem) (MemSize_Algo + MemSize_Arch words)
9.2 TuningBuffer 内存布局(在线调音时 Set mask=MASK_TuningBuffer)
TuningBuffer (UINT32*, 80,000 words = ~312 KB)
├── [0] isSet COMMAND_HEADER_WRITE(0x44332211) 或 COMMAND_HEADER_READ(0xAABBCCDD)
├── [1] pID 参数 ID
├── [2] pSize 实际数据长度(read时返回实际读取长度)
└── [3..] data 参数数据
9.3 关键 Param ID
| Param ID | 说明 |
|---|---|
| 0x16670001 | HMI Enable |
| 0x16670002 | AlgoChanNum(算法通道数) |
| 0x16670004 | HMI Tuning(在线调音入口) |
| 0x16670006 | VehicleCfg(车型配置) |
十、前端数据模型设计建议
基于以上分析,前端 TypeScript 模型应对应以下三个层次:
10.1 模块通用信息(对应 ModuleInstanceDescriptor)
interface ModuleInstance {
instanceId: string // 对应 nUniqueInstanceID
moduleTypeId: string // 对应 classID (e.g. "xisnddemom_v1")
state: 'active' | 'bypass' | 'mute' | 'inactive' // 对应 packedFlags[25:24]
inWireCount: number // 对应 packedFlags[7:0]
outWireCount: number // 对应 packedFlags[15:8]
profileTime?: number // 对应 profileTime(cycles × 256)
}
10.2 Wire 信息(对应 WireInstance)
interface WireInfo {
sampleRate: number // float
channels: number // wireInfo1[9:0]
maxBlockSize: number // wireInfo1[26:10]
blockSize: number // wireInfo2[16:0]
dataType: WireDataType // wireInfo2[22:17]
isComplex: boolean // wireInfo1[27]
sampleSizeBytes: number // wireInfo1[31:28]
rows: number // wireInfo3[9:0]
cols: number // wireInfo3[19:10]
isIPC: boolean // wireInfo3[20]
isPrivate: boolean // wireInfo3[21]
isClockMaster: boolean // wireInfo3[22]
}
type WireDataType = 'float32' | 'fract32' | 'int16' | 'int32' | 'int24'
10.3 模块专有参数(对应自定义字段,xisnd 示例)
interface XisndParams {
// 公开参数(Build 配置阶段)
enable: number // 0 or 1
vehicleCfg: number // 车型配置值
algoChanNum: number // 算法通道数
numOutChan: number // 输出通道数
memSizeAlgo: number // 算法内存大小(words)
memSizeArch: number // 架构内存大小(words)
memSizeTune: number // 调音内存大小(words)
// 私有参数(运行时,前端不直接修改)
// tuningBuffer: 通过调音协议访问
// algoMem: 运行时分配,前端只需知道大小
}
10.4 连接信息(对应 Wire 连接关系)
interface WireConnection {
wireId: string // wire 唯一 ID
fromModule: string // 源模块 instanceId
fromPort: number // 源模块输出 pin 索引
toModule: string // 目标模块 instanceId
toPort: number // 目标模块输入 pin 索引
wireInfo: WireInfo // wire 格式描述
}
10.5 链路(Layout)信息
interface LinkLayout {
layoutId: string
name: string
global: {
sampleRate: number
blockSize: number
dataType: WireDataType
}
modules: Record<string, ModuleInstance>
wires: WireConnection[]
// 各模块参数存储
params: Record<string, Record<string, number | string>>
}
十一、字段名对照表(头文件 vs 前端建议命名)
注:旧版
output/release/customModule/include/ModXisndDemom.h使用了不同的字段名(如xisndVehicleCfg)。以include/ModXisndDemom.h为准。
| 头文件字段名(正确版) | 前端建议字段名 | 说明 |
|---|---|---|
enable |
enable |
算法使能 |
VehicleCfg |
vehicleCfg |
车型配置 |
AlgoChanNum |
algoChanNum |
算法通道数 |
NumOutChan |
numOutChan |
输出通道数 |
MemSize_Algo |
memSizeAlgo |
算法内存大小 |
MemSize_Arch |
memSizeArch |
架构内存大小 |
MemSize_Tune |
memSizeTune |
调音缓冲内存大小 |
TuningBuffer |
(透明处理) | 在线调音通道,前端不直接操作 |
AlgoMem |
(透明处理) | 算法内存,运行时分配 |
生成时间:2026-03-25