Passed
Branch v10.3.x (f8533c)
by Rafael S.
07:15 queued 48s
created

lib/resampler/index.js   A

Complexity

Total Complexity 12
Complexity/F 3

Size

Lines of Code 110
Function Count 4

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 110
rs 10
c 0
b 0
f 0
wmc 12
mnd 8
bc 8
fnc 4
bpm 2
cpm 3
noi 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
A index.js ➔ upsample_ 0 11 3
A index.js ➔ downsample_ 0 13 3
A index.js ➔ resample 0 43 4
A index.js ➔ resample_ 0 6 2
1
/*
2
 * Copyright (c) 2019 Rafael da Silva Rocha.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
/**
26
 * @fileoverview The resample function.
27
 * @see https://github.com/rochars/wavefile
28
 */
29
30
import { Interpolator } from './interpolator';
31
import { FIRLPF } from './fir-lpf';
32
33
/**
34
 * Change the sample rate of the samples to a new sample rate.
35
 * @param {!Array|!TypedArray} samples The original samples.
36
 * @param {number} oldSampleRate The original sample rate.
37
 * @param {number} sampleRate The target sample rate.
38
 * @param {?Object} details The extra configuration, if needed.
39
 * @return {!Float64Array} the new samples.
40
 */
41
export function resample(samples, oldSampleRate, sampleRate, details={}) {  
42
  // Make the new sample container
43
  let rate = ((sampleRate - oldSampleRate) / oldSampleRate) + 1;
44
  let newSamples = new Float64Array(samples.length * (rate));
45
  // Create the interpolator
46
  let interpolator = new Interpolator(
47
    samples.length,
48
    newSamples.length,
49
    {
50
      method: details.method || 'cubic',
51
      tension: details.tension || 0,
52
      sincFilterSize: details.sincFilterSize || 32,
53
      sincWindow: details.sincWindow || undefined,
54
      lanczosFilterSize: details.lanczosFilterSize || 16,
55
      clip: details.clip || 'mirror'
56
    });
57
  // Default config
58
  details.LPF = details.LPF === undefined ? true : details.LPF;
59
  // Resample + LPF
60
  if (details.LPF) {
61
    // Upsampling
62
    if (sampleRate > oldSampleRate) {
63
      let filter = new FIRLPF(
64
        details.LPForder || 71,
65
        sampleRate,
66
        (oldSampleRate / 2));
67
      upsample_(
68
        samples, newSamples, interpolator, filter);
69
    // Downsampling
70
    } else {
71
      let filter = new FIRLPF(
72
        details.LPForder || 71,
73
        oldSampleRate,
74
        sampleRate / 2);
75
      downsample_(
76
        samples, newSamples, interpolator, filter);
77
    }
78
  // Resample, no LPF
79
  } else {
80
    resample_(samples, newSamples, interpolator);
81
  }
82
  return newSamples;
83
}
84
85
/**
86
 * Resample.
87
 * @param {!Array|!TypedArray} samples The original samples.
88
 * @param {!Float64Array} newSamples The container for the new samples.
89
 * @param {Object} interpolator The interpolator.
90
 * @private
91
 */
92
function resample_(samples, newSamples, interpolator) {
93
  // Resample
94
  for (let i = 0, len = newSamples.length; i < len; i++) {
95
    newSamples[i] = interpolator.interpolate(i, samples);
96
  }
97
}
98
99
/**
100
 * Upsample with LPF.
101
 * @param {!Array|!TypedArray} samples The original samples.
102
 * @param {!Float64Array} newSamples The container for the new samples.
103
 * @param {Object} interpolator The interpolator.
104
 * @param {Object} filter The LPF object.
105
 * @private
106
 */
107
function upsample_(samples, newSamples, interpolator, filter) {
108
  // Resample and filter
109
  for (let i = 0, len = newSamples.length; i < len; i++) {
110
    newSamples[i] = filter.filter(interpolator.interpolate(i, samples));
111
  }
112
  // Reverse filter
113
  filter.reset();
114
  for (let i = newSamples.length - 1; i >= 0; i--) {
115
    newSamples[i]  = filter.filter(newSamples[i]);
116
  }
117
}
118
119
/**
120
 * Downsample with LPF.
121
 * @param {!Array|!TypedArray} samples The original samples.
122
 * @param {!Float64Array} newSamples The container for the new samples.
123
 * @param {Object} interpolator The interpolator.
124
 * @param {Object} filter The LPF object.
125
 * @private
126
 */
127
function downsample_(samples, newSamples, interpolator, filter) {
128
  // Filter
129
  for (let i = 0, len = samples.length; i < len; i++) {
130
    samples[i]  = filter.filter(samples[i]);
131
  }
132
  // Reverse filter
133
  filter.reset();
134
  for (let i = samples.length - 1; i >= 0; i--) {
135
    samples[i]  = filter.filter(samples[i]);
136
  }
137
  // Resample
138
  resample_(samples, newSamples, interpolator);
139
}
140