14位浮点转11位整数算法的怪异设计疑问
旧音乐格式14位浮点转11位整数编码疑问
我在逆向一款旧音乐格式时,遇到了将14位无符号浮点值(记为pvf)转换为11位整数值的算法:
i87 = ((pvf >> 8) * 8) // 7 m = (((i87 & 0x7) + 7) << 8) | (pvf & 0xff) e = (~i87 & 0x38) >> 3 p = m >> e
经过测试,在取值范围[0,56*256)内,该算法等价于:
m = (pvf % 0x700) + 0x700 // 带隐藏位的尾数 e = 7 - (pvf // 0x700) p = m >> e
该算法本质是浮点转整数,通过指数对尾数移位,但高位字节的编码方式非常怪异:基础格式为00pppppp mmmmmmmm,将高6位p乘以8/7后得到00eeennn mmmmmmmm(n是尾数高位),没有给指数e分配完整3位,而是让n占用约2.8位(取值0-6)并与e混合。这种实现比直接给e分配3位的方案在对应架构上慢很多,必然存在合理设计原因。
该格式用于存储音符频率,转换得到的p是写入硬件的周期值,对应频率公式:
Hz = 1789773 // (16 * (p + 1))
我注意到转换算法中没有对p减1,疑似存在bug——比如高频场景下会导致严重失谐。另外,该格式似乎用于分段近似线性音高滑音/颤音,转换前会将相对音高(整数)加到浮点值上,但这和8/7的乘数有什么关联?
示例
- 输入
0x375c:0x37 * 8/7 = 0x3e,对应0x3e5c(二进制111110 01011100),计算得e=7-7=0,n=6+7=0xd(隐藏位),p=0xd5c >> 0=0xd5c,对应频率约32.70 Hz(接近C1)。 - 输入
0x14:0x14(二进制00010100),计算得e=7-0=7,n=0+7=7,p=0x714 >>7=0xe,对应频率约7457 Hz(接近A#8;实际应为B8,差1的bug导致高频失谐)。
核心疑问
- 为何该算法采用这种怪异的编码方式?
8/7乘数的作用是什么?- 这种编码与线性音高处理的关联是什么?
内容的提问来源于stack exchange,提问作者Justin Olbrantz
相关产品推荐
相关产品推荐

