javascript - 如何为 Ogg 建立 CRC32 表?
问题描述
从这个答案我改编了下面的代码:
function _makeCRCTable() {
const CRCTable = new Uint32Array(256);
for (let i = 256; i--;) {
let char = i;
for (let j = 8; j--;) {
char = char & 1 ? 3988292384 ^ char >>> 1 : char >>> 1;
}
CRCTable[i] = char;
}
return CRCTable;
}
此代码生成表,如此处,但对于 Ogg,我需要另一个表 - 如此处。
来自Ogg 文档:
32 位 CRC 值(直接算法,初始 val 和最终 XOR = 0,生成多项式=0x04c11db7)
parseInt('04c11db7', 16)
return 79764919
- 我尝试了这个多项式,但结果表不正确。
我是 CRC 领域的新手,因为我发现CRC32 algorithm 有一些变体。
解决方案
我不确定 javascript 的优先级,但 xor 需要在班次之后发生:
char = char & 1 ? 3988292384 ^ (char >>> 1) : char >>> 1;
但是,您显示的第一个表似乎是正确的,因为 table[128] = table[0x80] = 3988292384 = 0xEDB88320 这是 0x104c11db7 位反转,然后右移一位。
您拥有的第二个表用于左移 CRC,其中 table[1] = x04c11db7。在这种情况下,内部循环将包括如下内容:
let char = i << 24;
for (let j = 8; j--;) {
char = char & 0x80000000 ? 0x04c11db7 ^ char << 1 : char << 1;
}
用于比较的示例 C 代码,为模式 {0x01}、{0x01,0x00}、{0x01,0x00,0x00}、{0x01,0x00,0x00,0x00} 生成 crc。
#include <stdio.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
uint32_t crctbl[256];
void gentbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
for(c = 0; c < 0x100; c++){
crc = c<<24;
for(i = 0; i < 8; i++){
b = crc>>31;
crc <<= 1;
crc ^= (0 - b) & 0x04c11db7;
}
crctbl[c] = crc;
}
}
uint32_t crc32(uint8_t * bfr, size_t size)
{
uint32_t crc = 0;
while(size--)
crc = (crc << 8) ^ crctbl[(crc >> 24)^*bfr++];
return(crc);
}
int main(int argc, char** argv)
{
uint32_t crc;
uint8_t bfr[4] = {0x01,0x00,0x00,0x00};
gentbl();
crc = crc32(bfr, 1); /* 0x04c11db7 */
printf("%08x\n", crc);
crc = crc32(bfr, 2); /* 0xd219c1dc */
printf("%08x\n", crc);
crc = crc32(bfr, 3); /* 0x01d8ac87 */
printf("%08x\n", crc);
crc = crc32(bfr, 4); /* 0xdc6d9ab7 */
printf("%08x\n", crc);
return(0);
}
对于 JS:
function _makeCRC32Table() {
const polynomial = 79764919;
const mask = 2147483648;
const CRCTable = new Uint32Array(256);
for (let i = 256; i--;) {
let char = i << 24;
for (let j = 8; j--;) {
char = char & mask ? polynomial ^ char << 1 : char << 1;
}
CRCTable[i] = char;
}
return CRCTable;
}
如何使用此表:
[1, 0].reduce((crc, byte) => crc << 8 >>> 0 ^ CRCTable[crc >>> 24 ^ byte], 0) >>> 0
在这里,我们添加>>> 0
了接受数字的模块 - 因为 JS 中没有 unsigned int - JavaScript 没有整数。它只有双精度浮点数。
请注意,对于 Ogg,您必须以相反的顺序设置生成的 CRC。
推荐阅读
- html - 如何在使用 Vue CLI 3 时将 .obj 和 .mtl 文件加载到 Vue 组件中
- objective-c - 条件绑定的初始化程序必须具有可选类型,而不是“错误”
- github - 使用 Github Actions 将 nodejs 应用程序部署到专用服务器
- mysql - 创建一个带有时间戳字段 MySQL 的表
- database - 如何在生产中使用 Rocket 运行 Diesel 迁移?
- c# - 从任务计划程序计划 SSIS 包时,文件未从一个目录移动到另一个目录
- javascript - 改变速度和尺寸的旋转箱
- node.js - 为什么我在 MERN 应用程序后端包含 catch 语句的代码行上收到 UnhandledPromiseRejectionWarning?
- android - 如何在 github 上隐藏 Google Api Key?
- javascript - 具有多个类别和多个值的 Highcharts