Passed
Branch master (bc809e)
by Rafael S.
01:21
created

T_CONST ➔ intToFloat_   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 1
rs 10
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} original The original bit depth of the data.
115
 *      One of "8" ... "53", "32f", "64"
116
 * @param {!string} target The new bit depth of the data.
117
 *      One of "8" ... "53", "32f", "64"
118
 * @return {!Function}
119
 * @private
120
 */
121
function getBitDepthFunction_(original, target) {
122
    if (["32f", "64"].includes(original)) {
123
        if (["32f", "64"].includes(target)) {
124
            return floatToFloat_;
125
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
126
            return floatToInt_;
127
        }
128
    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
129
        if (["32f", "64"].includes(target)) {
130
            return intToFloat_;
131
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
132
            return intToInt_;
133
        }
134
    }
135
}
136
137
/**
138
 * Validate the bit depth.
139
 * @param {!string} bitDepth The original bit depth.
140
 *     Should be one of "8" ... "53", "32f" or "64".
141
 * @throws {Error} If any argument does not meet the criteria.
142
 * @return {!boolean}
143
 * @private
144
 */
145
function validateBitDepth_(bitDepth) {
146
    if ((bitDepth != "32f" && bitDepth != "64") &&
147
            (parseInt(bitDepth, 10) < "8" || parseInt(bitDepth, 10) > "53")) {
148
        throw new Error("Invalid bit depth.");
149
    }
150
    return true;
151
}
152
153
module.exports = toBitDepth;
154
module.exports.toBitDepth = toBitDepth;
155