sip-lab 1.29.0 → 1.30.0

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.
@@ -0,0 +1,164 @@
1
+ var sip = require ('../index.js')
2
+ var Zeq = require('@mayama/zeq')
3
+ var z = new Zeq()
4
+ var m = require('data-matching')
5
+ var sip_msg = require('sip-matching')
6
+ var sdp = require('sdp-matching')
7
+
8
+ function stringToBinary(str) {
9
+ return str.split('').map(char => {
10
+ return char.charCodeAt(0).toString(2).padStart(8, '0');
11
+ }).join('');
12
+ }
13
+
14
+ async function test() {
15
+ //sip.set_log_level(6)
16
+ sip.dtmf_aggregation_on(500)
17
+
18
+ sip.set_codecs("PCMU/8000/1:128")
19
+
20
+ z.trap_events(sip.event_source, 'event', (evt) => {
21
+ var e = evt.args[0]
22
+ return e
23
+ })
24
+
25
+ console.log(sip.start((data) => { console.log(data)} ))
26
+
27
+ t1 = sip.transport.create({address: "127.0.0.1", type: 'tcp'})
28
+ t2 = sip.transport.create({address: "127.0.0.1", type: 'tcp'})
29
+
30
+ console.log("t1", t1)
31
+ console.log("t2", t2)
32
+
33
+ oc = sip.call.create(t1.id, {
34
+ from_uri: '"abc"<sip:alice@test.com>',
35
+ to_uri: `sip:bob@${t2.address}:${t2.port}`,
36
+ })
37
+
38
+ await z.wait([
39
+ {
40
+ event: "incoming_call",
41
+ call_id: m.collect("call_id"),
42
+ msg: sip_msg({
43
+ $rm: 'INVITE',
44
+ $fU: 'alice',
45
+ $fd: 'test.com',
46
+ $tU: 'bob',
47
+ }),
48
+ },
49
+ {
50
+ event: 'response',
51
+ call_id: oc.id,
52
+ method: 'INVITE',
53
+ msg: sip_msg({
54
+ $rs: '100',
55
+ $rr: 'Trying',
56
+ }),
57
+ },
58
+ ], 1000)
59
+
60
+ ic = {
61
+ id: z.store.call_id,
62
+ sip_call_id: z.store.sip_call_id,
63
+ }
64
+
65
+ sip.call.respond(ic.id, {
66
+ code: 200,
67
+ reason:'OK',
68
+ })
69
+
70
+ await z.wait([
71
+ {
72
+ event: 'media_update',
73
+ call_id: oc.id,
74
+ status: 'ok',
75
+ },
76
+ {
77
+ event: 'media_update',
78
+ call_id: ic.id,
79
+ status: 'ok',
80
+ },
81
+ {
82
+ event: 'response',
83
+ call_id: oc.id,
84
+ method: 'INVITE',
85
+ msg: sip_msg({
86
+ $rs: '200',
87
+ $rr: 'OK',
88
+ }),
89
+ },
90
+ ], 1000)
91
+
92
+ sip.call.start_record_wav(oc.id, {file: './oc.wav'})
93
+ sip.call.start_record_wav(ic.id, {file: './ic.wav'})
94
+
95
+ sip.call.start_bfsk_detection(oc.id, {freq_zero: 500, freq_one: 2000})
96
+ sip.call.start_bfsk_detection(ic.id, {freq_zero: 500, freq_one: 2000})
97
+
98
+ await z.sleep(100)
99
+
100
+ sip.call.start_speech_synth(oc.id, {server_url: 'ws://0.0.0.0:8080', engine: 'bfsk-ss', voice: '5', language: '500:2000', text: 'a', times: 1})
101
+ sip.call.start_speech_synth(ic.id, {server_url: 'ws://0.0.0.0:8080', engine: 'bfsk-ss', voice: '5', language: '500:2000', text: 'b', times: 1})
102
+
103
+ await z.wait([
104
+ {
105
+ event: 'speech_synth_complete',
106
+ call_id: ic.id,
107
+ },
108
+ {
109
+ event: 'speech_synth_complete',
110
+ call_id: oc.id,
111
+ },
112
+ {
113
+ event: 'bfsk',
114
+ call_id: oc.id,
115
+ bits: stringToBinary('b'),
116
+ },
117
+ {
118
+ event: 'bfsk',
119
+ call_id: ic.id,
120
+ bits: stringToBinary('a'),
121
+ }
122
+ ], 3000)
123
+
124
+ await z.sleep(1000)
125
+
126
+ sip.call.stop_record_wav(oc.id)
127
+ sip.call.stop_record_wav(ic.id)
128
+
129
+ sip.call.terminate(oc.id)
130
+
131
+ await z.wait([
132
+ {
133
+ event: 'call_ended',
134
+ call_id: oc.id,
135
+ },
136
+ {
137
+ event: 'call_ended',
138
+ call_id: ic.id,
139
+ },
140
+ {
141
+ event: 'response',
142
+ call_id: oc.id,
143
+ method: 'BYE',
144
+ msg: sip_msg({
145
+ $rs: '200',
146
+ $rr: 'OK',
147
+ }),
148
+ },
149
+ ], 1000)
150
+
151
+ await z.sleep(100)
152
+
153
+ console.log("Success")
154
+
155
+ sip.stop()
156
+ }
157
+
158
+
159
+ test()
160
+ .catch(e => {
161
+ console.error(e)
162
+ process.exit(1)
163
+ })
164
+
@@ -16,8 +16,6 @@ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
16
16
  void *user_data,
