Passed
Push — master ( d8cd50...7c1afd )
by Rafael S.
01:01
created

lib/alaw.js   A

Size

Lines of Code 1

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 1
rs 10
noi 1
1
/*
2
 * alawmulaw: A-Law and mu-Law codecs in JavaScript.
3
 * https://github.com/rochars/alawmulaw
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 A-Law codec.
30
 * References:
31
 * https://github.com/deftio/companders
32
 * http://dystopiancode.blogspot.com.br/2012/02/pcm-law-and-u-law-companding-algorithms.html
33
 */
34
35
/** @module alawmulaw/alaw */
36
37
/** @type {!Array<number>} */
38
const LOG_TABLE = [
39
  1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 
40
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
41
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
42
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 
43
];
44
45
/**
46
 * Encode a 16-bit linear PCM sample as 8-bit A-Law.
47
 * @param {number} sample A 16-bit linear PCM sample
48
 * @return {number}
49
 */
50
function encodeSample(sample) {
51
  /** @type {number} */
52
  let compandedValue; 
53
  sample = (sample ==-32768) ? -32767 : sample;
54
  /** @type {number} */
55
  let sign = ((~sample) >> 8) & 0x80; 
56
  if (!sign) {
57
    sample = sample * -1; 
58
  }
59
  if (sample > 32635) {
60
    sample = 32635; 
61
  }
62
  if (sample >= 256)  {
63
    /** @type {number} */
64
    let exponent = LOG_TABLE[(sample >> 8) & 0x7F];
65
    /** @type {number} */
66
    let mantissa = (sample >> (exponent + 3) ) & 0x0F; 
67
    compandedValue = ((exponent << 4) | mantissa); 
68
  } else {
69
    compandedValue = sample >> 4; 
70
  } 
71
  return compandedValue ^ (sign ^ 0x55);
72
}
73
74
/**
75
 * Decode a 8-bit A-Law sample as 16-bit linear PCM.
76
 * @param {number} aLawSample The 8-bit A-Law sample
77
 * @return {number}
78
 */
79
function decodeSample(aLawSample) {
80
  /** @type {number} */
81
  let sign = 0;
82
  aLawSample ^= 0x55;
83
  if (aLawSample & 0x80) {
0 ignored issues
show
introduced by
You have used a bitwise operator & in a condition. Did you maybe want to use the logical operator &&
Loading history...
84
    aLawSample &= ~(1 << 7);
85
    sign = -1;
86
  }
87
  /** @type {number} */
88
  let position = ((aLawSample & 0xF0) >> 4) + 4;
89
  /** @type {number} */
90
  let decoded = 0;
91
  if (position != 4) {
92
    decoded = ((1 << position) |
93
      ((aLawSample & 0x0F) << (position - 4)) |
94
      (1 << (position - 5)));
95
  } else {
96
    decoded = (aLawSample << 1)|1;
97
  }
98
  decoded = (sign === 0) ? (decoded) : (-decoded);
99
  return (decoded * 8) * -1;
100
}
101
102
/**
103
 * Encode 16-bit linear PCM samples into 8-bit A-Law samples.
104
 * @param {!Array<number>} samples A array of 16-bit PCM samples.
105
 * @return {!Array<number>}
106
 */
107
function encode(samples) {
108
  /** @type {!Array<number>} */
109
  let aLawSamples = [];
110
  for (let i=0; i<samples.length; i++) {
111
    aLawSamples.push(encodeSample(samples[i]));
112
  }
113
  return aLawSamples;
114
}
115
116
/**
117
 * Decode 8-bit A-Law samples into 16-bit linear PCM samples.
118
 * @param {!Array<number>} samples A array of 8-bit A-Law samples.
119
 * @return {!Array<number>}
120
 */
121
function decode(samples) {
122
  /** @type {!Array<number>} */
123
  let pcmSamples = [];
124
  for (let i=0; i<samples.length; i++) {
125
    pcmSamples.push(decodeSample(samples[i]));
126
  }
127
  return pcmSamples;
128
}
129
130
/** @export */
131
module.exports.encodeSample = encodeSample;
132
/** @export */
133
module.exports.decodeSample = decodeSample;
134
/** @export */
135
module.exports.encode = encode;
136
/** @export */
137
module.exports.decode = decode;
138