Passed
Branch v4.x (8cfd5c)
by Rafael S.
01:16
created

T_CONST ➔ bitdepth   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
c 1
b 0
f 0
nc 24
nop 4
dl 0
loc 1
rs 8.8571
1
/*
2
 * bitdepth: Change the resolution of samples to and from any bit depth.
3
 * https://github.com/rochars/bitdepth
4
 *
5
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 */
27
28
/**
29
 * @fileoverview The bitdepth() function and private helper functions.
30
 */
31
32
/** @private */
33
const f64f32_ = new Float32Array(1);
34
35
/**
36
 * Change the bit depth of the data in a array.
37
 * The input array is modified in-place.
38
 * @param {!Array<number>} samples The samples.
39
 * @param {string} original The original bit depth of the data.
40
 *      One of "8" ... "53", "32f", "64"
41
 * @param {string} target The desired bit depth for the data.
42
 *      One of "8" ... "53", "32f", "64"
43
 * @param {Array<number>=} outputArray An optional array to write
44
        converted samples to. Useful for writing to typed arrays.
45
 */
46
function bitdepth(samples, original, target, outputArray) {
47
  validateBitDepth_(original);
48
  validateBitDepth_(target);
49
  outputArray = outputArray || samples;
50
  /** @type {!Function} */
51
  let toFunction = getBitDepthFunction_(original, target);
52
  /** @type {!Object} */
53
  let options = {
54
    oldMin: Math.pow(2, parseInt(original, 10)) / 2,
55
    newMin: Math.pow(2, parseInt(target, 10)) / 2,
56
    oldMax: (Math.pow(2, parseInt(original, 10)) / 2) - 1,
57
    newMax: (Math.pow(2, parseInt(target, 10)) / 2) - 1,
58
  };
59
  /** @type {number} */
60
  const len = samples.length;
61
  // sign the samples if original is 8-bit
62
  if (original == "8") {
63
    for (let i=0; i<len; i++) {
64
      outputArray[i] = samples[i] -= 128;
65
    }
66
  }
67
  // change the resolution of the samples
68
  for (let i=0; i<len; i++) {        
69
    outputArray[i] = toFunction(samples[i], options);
70
  }
71
  // unsign the samples if target is 8-bit
72
  if (target == "8") {
73
    for (let i=0; i<len; i++) {
74
      outputArray[i] = outputArray[i] += 128;
75
    }
76
  }
77
}
78
79
/**
80
 * Change the bit depth from int to int.
81
 * @param {number} sample The sample.
82
 * @param {!Object} args Data about the original and target bit depths.
83
 * @return {number}
84
 * @private
85
 */
86
function intToInt_(sample, args) {
87
  if (sample > 0) {
88
    sample = parseInt((sample / args.oldMax) * args.newMax, 10);
89
  } else {
90
    sample = parseInt((sample / args.oldMin) * args.newMin, 10);
91
  }
92
  return sample;
93
}
94
95
/**
96
 * Change the bit depth from float to int.
97
 * @param {number} sample The sample.
98
 * @param {!Object} args Data about the original and target bit depths.
99
 * @return {number}
100
 * @private
101
 */
102
function floatToInt_(sample, args) {
103
  return parseInt(
104
    sample > 0 ? sample * args.newMax : sample * args.newMin, 10);
105
}
106
107
/**
108
 * Change the bit depth from int to float.
109
 * @param {number} sample The sample.
110
 * @param {!Object} args Data about the original and target bit depths.
111
 * @return {number}
112
 * @private
113
 */
114
function intToFloat_(sample, args) {
115
  return sample > 0 ? sample / args.oldMax : sample / args.oldMin;
116
}
117
118
/**
119
 * Change the bit depth from float to float.
120
 * @param {number} sample The sample.
121
 * @return {number}
122
 * @private
123
 */
124
function floatToFloat_(sample) {
125
  f64f32_[0] = sample;
126
  return f64f32_[0];
127
}
128
129
/**
130
 * Return the function to change the bit depth of a sample.
131
 * @param {string} original The original bit depth of the data.
132
 *      One of "8" ... "53", "32f", "64"
133
 * @param {string} target The new bit depth of the data.
134
 *      One of "8" ... "53", "32f", "64"
135
 * @return {!Function}
136
 * @private
137
 */
138
function getBitDepthFunction_(original, target) {
139
  /** @type {!Function} */
140
  let func = function(x) {return x;};
141
  if (original != target) {
142
    if (["32f", "64"].includes(original)) {
143
      if (["32f", "64"].includes(target)) {
144
        func = floatToFloat_;
145
      } else {
146
        func = floatToInt_;
147
      }
148
    } else {
149
      if (["32f", "64"].includes(target)) {
150
        func = intToFloat_;
151
      } else {
152
        func = intToInt_;
153
      }
154
    }
155
  }
156
  return func;
157
}
158
159
/**
160
 * Validate the bit depth.
161
 * @param {string} bitDepth The original bit depth.
162
 *     Should be one of "8" ... "53", "32f" or "64".
163
 * @throws {Error} If any argument does not meet the criteria.
164
 * @private
165
 */
166
function validateBitDepth_(bitDepth) {
167
  if ((bitDepth != "32f" && bitDepth != "64") &&
168
      (parseInt(bitDepth, 10) < "8" || parseInt(bitDepth, 10) > "53")) {
169
    throw new Error("Invalid bit depth.");
170
  }
171
}
172
173
module.exports = bitdepth;
174