17
17
  int freq_zero,
18
18
  int freq_one,
19
- int min_level,
20
- int baud_rate,
21
19
  pjmedia_port **p_port);
22
20
 
23
21
  PJ_END_DECL
@@ -21,6 +21,7 @@ PJ_DEF(pj_status_t) pjmedia_ws_speech_port_create( pj_pool_t *pool,
21
21
  unsigned bits_per_sample,
22
22
  pj_websock_endpoint *ws_endpt,
23
23
  const char *server_url,
24
+ const char *uuid,
24
25
  const char *ss_engine,
25
26
  const char *ss_voice,
26
27
  const char *ss_language,
@@ -25,8 +25,7 @@
25
25
  #include <pj/pool.h>
26
26
  #include <pj/string.h>
27
27
 
28
- #include <spandsp.h>
29
- #include <spandsp/expose.h>
28
+ #include <math.h>
30
29
 
31
30
  #define SIGNATURE PJMEDIA_SIGNATURE('b', 'f', 'd', 't')
32
31
  #define THIS_FILE "bfsk_det.c"
@@ -37,6 +36,90 @@
37
36
  # define TRACE_(expr)
38
37
  #endif
39
38
 
39
+ // Adapted https://github.com/ericksc/goertzel/blob/master/main.cpp
40
+
41
+ #define PI 3.14159265358979
42
+
43
+ typedef struct {
44
+ float coeff;
45
+ int fix_coeff;
46
+ int Q1;
47
+ int Q2;
48
+ double sine;
49
+ double cosine;
50
+ } goertzel_t;
51
+
52
+ //Para definir punto fijo de 32 bits.
53
+ int FIXED_POINT_16 = 16;
54
+ int ONE_16 = 1 << 16;
55
+
56
+ int FIXED_POINT_30 = 30;
57
+ int ONE_30 = 1 << 30;
58
+
59
+ int toFix( float val, int ONE ) {
60
+ // Escalamiento
61
+ return (int) (val * ONE);
62
+ }
63
+
64
+ float floatVal( int fix, int ONE ) {
65
+ return ((float) fix) / ONE;
66
+ }
67
+
68
+ int intVal( int fix, int FIXED_POINT ) {
69
+ return fix >> FIXED_POINT;
70
+ }
71
+
72
+ int mul(int fix_coeff, int Q1, int FIXED_POINT_mixed) {
73
+ // Manejo de 64 bit para el resultado inmedianto de la multiplicación
74
+ // Conversion a 32 bits para posterior uso
75
+ return (int)((long long int)fix_coeff * (long long int)Q1 >> FIXED_POINT_mixed);
76
+ }
77
+
78
+ /* Call this routine before every "block" (size=N) of samples. */
79
+ void goertzel_det_reset(goertzel_t *g)
80
+ {
81
+ g->Q2 = 0;
82
+ g->Q1 = 0;
83
+ }
84
+ /* Call this once, to precompute the constants. */
85
+ void goertzel_det_init(goertzel_t *g, float frequency, float sampling_rate, int samples_per_frame)
86
+ {
87
+ int k;
88
+ double floatN;
89
+ double omega;
90
+ floatN = (double)samples_per_frame;
91
+ k = (int)(0.5 + ((floatN * frequency) / sampling_rate));
92
+ omega = (2.0 * PI * k) / floatN;
93
+ g->sine = sin(omega);
94
+ g->cosine = cos(omega);
95
+ g->coeff = 2.0 * g->cosine;
96
+ g->fix_coeff = toFix(g->coeff, ONE_30);
97
+ printf("For sampling_rate = %f", sampling_rate);
98
+ printf("samples_per_frame = %d", samples_per_frame);
99
+ printf(" and frequency = %f,\n", frequency);
100
+ printf("k = %d and coeff = %f\n\n", k, g->coeff);
101
+ goertzel_det_reset(g);
102
+ }
103
+
104
+ float goertzel_mag(goertzel_t *g, int *buf, int size)
105
+ {
106
+ for (int index = 0; index < size; index++)
107
+ {
108
+ // Punto fijo 32. INT
109
+ int Q0;
110
+ Q0 = mul(g->fix_coeff, g->Q1, 30) - g->Q2 + toFix(buf[index], ONE_16);
111
+ g->Q2 = g->Q1;
112
+ g->Q1 = Q0;
113
+ }
114
+
115
+ float result;
116
+ result = floatVal(g->Q1, ONE_16) * floatVal(g->Q1,ONE_16) + floatVal(g->Q2,ONE_16) * floatVal(g->Q2,ONE_16) - floatVal(g->Q1,ONE_16) * floatVal(g->Q2,ONE_16) * g->coeff;
117
+ goertzel_det_reset(g);
118
+ return result;
119
+ }
120
+
121
+
122
+
40
123
  static pj_status_t bfsk_det_put_frame(pjmedia_port *this_port,
41
124
  pjmedia_frame *frame);
42
125
  static pj_status_t bfsk_det_on_destroy(pjmedia_port *this_port);
@@ -44,11 +127,21 @@ static pj_status_t bfsk_det_on_destroy(pjmedia_port *this_port);
44
127
  struct bfsk_det
45
128
  {
46
129
  struct pjmedia_port base;
47
- fsk_rx_state_t state;
130
+ int clock_rate;
131
+ int freq_zero;
132
+ int freq_one;
133
+
134
+ int zero_in_progress;
135
+ int one_in_progress;
136
+
137
+ goertzel_t *goertzel_zero;
138
+ goertzel_t *goertzel_one;
139
+
48
140
  void (*bfsk_cb)(pjmedia_port*, void*, int);
49
141
  void *bfsk_cb_user_data;
50
142
  };
51
143
 
144
+ /*
52
145
  static void bfsk_det_bit_callback(void *user_data, int bit)
53
146
  {
54
147
  printf("bfsk_det_bit_callback got bit=%i\n", bit);
@@ -64,6 +157,7 @@ static void bfsk_det_bit_callback(void *user_data, int bit)
64
157
  dport->bfsk_cb_user_data,
65
158
  bit);
66
159
  }
160
+ */
67
161
 
68
162
  PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
69
163
  unsigned clock_rate,
@@ -76,13 +170,10 @@ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
76
170
  void *user_data,
77
171
  int freq_zero,
78
172
  int freq_one,
79
- int min_level,
80
- int baud_rate,
81
173
  pjmedia_port **p_port)
