Passed
Push — master ( 8d4558...de1506 )
by Rafael S.
01:12
created

index.js ➔ validateBitDepth_   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 1
nop 1
dl 0
loc 7
rs 8.8571
c 0
b 0
f 0
1
/**
2
 * bitdepth
3
 * Change the resolution of samples to and from 8, 11, 12, 16, 20, 24, 32, 48 & 64-bit.
4
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
5
 * https://github.com/rochars/bitdepth
6
 *
7
 */
8
9
/** @private */
10
const f64f32_ = new Float32Array(1);
11
12
/**
13
 * Change the bit depth of the data in a array.
14
 * The input array is modified in-place.
15
 * @param {!Array<number>} samples The samples.
16
 * @param {!string} original The original bit depth of the data.
17
 *      One of "8" ... "53", "32f", "64"
18
 * @param {!string} target The desired bit depth for the data.
19
 *      One of "8" ... "53", "32f", "64"
20
 */
21
function toBitDepth(samples, original, target) {
22
    if (original != target) {
23
        validateBitDepth_(original);
24
        validateBitDepth_(target);
25
        let toFunction = getBitDepthFunction_(original, target);
26
        let options = {
27
            oldMin: Math.pow(2, parseInt(original, 10)) / 2,
28
            newMin: Math.pow(2, parseInt(target, 10)) / 2,
29
            oldMax: (Math.pow(2, parseInt(original, 10)) / 2) - 1,
30
            newMax: (Math.pow(2, parseInt(target, 10)) / 2) - 1,
31
        };
32
        signed8Bit_(samples, original, false);
33
        for (let i=0; i<samples.length; i++) {        
34
            samples[i] = toFunction(samples[i], options);
35
        }
36
        signed8Bit_(samples, target, true);
37
    }
38
}
39
40
/**
41
 * Sign or unsign 8-bit samples.
42
 * The input array is modified in-place.
43
 * @param {!Array<number>} samples The samples.
44
 * @param {!string} bitDepth The original bit depth of the data.
45
 * @param {!boolean} signed True if should sign the samples, false otherwise.
46
 */
47
function signed8Bit_(samples, bitDepth, signed) {
48
    if (bitDepth == "8") {
49
        if (signed) {
50
            for (let i=0; i<samples.length; i++) {
51
                samples[i] += 128;
52
            }
53
        } else {
54
            for (let i=0; i<samples.length; i++) {
55
                samples[i] -= 128;
56
            }
57
        }
58
    }
59
}
60
61
/**
62
 * Change the bit depth from int to int.
63
 * @param {!number} sample The sample.
64
 * @param {!Object} args Data about the original and target bit depths.
65
 * @return {!number}
66
 * @private
67
 */
68
function intToInt_(sample, args) {
69
    if (sample > 0) {
70
        sample = parseInt((sample / args.oldMax) * args.newMax, 10);
71
    } else {
72
        sample = parseInt((sample / args.oldMin) * args.newMin, 10);
73
    }
74
    return sample;
75
}
76
77
/**
78
 * Change the bit depth from float to int.
79
 * @param {!number} sample The sample.
80
 * @param {!Object} args Data about the original and target bit depths.
81
 * @return {!number}
82
 * @private
83
 */
84
function floatToInt_(sample, args) {
85
    return parseInt(
86
        sample > 0 ? sample * args.newMax : sample * args.newMin, 10);
87
}
88
89
/**
90
 * Change the bit depth from int to float.
91
 * @param {!number} sample The sample.
92
 * @param {!Object} args Data about the original and target bit depths.
93
 * @return {!number}
94
 * @private
95
 */
96
function intToFloat_(sample, args) {
97
    return sample > 0 ? sample / args.oldMax : sample / args.oldMin;
98
}
99
100
/**
101
 * Change the bit depth from float to float.
102
 * @param {!number} sample The sample.
103
 * @return {!number}
104
 * @private
105
 */
106
function floatToFloat_(sample) {
107
    f64f32_[0] = sample;
108
    sample = f64f32_[0];
109
    return sample;
110
}
111
112
/**
113
 * Get the function to change the bit depth of a sample.
114
 * @param {!string} originalBitDepth The original bit depth of the data.
115
 *      One of "8" ... "53", "32f", "64"
116
 * @param {!string} targetBitDepth The new bit depth of the data.
117
 *      One of "8" ... "53", "32f", "64"
118
 * @return {!Function}
119
 * @private
120
 */
121
function getBitDepthFunction_(originalBitDepth, targetBitDepth) {
122
    if (["32f", "64"].includes(originalBitDepth)) {
123
        if (["32f", "64"].includes(targetBitDepth)) {
124
            return floatToFloat_;
125
        } else {
126
            return floatToInt_;
127
        }
128
    } else {
129
        if (["32f", "64"].includes(targetBitDepth)) {
130
            return intToFloat_;
131
        } else {
132
            return intToInt_;
133
        }
134
    }
135
}
136
137
/**
138
 * Validate the bit depth.
139
 * @param {!string} originalBitDepth The original bit depth.
0 ignored issues
show
Documentation introduced by
The parameter originalBitDepth does not exist. Did you maybe forget to remove this comment?
Loading history...
140
 *     Should be one of "8" ... "53", "32f" or "64".
141
 * @param {!string} targetBitDepth The target bit depth.
0 ignored issues
show
Documentation introduced by
The parameter targetBitDepth does not exist. Did you maybe forget to remove this comment?
Loading history...
142
 *     Should be one of "8" ... "53", "32f" or "64".
143
 * @throws {Error} If any argument does not meet the criteria.
144
 * @return {!boolean}
145
 * @private
146
 */
147
function validateBitDepth_(bitDepth) {
148
    if ((bitDepth != "32f" && bitDepth != "64") &&
149
            (parseInt(bitDepth, 10) < "8" || parseInt(bitDepth, 10) > "53")) {
150
        throw new Error("Invalid bit depth.");
151
    }
152
    return true;
153
}
154
155
module.exports = toBitDepth;
156
module.exports.toBitDepth = toBitDepth;
157