Как справиться с порядком байтов с UInt8 в DataView? - PullRequest
0 голосов
/ 24 февраля 2019

Кажется, что при работе с UInt8 нечего обращаться с порядком байтов.Например, при работе с UInt16 вы можете установить, хотите ли вы маленький или старший порядковый номер:

dataview.setUint16(byteOffset, value [, littleEndian])

против

dataview.setUint8(byteOffset, value)

Я полагаю, это потому, что порядок байтов связан с порядком байтов, и если я вставляю по одному байту за раз, мне нужно самому их упорядочить.

Так как же мне самому заняться обработкой байтов?Я создаю заголовок файла WAVE, используя эту спецификацию: http://soundfile.sapp.org/doc/WaveFormat/

Первая часть заголовка - "ChunkID" в big endian , и вот как я это делаю:

dataView.setUint8(0, 'R'.charCodeAt());
dataView.setUint8(1, 'I'.charCodeAt());
dataView.setUint8(2, 'F'.charCodeAt());
dataView.setUint8(3, 'F'.charCodeAt());

Вторая часть заголовка - это "ChunkSize" в smallianian , и вот как я это делаю:

dataView.setUint8(4, 172);

Теперь я предполагаю, что с тех пор как endiannessиз этих кусков отличается, то я должен делать что-то другое в каждом кусочке.Что я должен делать по-разному в этих двух случаях?

Ура!

РЕДАКТИРОВАТЬ

Я задаю этот вопрос, потому что файл 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);
}

1 Ответ

0 голосов
/ 24 февраля 2019

Один байт (uint8) не имеет порядка байтов, endianness является свойством последовательности байтов.

В соответствии со спецификацией, которую вы связали, ChunkSize занимает пространство для 4 байтов - смладший значащий байт первый (little-endian).Если ваше значение составляет всего один байт (не больше 255), вы просто записали бы байт со смещением 4, как и раньше.Если бы 4 байта были в порядке с прямым порядком байтов, вы должны записать свой байт со смещением 7.

Однако я бы порекомендовал просто использовать setUint32:

dataView.setUint32(0, 0x52494646, false); // RIFF
dataView.setUint32(4, 172       , true);
dataView.setUint32(8, 0x57415645, false) // WAVE
...