1 | /*
|
2 | * alawmulaw: A-Law and mu-Law codecs in JavaScript.
|
3 | * https://github.com/rochars/alawmulaw
|
4 | *
|
5 | * Copyright (c) 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 mu-Law codec.
|
30 | */
|
31 |
|
32 | /** @module alawmulaw/mulaw */
|
33 |
|
34 | /**
|
35 | * @type {number}
|
36 | * @private
|
37 | */
|
38 | const BIAS = 0x84;
|
39 | /**
|
40 | * @type {number}
|
41 | * @private
|
42 | */
|
43 | const CLIP = 32635;
|
44 | /**
|
45 | * @type {Array<number>}
|
46 | * @private
|
47 | */
|
48 | const encodeTable = [
|
49 | 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
|
50 | 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
51 | 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
52 | 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
53 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
54 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
55 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
56 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
57 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
58 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
59 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
60 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
61 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
62 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
63 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
64 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7];
|
65 | /**
|
66 | * @type {Array<number>}
|
67 | * @private
|
68 | */
|
69 | const decodeTable = [0,132,396,924,1980,4092,8316,16764];
|
70 |
|
71 | /**
|
72 | * Encode a 16-bit linear PCM sample as 8-bit mu-Law.
|
73 | * @param {number} sample A 16-bit PCM sample
|
74 | * @return {number}
|
75 | */
|
76 | export function encodeSample(sample) {
|
77 | /** @type {number} */
|
78 | let sign;
|
79 | /** @type {number} */
|
80 | let exponent;
|
81 | /** @type {number} */
|
82 | let mantissa;
|
83 | /** @type {number} */
|
84 | let muLawSample;
|
85 | /** get the sample into sign-magnitude **/
|
86 | sign = (sample >> 8) & 0x80;
|
87 | if (sign != 0) sample = -sample;
|
88 | if (sample > CLIP) sample = CLIP;
|
89 | /** convert from 16 bit linear to ulaw **/
|
90 | sample = sample + BIAS;
|
91 | exponent = encodeTable[(sample>>7) & 0xFF];
|
92 | mantissa = (sample >> (exponent+3)) & 0x0F;
|
93 | muLawSample = ~(sign | (exponent << 4) | mantissa);
|
94 | /** return the result **/
|
95 | return muLawSample;
|
96 | }
|
97 |
|
98 | /**
|
99 | * Decode a 8-bit mu-Law sample as 16-bit PCM.
|
100 | * @param {number} muLawSample The 8-bit mu-Law sample
|
101 | * @return {number}
|
102 | */
|
103 | export function decodeSample(muLawSample) {
|
104 | /** @type {number} */
|
105 | let sign;
|
106 | /** @type {number} */
|
107 | let exponent;
|
108 | /** @type {number} */
|
109 | let mantissa;
|
110 | /** @type {number} */
|
111 | let sample;
|
112 | muLawSample = ~muLawSample;
|
113 | sign = (muLawSample & 0x80);
|
114 | exponent = (muLawSample >> 4) & 0x07;
|
115 | mantissa = muLawSample & 0x0F;
|
116 | sample = decodeTable[exponent] + (mantissa << (exponent+3));
|
117 | if (sign != 0) sample = -sample;
|
118 | return sample;
|
119 | }
|
120 |
|
121 | /**
|
122 | * Encode 16-bit linear PCM samples into 8-bit mu-Law samples.
|
123 | * @param {!Int16Array} samples A array of 16-bit PCM samples.
|
124 | * @return {!Uint8Array}
|
125 | */
|
126 | export function encode(samples) {
|
127 | /** @type {!Uint8Array} */
|
128 | let muLawSamples = new Uint8Array(samples.length);
|
129 | for (let i=0; i<samples.length; i++) {
|
130 | muLawSamples[i] = encodeSample(samples[i]);
|
131 | }
|
132 | return muLawSamples;
|
133 | }
|
134 |
|
135 | /**
|
136 | * Decode 8-bit mu-Law samples into 16-bit PCM samples.
|
137 | * @param {!Uint8Array} samples A array of 8-bit mu-Law samples.
|
138 | * @return {!Int16Array}
|
139 | */
|
140 | export function decode(samples) {
|
141 | /** @type {!Int16Array} */
|
142 | let pcmSamples = new Int16Array(samples.length);
|
143 | for (let i=0; i<samples.length; i++) {
|
144 | pcmSamples[i] = decodeSample(samples[i]);
|
145 | }
|
146 | return pcmSamples;
|
147 | }
|