如何在 DataView 中使用 UInt8 处理字节顺序?
How to handle the endianness with UInt8 in a DataView?
似乎在使用 UInt8 时没有什么可以处理字节顺序的。比如处理UInt16时,可以设置是小端还是大端:
dataview.setUint16(byteOffset, value [, littleEndian])
对
dataview.setUint8(byteOffset, value)
我想这是因为字节顺序处理的是字节的顺序,如果我一次插入一个字节,那么我需要自己对它们进行排序。
那么我该如何自己处理字节序呢?我正在使用此规范创建一个 WAVE 文件 header:http://soundfile.sapp.org/doc/WaveFormat/
header 的第一部分是 "ChunkID" 在 big endian 中,我是这样做的:
dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());
header 的第二部分是 small endian 中的 "ChunkSize",我是这样做的:
dataView.setUint8(4, 172);
现在我想既然这些块的字节顺序不同,那么我应该在每个块中做一些不同的事情。在这两种情况下我应该做些什么不同?
干杯!
编辑
我问这个问题,因为我正在创建的 wav 文件无效(根据 https://indiehd.com/auxiliary/flac-validator/)。我怀疑这是因为我没有正确处理字节顺序。这是完整的波形文件:
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);
}
单个字节 (uint8
) 没有任何字节顺序,字节顺序是字节序列的 属性。
根据您链接的规范,ChunkSize 占用 space 4 个字节 - 最低有效字节在前(小端)。如果您的值只有一个字节(不大于 255),您只需像您所做的那样在偏移量 4 处写入该字节。如果这 4 个字节是大端顺序,你必须在偏移量 7 处写入你的字节。
但是我建议简单地使用 setUint32
:
dataView.setUint32(0, 0x52494646, false); // RIFF
dataView.setUint32(4, 172 , true);
dataView.setUint32(8, 0x57415645, false) // WAVE
似乎在使用 UInt8 时没有什么可以处理字节顺序的。比如处理UInt16时,可以设置是小端还是大端:
dataview.setUint16(byteOffset, value [, littleEndian])
对
dataview.setUint8(byteOffset, value)
我想这是因为字节顺序处理的是字节的顺序,如果我一次插入一个字节,那么我需要自己对它们进行排序。
那么我该如何自己处理字节序呢?我正在使用此规范创建一个 WAVE 文件 header:http://soundfile.sapp.org/doc/WaveFormat/
header 的第一部分是 "ChunkID" 在 big endian 中,我是这样做的:
dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());
header 的第二部分是 small endian 中的 "ChunkSize",我是这样做的:
dataView.setUint8(4, 172);
现在我想既然这些块的字节顺序不同,那么我应该在每个块中做一些不同的事情。在这两种情况下我应该做些什么不同?
干杯!
编辑
我问这个问题,因为我正在创建的 wav 文件无效(根据 https://indiehd.com/auxiliary/flac-validator/)。我怀疑这是因为我没有正确处理字节顺序。这是完整的波形文件:
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);
}
单个字节 (uint8
) 没有任何字节顺序,字节顺序是字节序列的 属性。
根据您链接的规范,ChunkSize 占用 space 4 个字节 - 最低有效字节在前(小端)。如果您的值只有一个字节(不大于 255),您只需像您所做的那样在偏移量 4 处写入该字节。如果这 4 个字节是大端顺序,你必须在偏移量 7 处写入你的字节。
但是我建议简单地使用 setUint32
:
dataView.setUint32(0, 0x52494646, false); // RIFF
dataView.setUint32(4, 172 , true);
dataView.setUint32(8, 0x57415645, false) // WAVE