Passed
Push — master ( 4f5721...bda8e1 )
by Rafael S.
59s
created

index.js   A

Complexity

Total Complexity 21
Complexity/F 2.33

Size

Lines of Code 182
Function Count 9

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 0
nc 1
dl 0
loc 182
rs 10
c 4
b 0
f 0
wmc 21
mnd 1
bc 20
fnc 9
bpm 2.2222
cpm 2.3333
noi 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A CODECS.intToInt 0 10 2
A CODECS.floatToFloat 0 7 3
A ➔ unsign8Bit_ 0 6 2
A ➔ sign8Bit_ 0 6 2
A CODECS.floatToInt 0 4 2
A CODECS.intToFloat 0 4 2
A ➔ getBitDepthFunction_ 0 15 3
A ➔ toBitDepth 0 20 2
A ➔ validateBitDepths_ 0 8 3
1
/*!
2
 * bitdepth
3
 * Change the bit depth of samples to and from 8, 16, 24, 32 & 64-bit.
4
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
5
 * https://github.com/rochars/bitdepth
6
 *
7
 */
8
9
const f64f32 = new Float32Array(1);
10
11
/**
12
 * Max number of different values for each bit depth.
13
 * @enum {number}
14
 * @private
15
 */
16
const MAX_VALUES = {
17
    "8": 256,
18
    "16": 65536,
19
    "24": 16777216,
20
    "32": 4294967296,
21
    "32f": 1,
22
    "64": 1
23
};
24
25
/**
26
 * Functions to change the bit depth of a sample.
27
 * @enum {Function}
28
 * @private
29
 */
30
const CODECS = {
31
32
    /**
33
     * Change the bit depth from int to int.
34
     * @param {number} sample The sample.
35
     * @param {Object} args Data about the original and target bit depths.
36
     * @return {number}
37
     */
38
    "intToInt": function(sample, args) {
39
        if (sample > 0) {
40
            sample = parseInt(
41
                (sample / args["oldPositive"]) * args["newPositive"], 10);
42
        } else {
43
            sample = parseInt(
44
                (sample / args["oldNegative"]) * args["newNegative"], 10);
45
        }
46
        return sample;
47
    },
48
49
    /**
50
     * Change the bit depth from float to int.
51
     * @param {number} sample The sample.
52
     * @param {Object} args Data about the original and target bit depths.
53
     * @return {number}
54
     */
55
    "floatToInt": function(sample, args) {
56
        return sample > 0 ?
57
            sample * args["newPositive"] : sample * args["newNegative"];
58
    },
59
60
    /**
61
     * Change the bit depth from int to float.
62
     * @param {number} sample The sample.
63
     * @param {Object} args Data about the original and target bit depths.
64
     * @return {number}
65
     */
66
    "intToFloat": function(sample, args) {
67
        return sample > 0 ?
68
            sample / args["oldPositive"] : sample / args["oldNegative"];
69
    },
70
71
    /**
72
     * Change the bit depth from float to float.
73
     * @param {number} sample The sample.
74
     * @param {Object} args Data about the original and target bit depths.
75
     * @return {number}
76
     */
77
    "floatToFloat": function(sample, args) {
78
        if (args["original"] == "64" && args["target"] == "32f") {
79
            f64f32[0] = sample;
80
            sample = f64f32[0];
81
        }
82
        return sample;
83
    }
84
};
85
86
/**
87
 * Change the bit depth of the data in a array.
88
 * The input array is modified in-place.
89
 * @param {Array<number>} samples The samples.
90
 * @param {string} originalBitDepth The original bit depth of the data.
91
 *      One of "8", "16", "24", "32", "32f", "64"
92
 * @param {string} targetBitDepth The new bit depth of the data.
93
 *      One of "8", "16", "24", "32", "32f", "64"
94
 */
95
function toBitDepth(samples, originalBitDepth, targetBitDepth) {
96
    validateBitDepths_(originalBitDepth, targetBitDepth);
97
    let toFunction = getBitDepthFunction_(originalBitDepth, targetBitDepth);
98
    let len = samples.length;
99
    for (let i=0; i<len; i++) {        
100
        samples[i] = sign8Bit_(samples[i], originalBitDepth);
101
        samples[i] = toFunction(
102
                samples[i],
103
                {
104
                    "oldNegative": MAX_VALUES[originalBitDepth] / 2,
105
                    "newNegative": MAX_VALUES[targetBitDepth] / 2,
106
                    "oldPositive": MAX_VALUES[originalBitDepth] / 2 - 1,
107
                    "newPositive": MAX_VALUES[targetBitDepth] / 2 - 1,
108
                    "original": originalBitDepth,
109
                    "target": targetBitDepth
110
                }
111
            );
112
        samples[i] = unsign8Bit_(samples[i], targetBitDepth);
113
    }
114
}
115
116
/**
117
 * Get the function to change the bit depth of a sample.
118
 * @param {string} originalBitDepth The original bit depth of the data.
119
 *      One of "8", "16", "24", "32", "32f", "64"
120
 * @param {string} targetBitDepth The new bit depth of the data.
121
 *      One of "8", "16", "24", "32", "32f", "64"
122
 * @return {Function}
123
 * @private
124
 */
125
function getBitDepthFunction_(originalBitDepth, targetBitDepth) {
126
    let prefix;
127
    let suffix;
128
    if (["32f", "64"].includes(originalBitDepth)) {
129
        prefix = "float";
130
    } else {
131
        prefix = "int";
132
    }
133
    if (["32f", "64"].includes(targetBitDepth)) {
134
        suffix = "Float";
135
    } else {
136
        suffix = "Int";
137
    }
138
    return CODECS[prefix + "To" + suffix];
139
}
140
141
/**
142
 * Sign unsigned 8-bit data.
143
 * @param {number} sample The sample.
144
 * @param {string} originalBitDepth The original bit depth of the data.
145
 *      One of "8", "16", "24", "32", "32f", "64"
146
 * @return {number}
147
 * @private
148
 */
149
function sign8Bit_(sample, originalBitDepth) {
150
    if (originalBitDepth == "8") {
151
        sample -= 128;
152
    }
153
    return sample;
154
}
155
156
/**
157
 * Unsign signed 8-bit data.
158
 * @param {number} sample The sample.
159
 * @param {string} targetBitDepth The target bit depth of the data.
160
 *      One of "8", "16", "24", "32", "32f", "64"
161
 * @return {number}
162
 * @private
163
 */
164
function unsign8Bit_(sample, targetBitDepth) {
165
    if (targetBitDepth == "8") {
166
        sample += 128;
167
    }
168
    return sample;
169
}
170
171
/**
172
 * Validate the bit depth.
173
 * @param {string} originalBitDepth The original bit depth.
174
 *     Should be one of "8", "16", "24", "32", "32f", "64".
175
 * @param {string} targetBitDepth The target bit depth.
176
 *     Should be one of "8", "16", "24", "32", "32f", "64".
177
 * @throws {Error} If any argument does not meet the criteria.
178
 * @return {boolean}
179
 * @private
180
 */
181
function validateBitDepths_(originalBitDepth, targetBitDepth) {
182
    let validBitDepths = ["8", "16", "24", "32", "32f", "64"];
183
    if (validBitDepths.indexOf(originalBitDepth) == -1 ||
184
        validBitDepths.indexOf(targetBitDepth) == -1) {
185
        throw new Error("Invalid bit depth.");
186
    }
187
    return true;
188
}
189
190
module.exports.toBitDepth = toBitDepth;
191