Passed
Push — master ( 7e9cc8...5ffeb6 )
by Rafael S.
01:42
created

index.js ➔ writeSubChunks_   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
1
/*!
2
 * riff-chunks
3
 * Read and write the chunks of RIFF and RIFX files.
4
 * Copyright (c) 2017 Rafael da Silva Rocha.
5
 * https://github.com/rochars/riff-chunks
6
 *
7
 */
8
9
/** @private */
10
const byteData = require("byte-data");
11
/** @private */
12
const chr = byteData.chr;
13
/** @private */
14
let uInt32 = byteData.uInt32;
15
16
17
/**
18
 * Write the bytes of a RIFF/RIFX file.
19
 * @param {Object} chunks A structure like the return of riffChunks.read().
20
 * @return {Uint8Array} The file bytes as Uint8Array when
21
 *      chunkId is "RIFF" or "RIFX" or the chunk bytes as Array<number>
22
 *      when chunkId is "LIST".
23
 */
24
function write(chunks) {
25
    uInt32.be = chunks["chunkId"] === "RIFX";
26
    let bytes =
27
        byteData.packArray(chunks["chunkId"], chr).concat(
28
                byteData.pack(chunks["chunkSize"], uInt32),
29
                byteData.packArray(chunks["format"], chr),
30
                writeSubChunks_(chunks["subChunks"])
31
            );
32
    if (chunks["chunkId"] === "RIFF" || chunks["chunkId"] === "RIFX" ) {
33
        bytes = new Uint8Array(bytes);
34
    }
35
    return bytes;
36
}
37
38
/**
39
 * Get the chunks of a RIFF/RIFX file.
40
 * @param {Uint8Array|Array<number>} buffer The file bytes.
41
 * @return {Object} The chunk.
42
 */
43
function read(buffer) {
44
    buffer = [].slice.call(buffer);
45
    let chunkId = getChunkId_(buffer, 0);
46
    uInt32.be = chunkId === "RIFX";
47
    return {
48
        "chunkId": chunkId,
49
        "chunkSize": getChunkSize_(buffer, 0),
50
        "format": byteData.unpackArray(buffer.slice(8, 12), chr),
51
        "subChunks": getSubChunks_(buffer)
52
    };
53
}
54
55
/**
56
 * Write the sub chunks of a RIFF file.
57
 * @param {Array<Object>} chunks The chunks.
58
 * @return {Array<number>} The chunk bytes.
59
 * @private
60
 */
61
function writeSubChunks_(chunks) {
62
    let subChunks = [];
63
    let i = 0;
64
    while (i < chunks.length) {
65
        if (chunks[i]["chunkId"] === "LIST") {
66
            subChunks = subChunks.concat(write(chunks[i]));
67
        } else {
68
            subChunks = subChunks.concat(
69
                byteData.packArray(chunks[i]["chunkId"], chr),
70
                byteData.pack(chunks[i]["chunkSize"], uInt32),
71
                chunks[i]["chunkData"]
72
            );
73
        }
74
        i++;
75
    }
76
    return subChunks;
77
}
78
79
/**
80
 * Get the sub chunks of a RIFF file.
81
 * @param {Uint8Array|Array<number>} buffer the RIFF file bytes.
82
 * @return {Object} The subchunks of a RIFF/RIFX or LIST chunk.
83
 * @private
84
 */
85
function getSubChunks_(buffer) {
86
    let chunks = [];
87
    let i = 12;
88
    while(i < buffer.length) {
89
        chunks.push(getSubChunk_(buffer, i));
90
        i += 8 + chunks[chunks.length - 1]["chunkSize"];
91
    }
92
    return chunks;
93
}
94
95
/**
96
 * Get a sub chunk from a RIFF file.
97
 * @param {Uint8Array|Array<number>} buffer the RIFF file bytes.
98
 * @param {number} index The start index of the chunk.
99
 * @return {Object} A subchunk of a RIFF/RIFX or LIST chunk.
100
 * @private
101
 */
102
function getSubChunk_(buffer, index) {
103
    let chunk = {
104
        "chunkId": getChunkId_(buffer, index),
105
        "chunkSize": getChunkSize_(buffer, index)
106
    };
107
    if (chunk["chunkId"] === "LIST") {
108
        chunk["format"] = byteData.unpackArray(buffer.slice(8, 12), chr);
109
        chunk["subChunks"] = getSubChunks_(
110
            buffer.slice(index, index + chunk["chunkSize"]));
111
    } else {
112
        chunk["chunkData"] = buffer.slice(
113
            index + 8, index + 8 + chunk["chunkSize"]);
114
    }
115
    return chunk;
116
}
117
118
/**
119
 * Return the FourCC of a chunk.
120
 * @param {Uint8Array|Array<number>} buffer the RIFF file bytes.
121
 * @param {number} index The start index of the chunk.
122
 * @return {string} The id of the chunk.
123
 * @private
124
 */
125
function getChunkId_(buffer, index) {
126
    return byteData.unpackArray(buffer.slice(index, index + 4), chr);
127
}
128
129
/**
130
 * Return the size of a chunk.
131
 * @param {Uint8Array|Array<number>} buffer the RIFF file bytes.
132
 * @param {number} index The start index of the chunk.
133
 * @return {number} The size of the chunk without the id and size fields.
134
 * @private
135
 */
136
function getChunkSize_(buffer, index) {
137
    return byteData.unpack(buffer.slice(index + 4, index + 8), uInt32);
138
}
139
140
module.exports.read = read;
141
module.exports.write = write;
142