sip-lab 1.40.1 → 1.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEV.md +19 -11
- package/README.md +6 -13
- package/binding.gyp +2 -1
- package/index.js +1 -1
- package/package.json +8 -3
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/runtests +25 -9
- package/samples/call_with_authentication.js +278 -0
- package/samples/{t → speex.js} +5 -14
- package/src/pjmedia/src/pjmedia/bfsk_det.c +115 -102
- package/src/pjmedia/src/pjmedia/bfsk_det2.c +171 -109
- package/prebuilds/linux-x64/node.abi102.node +0 -0
- package/prebuilds/linux-x64/node.abi108.node +0 -0
- package/prebuilds/linux-x64/node.abi111.node +0 -0
- package/prebuilds/linux-x64/node.abi115.node +0 -0
- package/prebuilds/linux-x64/node.abi120.node +0 -0
- package/prebuilds/linux-x64/node.abi88.node +0 -0
- package/prebuilds/linux-x64/node.abi93.node +0 -0
- package/src/sip.cpp.old +0 -9236
|
@@ -18,18 +18,34 @@
|
|
|
18
18
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/*
|
|
22
|
+
* BFSK detector variant 2: uses spandsp's Goertzel implementation.
|
|
23
|
+
*
|
|
24
|
+
* spandsp's goertzel_result() returns the squared DFT magnitude for the
|
|
25
|
+
* configured frequency. For a full-scale sine wave of N samples the
|
|
26
|
+
* expected result is approximately:
|
|
27
|
+
*
|
|
28
|
+
* ((N * 32768.0 / sqrt(2)) ^ 2 [float build]
|
|
29
|
+
*
|
|
30
|
+
* We derive a per-instance threshold from the reference level at creation
|
|
31
|
+
* time so the detector scales correctly with block size and sample rate.
|
|
32
|
+
*/
|
|
33
|
+
|
|
21
34
|
#include <pjmedia/bfsk_det2.h>
|
|
22
35
|
#include <pjmedia/errno.h>
|
|
23
36
|
#include <pjmedia/port.h>
|
|
24
37
|
#include <pj/assert.h>
|
|
25
38
|
#include <pj/pool.h>
|
|
26
39
|
#include <pj/string.h>
|
|
40
|
+
#include <pj/log.h>
|
|
27
41
|
|
|
28
42
|
#include <spandsp.h>
|
|
29
43
|
#include <spandsp/expose.h>
|
|
30
44
|
#include <spandsp/tone_detect.h>
|
|
31
45
|
|
|
32
46
|
#include <math.h>
|
|
47
|
+
#include <stdio.h>
|
|
48
|
+
#include <stdlib.h>
|
|
33
49
|
|
|
34
50
|
#define SIGNATURE PJMEDIA_SIGNATURE('b', 'f', 'd', '2')
|
|
35
51
|
#define THIS_FILE "bfsk_det2.c"
|
|
@@ -40,68 +56,113 @@
|
|
|
40
56
|
# define TRACE_(expr)
|
|
41
57
|
#endif
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
/*
|
|
60
|
+
* Number of samples fed to each Goertzel block.
|
|
61
|
+
* 102 samples @ 8000 Hz = ~12.75 ms per block, ~78 Hz resolution.
|
|
62
|
+
* This matches spandsp's DTMF detector block size and is a good trade-off
|
|
63
|
+
* between latency and frequency selectivity for telephony FSK.
|
|
64
|
+
*/
|
|
65
|
+
#define SAMPLES_PER_BLOCK 102
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* Detection threshold expressed as a fraction of the full-scale reference
|
|
69
|
+
* magnitude. 0.05 = the tone must carry at least 5% of full-scale energy
|
|
70
|
+
* to be declared present. Increase toward 1.0 for noisier environments.
|
|
71
|
+
*/
|
|
72
|
+
#define THRESHOLD_RATIO 0.05f
|
|
46
73
|
|
|
47
74
|
static pj_status_t bfsk_det2_put_frame(pjmedia_port *this_port,
|
|
48
|
-
|
|
75
|
+
pjmedia_frame *frame);
|
|
49
76
|
static pj_status_t bfsk_det2_on_destroy(pjmedia_port *this_port);
|
|
50
77
|
|
|
51
78
|
struct bfsk_det2
|
|
52
79
|
{
|
|
53
|
-
struct pjmedia_port
|
|
80
|
+
struct pjmedia_port base;
|
|
54
81
|
int clock_rate;
|
|
55
82
|
int freq_zero;
|
|
56
83
|
int freq_one;
|
|
57
84
|
|
|
85
|
+
/*
|
|
86
|
+
* *_in_progress: set when the corresponding tone was above threshold in
|
|
87
|
+
* the previous block. A bit is reported on the trailing edge.
|
|
88
|
+
* Mutual exclusion is enforced by the dominant-frequency logic.
|
|
89
|
+
*/
|
|
58
90
|
int zero_in_progress;
|
|
59
91
|
int one_in_progress;
|
|
60
92
|
|
|
61
|
-
|
|
62
|
-
int32_t energy;
|
|
63
|
-
|
|
93
|
+
/* spandsp Goertzel descriptors (static configuration) and states. */
|
|
64
94
|
goertzel_descriptor_t desc_zero;
|
|
65
95
|
goertzel_descriptor_t desc_one;
|
|
96
|
+
goertzel_state_t state_zero;
|
|
97
|
+
goertzel_state_t state_one;
|
|
66
98
|
|
|
67
|
-
|
|
68
|
-
|
|
99
|
+
/*
|
|
100
|
+
* Threshold in the same units as goertzel_result().
|
|
101
|
+
* Computed at create time as THRESHOLD_RATIO * reference_magnitude.
|
|
102
|
+
*/
|
|
103
|
+
#if defined(SPANDSP_USE_FIXED_POINT)
|
|
104
|
+
int32_t threshold;
|
|
105
|
+
#else
|
|
106
|
+
float threshold;
|
|
107
|
+
#endif
|
|
69
108
|
|
|
70
109
|
void (*bfsk_cb)(pjmedia_port*, void*, int);
|
|
71
110
|
void *bfsk_cb_user_data;
|
|
72
111
|
};
|
|
73
112
|
|
|
74
|
-
|
|
113
|
+
/*
|
|
114
|
+
* Compute the Goertzel result for a synthetic full-scale pure sine wave
|
|
115
|
+
* at the given frequency so we can derive a calibrated threshold.
|
|
116
|
+
*/
|
|
117
|
+
#if defined(SPANDSP_USE_FIXED_POINT)
|
|
118
|
+
static int32_t compute_reference_magnitude(int freq, int sample_rate)
|
|
119
|
+
#else
|
|
120
|
+
static float compute_reference_magnitude(int freq, int sample_rate)
|
|
121
|
+
#endif
|
|
122
|
+
{
|
|
123
|
+
goertzel_descriptor_t desc;
|
|
124
|
+
goertzel_state_t state;
|
|
125
|
+
double t = 0.0;
|
|
126
|
+
double tstep = 1.0 / sample_rate;
|
|
127
|
+
int i;
|
|
128
|
+
|
|
129
|
+
make_goertzel_descriptor(&desc, (float)freq, SAMPLES_PER_BLOCK);
|
|
130
|
+
goertzel_init(&state, &desc);
|
|
131
|
+
|
|
132
|
+
for (i = 0; i < SAMPLES_PER_BLOCK; i++) {
|
|
133
|
+
int16_t s = (int16_t)(32767.0 * sin(2.0 * M_PI * freq * t));
|
|
134
|
+
goertzel_sample(&state, s);
|
|
135
|
+
t += tstep;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return goertzel_result(&state);
|
|
139
|
+
}
|
|
75
140
|
|
|
76
141
|
PJ_DEF(pj_status_t) pjmedia_bfsk_det2_create( pj_pool_t *pool,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
142
|
+
unsigned clock_rate,
|
|
143
|
+
unsigned channel_count,
|
|
144
|
+
unsigned samples_per_frame,
|
|
145
|
+
unsigned bits_per_sample,
|
|
146
|
+
void (*cb)(pjmedia_port*,
|
|
147
|
+
void *user_data,
|
|
148
|
+
int bit),
|
|
149
|
+
void *user_data,
|
|
85
150
|
int freq_zero,
|
|
86
151
|
int freq_one,
|
|
87
|
-
|
|
152
|
+
pjmedia_port **p_port)
|
|
88
153
|
{
|
|
89
|
-
//printf("pjmedia_bfsk_det2_create\n");
|
|
90
154
|
struct bfsk_det2 *det;
|
|
91
|
-
|
|
92
155
|
const pj_str_t name = pj_str("bfsk_det2");
|
|
93
156
|
|
|
94
157
|
PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
|
|
158
|
+
samples_per_frame && bits_per_sample == 16 &&
|
|
159
|
+
p_port != NULL, PJ_EINVAL);
|
|
99
160
|
|
|
100
161
|
det = PJ_POOL_ZALLOC_T(pool, struct bfsk_det2);
|
|
101
|
-
PJ_ASSERT_RETURN(
|
|
162
|
+
PJ_ASSERT_RETURN(det != NULL, PJ_ENOMEM);
|
|
102
163
|
|
|
103
164
|
pjmedia_port_info_init(&det->base.info, &name, SIGNATURE, clock_rate,
|
|
104
|
-
|
|
165
|
+
channel_count, bits_per_sample, samples_per_frame);
|
|
105
166
|
|
|
106
167
|
det->base.put_frame = &bfsk_det2_put_frame;
|
|
107
168
|
det->base.on_destroy = &bfsk_det2_on_destroy;
|
|
@@ -113,108 +174,108 @@ PJ_DEF(pj_status_t) pjmedia_bfsk_det2_create( pj_pool_t *pool,
|
|
|
113
174
|
det->freq_zero = freq_zero;
|
|
114
175
|
det->freq_one = freq_one;
|
|
115
176
|
|
|
116
|
-
|
|
117
|
-
make_goertzel_descriptor(&det->
|
|
177
|
+
/* Initialise spandsp Goertzel descriptors and states. */
|
|
178
|
+
make_goertzel_descriptor(&det->desc_zero, (float)freq_zero, SAMPLES_PER_BLOCK);
|
|
179
|
+
make_goertzel_descriptor(&det->desc_one, (float)freq_one, SAMPLES_PER_BLOCK);
|
|
118
180
|
|
|
119
|
-
goertzel_init(&det->
|
|
120
|
-
goertzel_init(&det->
|
|
181
|
+
goertzel_init(&det->state_zero, &det->desc_zero);
|
|
182
|
+
goertzel_init(&det->state_one, &det->desc_one);
|
|
121
183
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
184
|
+
/*
|
|
185
|
+
* Derive threshold from the reference magnitude of each frequency.
|
|
186
|
+
* Use the average of the two reference levels so a single threshold
|
|
187
|
+
* applies to both detectors.
|
|
188
|
+
*/
|
|
189
|
+
#if defined(SPANDSP_USE_FIXED_POINT)
|
|
190
|
+
{
|
|
191
|
+
int32_t ref0 = compute_reference_magnitude(freq_zero, (int)clock_rate);
|
|
192
|
+
int32_t ref1 = compute_reference_magnitude(freq_one, (int)clock_rate);
|
|
193
|
+
det->threshold = (int32_t)(THRESHOLD_RATIO * (float)((ref0 + ref1) / 2));
|
|
194
|
+
}
|
|
195
|
+
#else
|
|
196
|
+
{
|
|
197
|
+
float ref0 = compute_reference_magnitude(freq_zero, (int)clock_rate);
|
|
198
|
+
float ref1 = compute_reference_magnitude(freq_one, (int)clock_rate);
|
|
199
|
+
det->threshold = THRESHOLD_RATIO * ((ref0 + ref1) / 2.0f);
|
|
200
|
+
}
|
|
201
|
+
#endif
|
|
128
202
|
|
|
129
|
-
*p_port = &det->base;
|
|
203
|
+
*p_port = &det->base;
|
|
130
204
|
return PJ_SUCCESS;
|
|
131
205
|
}
|
|
132
206
|
|
|
133
207
|
static pj_status_t bfsk_det2_put_frame(pjmedia_port *this_port,
|
|
134
|
-
|
|
208
|
+
pjmedia_frame *frame)
|
|
135
209
|
{
|
|
136
|
-
|
|
137
|
-
if(frame->type != PJMEDIA_FRAME_TYPE_AUDIO) return PJ_SUCCESS;
|
|
210
|
+
if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) return PJ_SUCCESS;
|
|
138
211
|
|
|
139
212
|
struct bfsk_det2 *dport = (struct bfsk_det2*) this_port;
|
|
140
213
|
|
|
141
|
-
|
|
142
|
-
int
|
|
143
|
-
|
|
144
|
-
//printf("p=%x, size=%i clock_rate=%i bits_per_sample=%i\n", frame->buf, size, dport->clock_rate, bps);
|
|
145
|
-
|
|
146
|
-
int16_t * samples = (int16_t*)frame->buf;
|
|
147
|
-
int16_t * num_samples = frame->size/2;
|
|
214
|
+
int16_t *samples = (int16_t*)frame->buf;
|
|
215
|
+
int num_samples = (int)(frame->size / sizeof(int16_t));
|
|
216
|
+
int pos;
|
|
148
217
|
|
|
149
218
|
/*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
219
|
+
* Feed samples into the Goertzel filters one SAMPLES_PER_BLOCK chunk at
|
|
220
|
+
* a time. Any trailing samples that don't fill a complete block are
|
|
221
|
+
* discarded — this matches how spandsp's own tone detectors behave and
|
|
222
|
+
* avoids carrying partial state across frames.
|
|
223
|
+
*/
|
|
224
|
+
for (pos = 0; pos + SAMPLES_PER_BLOCK <= num_samples; pos += SAMPLES_PER_BLOCK) {
|
|
225
|
+
int j;
|
|
226
|
+
for (j = 0; j < SAMPLES_PER_BLOCK; j++) {
|
|
227
|
+
goertzel_sample(&dport->state_zero, samples[pos + j]);
|
|
228
|
+
goertzel_sample(&dport->state_one, samples[pos + j]);
|
|
229
|
+
}
|
|
157
230
|
|
|
158
231
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
int16_t xamp;
|
|
162
|
-
float famp;
|
|
232
|
+
int32_t zero_power = goertzel_result(&dport->state_zero);
|
|
233
|
+
int32_t one_power = goertzel_result(&dport->state_one);
|
|
163
234
|
#else
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
float xamp;
|
|
167
|
-
float famp;
|
|
235
|
+
float zero_power = goertzel_result(&dport->state_zero);
|
|
236
|
+
float one_power = goertzel_result(&dport->state_one);
|
|
168
237
|
#endif
|
|
169
238
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
239
|
+
/* goertzel_result() calls goertzel_reset() internally, so the
|
|
240
|
+
* state is ready for the next block without further action. */
|
|
241
|
+
|
|
242
|
+
/*
|
|
243
|
+
* FSK: at most one frequency should be active at a time.
|
|
244
|
+
* When both exceed the threshold pick the stronger one.
|
|
245
|
+
*/
|
|
246
|
+
int zero, one;
|
|
247
|
+
if (zero_power >= dport->threshold || one_power >= dport->threshold) {
|
|
248
|
+
if (zero_power >= one_power) {
|
|
249
|
+
zero = 1;
|
|
250
|
+
one = 0;
|
|
251
|
+
} else {
|
|
252
|
+
zero = 0;
|
|
253
|
+
one = 1;
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
zero = 0;
|
|
257
|
+
one = 0;
|
|
258
|
+
}
|
|
176
259
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
dport->energy += xamp*xamp;
|
|
188
|
-
#endif
|
|
189
|
-
goertzel_samplex(&dport->goertzel_zero, xamp);
|
|
190
|
-
goertzel_samplex(&dport->goertzel_one, xamp);
|
|
260
|
+
TRACE_((THIS_FILE, "zero_power=%f one_power=%f threshold=%f zero=%d one=%d",
|
|
261
|
+
(double)zero_power, (double)one_power, (double)dport->threshold,
|
|
262
|
+
zero, one));
|
|
263
|
+
|
|
264
|
+
/* Report bit=0 on trailing edge of zero tone. */
|
|
265
|
+
if (dport->zero_in_progress && !zero) {
|
|
266
|
+
dport->bfsk_cb((pjmedia_port*)dport, dport->bfsk_cb_user_data, 0);
|
|
267
|
+
dport->zero_in_progress = 0;
|
|
268
|
+
} else {
|
|
269
|
+
dport->zero_in_progress = zero;
|
|
191
270
|
}
|
|
192
|
-
}
|
|
193
|
-
int32_t zero_power = goertzel_result(&dport->goertzel_zero);
|
|
194
|
-
int32_t one_power = goertzel_result(&dport->goertzel_one);
|
|
195
|
-
|
|
196
|
-
int zero = zero_power > dport->threshold;
|
|
197
|
-
int one = one_power > dport->threshold;
|
|
198
|
-
|
|
199
|
-
printf("zero_power=%f zero_in_progress=%i zero=%i threshold=%f\n", zero_power, dport->zero_in_progress, zero, dport->threshold);
|
|
200
|
-
printf(" one_power=%f one_in_progress=%i one=%i threshold=%f\n", one_power, dport->one_in_progress, one, dport->threshold);
|
|
201
|
-
|
|
202
|
-
// Check for zero signal extinction
|
|
203
|
-
if(dport->zero_in_progress && zero == 0) {
|
|
204
|
-
printf("notifying bit=0\n");
|
|
205
|
-
dport->bfsk_cb((pjmedia_port*)dport, dport->bfsk_cb_user_data, 0);
|
|
206
|
-
dport->zero_in_progress = 0;
|
|
207
|
-
} else {
|
|
208
|
-
dport->zero_in_progress = zero;
|
|
209
|
-
}
|
|
210
271
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
272
|
+
/* Report bit=1 on trailing edge of one tone. */
|
|
273
|
+
if (dport->one_in_progress && !one) {
|
|
274
|
+
dport->bfsk_cb((pjmedia_port*)dport, dport->bfsk_cb_user_data, 1);
|
|
275
|
+
dport->one_in_progress = 0;
|
|
276
|
+
} else {
|
|
277
|
+
dport->one_in_progress = one;
|
|
278
|
+
}
|
|
218
279
|
}
|
|
219
280
|
|
|
220
281
|
return PJ_SUCCESS;
|
|
@@ -222,5 +283,6 @@ static pj_status_t bfsk_det2_put_frame(pjmedia_port *this_port,
|
|
|
222
283
|
|
|
223
284
|
static pj_status_t bfsk_det2_on_destroy(pjmedia_port *this_port)
|
|
224
285
|
{
|
|
286
|
+
PJ_UNUSED_ARG(this_port);
|
|
225
287
|
return PJ_SUCCESS;
|
|
226
288
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|