Completed
Branch v10.2.x (c81ed9)
by Rafael S.
16:21
created

FIRLPF.filter   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 10
rs 10
c 0
b 0
f 0
cc 2
1
/*
2
 * Copyright (c) 2019 Rafael da Silva Rocha.
3
 * Copyright (c) 2014 Florian Markert
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining
6
 * a copy of this software and associated documentation files (the
7
 * "Software"), to deal in the Software without restriction, including
8
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * distribute, sublicense, and/or sell copies of the Software, and to
10
 * permit persons to whom the Software is furnished to do so, subject to
11
 * the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 */
25
26
/**
27
 * @fileoverview FIR LPF. Based on the FIR LPF from Fili by Florian Markert.
28
 * @see https://github.com/rochars/wavefile
29
 * @see https://github.com/markert/fili.js
30
 */
31
32
/**
33
 * A FIR low pass filter.
34
 */
35
export class FIRLPF {
36
  
37
  /**
38
   * @param {number} order The order of the filter.
39
   * @param {number} sampleRate The sample rate.
40
   * @param {number} cutOff The cut off frequency.
41
   */
42
  constructor(order, sampleRate, cutOff) {
43
    let omega = 2 * Math.PI * cutOff / sampleRate;
44
    let dc = 0;
45
    this.filters = [];
46
    for (let i = 0; i <= order; i++) {
47
      if (i - order / 2 === 0) {
48
        this.filters[i] = omega;
49
      } else {
50
        this.filters[i] = Math.sin(omega * (i - order / 2)) / (i - order / 2);
51
        // Hamming window
52
        this.filters[i] *= (0.54 - 0.46 * Math.cos(2 * Math.PI * i / order));
53
      }
54
      dc = dc + this.filters[i];
55
    }
56
    // normalize
57
    for (let i = 0; i <= order; i++) {
58
      this.filters[i] /= dc;
59
    }
60
    let b = [];
61
    for (let i = 0; i < this.filters.length; i++) {
62
      b[i] = {
63
        re: this.filters[i],
64
        im: 0
65
      };
66
    }
67
    let r = [];
68
    for (let i = 0; i < this.filters.length - 1; i++) {
69
      r.push(0);
70
    }
71
    this.z = {
72
      buf: r,
73
      pointer: 0
74
    };
75
  }
76
77
  /**
78
   * @param {number} sample A sample of a sequence.
79
   * @return {number}
80
   */
81
  filter(sample) {
82
    this.z.buf[this.z.pointer] = sample;
83
    let out = 0;
84
    for (let i = 0; i < this.z.buf.length; i++) {
85
      out += (
86
        this.filters[i] * this.z.buf[(this.z.pointer + i) % this.z.buf.length]);
87
    }
88
    this.z.pointer = (this.z.pointer + 1) % (this.z.buf.length);
89
    return out;
90
  }
91
}
92