Javascript 如何在DataView中使用UInt8处理endianness?

Javascript 如何在DataView中使用UInt8处理endianness?,javascript,wav,endianness,dataview,uint8array,Javascript,Wav,Endianness,Dataview,Uint8array,在使用UInt8时,似乎没有什么需要处理的endianness。例如,在处理UInt16时,您可以设置是需要小尾端还是大尾端: dataview.setUint16(字节偏移量,值[,littleEndian]) vs dataview.setUint8(字节偏移量,值) 我猜这是因为endianness处理字节的顺序,若我一次插入一个字节,那个么我需要自己对它们进行排序 那么,我自己如何处理endianness呢?我正在使用以下规范创建WAVE文件头: 标题的第一部分是big-endian中的

在使用UInt8时,似乎没有什么需要处理的endianness。例如,在处理UInt16时,您可以设置是需要小尾端还是大尾端:

dataview.setUint16(字节偏移量,值[,littleEndian])

vs

dataview.setUint8(字节偏移量,值)

我猜这是因为endianness处理字节的顺序,若我一次插入一个字节,那个么我需要自己对它们进行排序

那么,我自己如何处理endianness呢?我正在使用以下规范创建WAVE文件头:

标题的第一部分是big-endian中的“ChunkID”,我就是这样做的:

dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());
dataView.setUint8(4, 172);
标题的第二部分是small-endian中的“ChunkSize”,我就是这样做的:

dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());
dataView.setUint8(4, 172);
现在我想,既然这些块的端点是不同的,那么我应该在每个块中做一些不同的事情。在这两种情况下,我应该做什么不同

干杯

编辑

我问这个问题,因为我创建的wav文件无效(根据)。我怀疑这是因为我没有正确处理endianness。这是完整的wave文件:

const fs = require('fs');

const BITS_PER_BYTE = 8;
const BITS_PER_SAMPLE = 8;
const SAMPLE_RATE = 44100;
const NB_CHANNELS = 2;
const SUB_CHUNK_2_SIZE = 128;

const chunkSize = 36 + SUB_CHUNK_2_SIZE;
const blockAlign = NB_CHANNELS * (BITS_PER_SAMPLE / BITS_PER_BYTE);
const byteRate = SAMPLE_RATE * blockAlign;

const arrayBuffer = new ArrayBuffer(chunkSize + 8)
const dataView = new DataView(arrayBuffer);

// The RIFF chunk descriptor
// ChunkID
dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());
// ChunkSize
dataView.setUint8(4, chunkSize);
// Format
dataView.setUint8(8, 'W'.charCodeAt());
dataView.setUint8(9, 'A'.charCodeAt());
dataView.setUint8(10, 'V'.charCodeAt());
dataView.setUint8(11, 'E'.charCodeAt());

// The fmt sub-chunk
// Subchunk1ID
dataView.setUint8(12, 'f'.charCodeAt());
dataView.setUint8(13, 'm'.charCodeAt());
dataView.setUint8(14, 't'.charCodeAt());
// Subchunk1Size
dataView.setUint8(16, 16);
// AudioFormat
dataView.setUint8(20, 1);
// NumChannels
dataView.setUint8(22, NB_CHANNELS);
// SampleRate
dataView.setUint8(24, ((SAMPLE_RATE >> 8) & 255));
dataView.setUint8(25, SAMPLE_RATE & 255);
// ByteRate
dataView.setUint8(28, ((byteRate >> 8) & 255));
dataView.setUint8(29, byteRate & 255);
// BlockAlign
dataView.setUint8(32, blockAlign);
// BitsPerSample
dataView.setUint8(34, BITS_PER_SAMPLE);

// The data sub-chunk
// Subchunk2ID
dataView.setUint8(36, 'd'.charCodeAt());
dataView.setUint8(37, 'a'.charCodeAt());
dataView.setUint8(38, 't'.charCodeAt());
dataView.setUint8(39, 'a'.charCodeAt());
// Subchunk2Size
dataView.setUint8(40, SUB_CHUNK_2_SIZE);
// Data
for (let i = 0; i < SUB_CHUNK_2_SIZE; i++) {
    dataView.setUint8(i + 44, i);
}
const fs=require('fs');
每字节常量位=8;
每个样本的常量位=8;
常数采样率=44100;
const NB_通道=2;
const SUB_CHUNK_2_SIZE=128;
const chunkSize=36+子块2大小;
const blockAlign=NB_通道*(每_采样位/BITS_每_字节位);
常量字节=采样率*块对齐;
const arrayBuffer=新的arrayBuffer(chunkSize+8)
const dataView=新数据视图(arrayBuffer);
//RIFF块描述符
//ChunkID
setUint8(0,'R'.charCodeAt());
setUint8(1,'I'.charCodeAt());
setUint8(2,'F'.charCodeAt());
setUint8(3,'F'.charCodeAt());
//块大小
setUint8(4,chunkSize);
//格式
setUint8(8,'W'.charCodeAt());
setUint8(9,'A'.charCodeAt());
setUint8(10,'V'.charCodeAt());
setUint8(11,'E'.charCodeAt());
//fmt子块
//亚chunk1id
setUint8(12,'f'.charCodeAt());
setUint8(13,'m'.charCodeAt());
setUint8(14,'t'.charCodeAt());
//亚成片尺寸
dataView.setUint8(16,16);
//音频格式
dataView.setUint8(20,1);
//数字通道
dataView.setUint8(22个NB_通道);
//采样器
dataView.setUint8(24,((采样率>>8)和255));
dataView.setUint8(25,样本率&255);
//拜特
dataView.setUint8(28,((byteRate>.8)和255));
dataView.setUint8(29,byteRate&255);
//块对齐
dataView.setUint8(32,blockAlign);
//比特采样
dataView.setUint8(34,每个样本的位);
//数据子块
//亚成虫
setUint8(36,'d'.charCodeAt());
setUint8(37,'a'.charCodeAt());
setUint8(38,'t'.charCodeAt());
setUint8(39,'a'.charCodeAt());
//亚成片大小
dataView.setUint8(40,子块大小);
//资料
for(设i=0;i单个字节(
uint8
)没有任何endianness,endianness是字节序列的属性

根据您链接的规范,ChunkSize占用4个字节的空间,其中最低有效字节排在第一位(小尾端)。如果您的值只有一个字节(不大于255),则只需像以前一样在偏移量4处写入该字节。如果4个字节的顺序是大端,那么必须在偏移量7处写入字节

但是,我建议只使用:


谢谢你的回答。所以我的ChunkSize是1字节,因为它是小尾端,所以它位于偏移量4。我不明白的是,如果endian很大,为什么它会被定位在偏移量7。“最低有效字节”和“最高有效字节”是什么?@maximedupre ChunkSize是4个字节,从索引4到7。@maximedupre检查,如果我的值是3个字节,并且4个字节(例如Subchunk1ID)是大端顺序,我需要将值放在索引13、14和15(而不是12、13和14)处?@maximedupre:15,14,13(大端)对12,13,14(小端)。但正如我所说,你真的应该使用
setUint32
setUint16
而不是手动设置单个字节。我注意到你忘记了将字节15设置为0x20——空格字符。@Bergi哦,我的天哪!丢失的那块!你怎么知道我应该加个空格?它现在正在工作:D。因为规范这么说:“包含字母
“fmt”
(0x666d7420大端形式)”:-)