82
174
  {
83
175
  printf("pjmedia_bfsk_det_create\n");
84
176
  struct bfsk_det *det;
85
- fsk_spec_t *fsk_spec;
86
177
 
87
178
  printf("p1\n");
88
179
  const pj_str_t name = pj_str("bfsk_det");
@@ -102,8 +193,6 @@ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
102
193
  pjmedia_port_info_init(&det->base.info, &name, SIGNATURE, clock_rate,
103
194
  channel_count, bits_per_sample, samples_per_frame);
104
195
 
105
- printf("p4\n");
106
-
107
196
  det->base.put_frame = &bfsk_det_put_frame;
108
197
  det->base.on_destroy = &bfsk_det_on_destroy;
109
198
 
@@ -112,28 +201,28 @@ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
112
201
  det->bfsk_cb = cb;
113
202
  det->bfsk_cb_user_data = user_data;
114
203
 
115
- fsk_spec = PJ_POOL_ZALLOC_T(pool, fsk_spec_t);
116
- PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
117
204
  printf("p6\n");
118
205
 
119
- fsk_spec->name = "bfsk";
120
- fsk_spec->freq_zero = freq_zero;
121
- fsk_spec->freq_one = freq_one;
122
- fsk_spec->min_level = min_level;
123
- fsk_spec->baud_rate = baud_rate;
206
+ det->clock_rate = clock_rate;
207
+ det->freq_zero = freq_zero;
208
+ det->freq_one = freq_one;
124
209
 
125
- int sync_mode = 0;
210
+ float threshold = 0.1;
126
211
 
127
- printf("p7\n");
128
- fsk_rx_state_t *res = fsk_rx_init(&det->state, fsk_spec, sync_mode, &bfsk_det_bit_callback, (void*)det);
129
- if(res != &det->state) {
130
- printf("fsx_rx_init failed\n");
131
- }
212
+ det->goertzel_zero = PJ_POOL_ZALLOC_T(pool, goertzel_t);
213
+ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
214
+
215
+ det->goertzel_one = PJ_POOL_ZALLOC_T(pool, goertzel_t);
216
+ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
132
217
 
133
- //fsk_rx_init(&(det->state), &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, &bfsk_det_bit_callback, (void*)det);
218
+ int sample_rate = clock_rate;
219
+
220
+ goertzel_det_init(det->goertzel_zero, det->freq_zero, sample_rate, samples_per_frame);
221
+ goertzel_det_init(det->goertzel_one, det->freq_one, sample_rate, samples_per_frame);
222
+
223
+ printf("p7\n");
134
224
 
135
- printf("p8\n");
136
- TRACE_((THIS_FILE, "bfsk_det created: %u/%u/%u/%u", clock_rate,
225
+ TRACE_((THIS_FILE, "bfsk_det created: clock_rate=%u channel_count=%u samples_per_frame=%u bits_per_frame=%u", clock_rate,
137
226
  channel_count, samples_per_frame, bits_per_sample));
138
227
 
139
228
  printf("fsk_rx_init done\n");
@@ -150,9 +239,46 @@ static pj_status_t bfsk_det_put_frame(pjmedia_port *this_port,
150
239
 
151
240
  struct bfsk_det *dport = (struct bfsk_det*) this_port;
152
241
 
153
- printf("p=%x, size=%i\n", frame->buf, PJMEDIA_PIA_SPF(&dport->base.info));
154
- fsk_rx(&dport->state, (const pj_int16_t *)frame->buf,
155
- PJMEDIA_PIA_SPF(&dport->base.info));
242
+ int size = PJMEDIA_PIA_SPF(&dport->base.info);
243
+ int bps = PJMEDIA_PIA_BITS(&dport->base.info);
244
+
245
+ printf("p=%x, size=%i clock_rate=%i bits_per_sample=%i\n", frame->buf, size, dport->clock_rate, bps);
246
+
247
+ int16_t * samples = (int16_t*)frame->buf;
248
+
249
+ printf("Buffer contents:\n");
250
+ for (int i = 0; i < size; i++) {
251
+ printf("%04x ", samples[i] & 0xFFFF);
252
+ }
253
+ printf("\n");
254
+
255
+ float zero_power = goertzel_mag(dport->goertzel_zero, frame->buf, size);
256
+ float one_power = goertzel_mag(dport->goertzel_one, frame->buf, size);
257
+
258
+ int zero = zero_power > 1000000000.0;
259
+ int one = one_power > 1000000000.0;
260
+
261
+ printf("zero_power=%f zero_in_progress=%i zero=%i\n", zero_power, dport->zero_in_progress, zero);
262
+ printf("one_power=%f one_in_progress=%i one=%i\n", one_power, dport->one_in_progress, one);
263
+
264
+
265
+ // Check for zero signal extinction
266
+ if(dport->zero_in_progress && zero == 0) {
267
+ printf("notifying bit=0\n");
268
+ dport->bfsk_cb((pjmedia_port*)dport, dport->bfsk_cb_user_data, 0);
269
+ dport->zero_in_progress = 0;
270
+ } else {
271
+ dport->zero_in_progress = zero;
272
+ }
273
+
274
+ // Check for one signal extinction
275
+ if(dport->one_in_progress && one == 0) {
276
+ printf("notifying bit=1\n");
277
+ dport->bfsk_cb((pjmedia_port*)dport, dport->bfsk_cb_user_data, 1);
278
+ dport->one_in_progress = 0;
279
+ } else {
280
+ dport->one_in_progress = one;
281
+ }
156
282
 
157
283
  return PJ_SUCCESS;
158
284
  }
@@ -70,6 +70,8 @@ struct ws_speech_t
70
70
 
71
71
  int sample_rate;
72
72
 
73
+ char *uuid;
74
+
73
75
  char *ss_engine;
74
76
  char *ss_voice;
75
77
  char *ss_language;
@@ -112,6 +114,7 @@ static pj_bool_t on_connect_complete(pj_websock_t *c, pj_status_t status)
112
114
 
113
115
  // Add members to the "args" object
114
116
  args.AddMember("sampleRate", port->sample_rate, allocator);
117
+ args.AddMember("uuid", rapidjson::Value(port->uuid, allocator), allocator);
115
118
  args.AddMember("engine", rapidjson::Value(port->ss_engine, allocator), allocator);
116
119
  args.AddMember("voice", rapidjson::Value(port->ss_voice, allocator), allocator);
117
120
  args.AddMember("language", rapidjson::Value(port->ss_language, allocator), allocator);
@@ -145,6 +148,7 @@ static pj_bool_t on_connect_complete(pj_websock_t *c, pj_status_t status)
145
148
 
146
149
  // Add members to the "args" object
147
150
  args.AddMember("sampleRate", port->sample_rate, allocator);
151
+ args.AddMember("uuid", rapidjson::Value(port->uuid, allocator), allocator);
148
152
  args.AddMember("engine", rapidjson::Value(port->sr_engine, allocator), allocator);
149
153
  args.AddMember("language", rapidjson::Value(port->sr_language, allocator), allocator);
150
154
 
@@ -237,6 +241,7 @@ PJ_DEF(pj_status_t) pjmedia_ws_speech_port_create(pj_pool_t *pool,
237
241
  unsigned bits_per_sample,
238
242
  struct pj_websock_endpoint *ws_endpt,
239
243
  const char *server_url,
244
+ const char *uuid,
240
245
  const char *ss_engine,
241
246
  const char *ss_voice,
242
247
  const char *ss_language,
@@ -265,6 +270,9 @@ PJ_DEF(pj_status_t) pjmedia_ws_speech_port_create(pj_pool_t *pool,
265
270
 
266
271
  port->sample_rate = clock_rate;
267
272
 
273
+ port->uuid = (char*)pj_pool_alloc(pool, strlen(uuid) + 1);
274
+ pj_ansi_strcpy(port->uuid, uuid);
275
+
268
276
  if(ss_engine) {
269
277
  port->ss_engine = (char*)pj_pool_alloc(pool, strlen(ss_engine) + 1);
270
278
  pj_ansi_strcpy(port->ss_engine, ss_engine);