-
Notifications
You must be signed in to change notification settings - Fork 2
/
afsk-encoder.js
91 lines (81 loc) · 2.72 KB
/
afsk-encoder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
function FskEncoder(sampleRate, lbr) {
if (lbr == true) {
this.f_lo = 8666 / 4;
this.f_hi = 12500 / 4;
this.baud_rate = 8000 / 4;
} else {
this.f_lo = 8666;
this.f_hi = 12500;
this.baud_rate = 8000;
}
this.sample_rate = sampleRate;
this.state.omega_lo = (2 * Math.PI * this.f_lo) / this.sample_rate;
this.state.omega_hi = (2 * Math.PI * this.f_hi) / this.sample_rate;
this.state.phase = 0;
this.state.current_bit = 0;
this.state.baud_frac = 0;
this.state.baud_incr = this.baud_rate / this.sample_rate;
}
FskEncoder.prototype = {
// All of these settings are assigned in the constructor.
f_lo: 0,
f_hi: 0,
baud_rate: 0,
sample_rate: 0,
state: {
phase: 0,
omega_lo: 0,
omega_hi: 0,
current_bit: 0,
baud_frac: 0,
baud_incr: 0,
curbyte: 0,
bitpos: 0,
datapos: 0,
},
PHASE_BITS: 16,
PHASE_BASE: (1 << 16), // hardcode PHASE_BITS here b/c javascript can't reference initializers in initializers
// compute samples per bit. Needed to allocate audio buffers before modulating
samplesPerBit: function () {
return this.sample_rate / this.baud_rate; // Not rounded! Floating point!
},
// for debug.
dumpBuffer: function (buf) {
var out = "";
for (var i = 0; i < buf.length; i++)
out += "0x" + buf[i].toString(16) + ",";
return out;
},
// does what you think it does -- input data should be uint8 array, outputdata is floats
modulate: function (inputData, outputData) {
for (var i = 0; i < outputData.length; i++) {
this.state.baud_frac += this.state.baud_incr;
if (this.state.baud_frac >= 1) {
this.state.baud_frac -= 1;
if (this.state.bitpos == 0) {
if (this.state.datapos <= inputData.length) {
this.state.curbyte = inputData[this.state.datapos++];
this.state.bitpos = 8;
} else {
return outputData;
}
}
this.state.current_bit = this.state.curbyte & 1;
this.state.curbyte >>= 1;
this.state.bitpos--;
}
outputData[i] = Math.cos(this.state.phase);
if (this.state.current_bit == 0) {
this.state.phase += this.state.omega_lo;
} else {
this.state.phase += this.state.omega_hi;
}
}
this.state.datapos = 0;
return outputData;
}
};
// AMD exports
if (typeof module !== "undefined" && module.exports) {
module.exports = FskEncoder;
}