sip-lab 1.28.12 → 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.
Files changed (47) hide show
  1. package/DEV.md +55 -0
  2. package/README.md +8 -2
  3. package/binding.gyp +1 -0
  4. package/build_deps.sh +2 -1
  5. package/index.js +7 -0
  6. package/package.json +1 -1
  7. package/prebuilds/linux-x64/node.abi102.node +0 -0
  8. package/prebuilds/linux-x64/node.abi108.node +0 -0
  9. package/prebuilds/linux-x64/node.abi111.node +0 -0
  10. package/prebuilds/linux-x64/node.abi115.node +0 -0
  11. package/prebuilds/linux-x64/node.abi120.node +0 -0
  12. package/prebuilds/linux-x64/node.abi88.node +0 -0
  13. package/prebuilds/linux-x64/node.abi93.node +0 -0
  14. package/samples/100_calls.js +4 -0
  15. package/samples/16_audio_streams.js +2 -0
  16. package/samples/183_session_progress.js +2 -0
  17. package/samples/delayed_media.js +2 -0
  18. package/samples/four_audio_streams_two_refused.js +7 -4
  19. package/samples/mrcp_and_audio.simplified_media.js +2 -0
  20. package/samples/multiple_audio_streams.js +2 -0
  21. package/samples/refuse_telephone_event.js +3 -0
  22. package/samples/reinvite_and_dtmf.js +3 -0
  23. package/samples/reinvite_audio_audio.js +2 -0
  24. package/samples/reinvite_with_hold_unhold.js +2 -0
  25. package/samples/rtp_and_srtp.js +3 -0
  26. package/samples/rtp_and_srtp.rtp_refused.js +3 -0
  27. package/samples/send_and_receive_bfsk.js.future +171 -0
  28. package/samples/srtp.js +3 -0
  29. package/samples/tcp.js +2 -0
  30. package/samples/text_to_speech.js +3 -0
  31. package/samples/two_audio_streams.js +4 -0
  32. package/samples/two_audio_streams.port_zero.js +4 -0
  33. package/samples_extra/ws_speech_server.bfsk.js +154 -0
  34. package/samples_extra/ws_speech_server.dtmf.js +5 -21
  35. package/samples_extra/ws_speech_server.google.js +8 -10
  36. package/samples_extra/ws_speech_server.send_bfsk.js +156 -0
  37. package/samples_extra/ws_speech_server.start_bfsk_detection.js.future +164 -0
  38. package/src/addon.cpp +180 -10
  39. package/src/event_templates.cpp +8 -0
  40. package/src/event_templates.hpp +3 -0
  41. package/src/pjmedia/include/pjmedia/bfsk_det.h +23 -0
  42. package/src/pjmedia/include/pjmedia/ws_speech_port.h +1 -0
  43. package/src/pjmedia/src/pjmedia/bfsk_det.c +289 -0
  44. package/src/pjmedia/src/pjmedia/ws_speech_port.cpp +8 -0
  45. package/src/sip.cpp +552 -35
  46. package/src/sip.cpp.old +9236 -0
  47. package/src/sip.hpp +11 -0
package/src/addon.cpp CHANGED
@@ -399,6 +399,40 @@ Napi::Value call_send_dtmf(const Napi::CallbackInfo &info) {
399
399
  return env.Null();
400
400
  }
401
401
 
402
+ Napi::Value call_send_bfsk(const Napi::CallbackInfo &info) {
403
+ Napi::Env env = info.Env();
404
+
405
+ if (info.Length() != 2) {
406
+ Napi::Error::New(env,
407
+ "Wrong number of arguments. Expected: call_id, params.")
408
+ .ThrowAsJavaScriptException();
409
+ return env.Null();
410
+ }
411
+
412
+ if (!info[0].IsNumber()) {
413
+ Napi::TypeError::New(env, "call_id must be number.")
414
+ .ThrowAsJavaScriptException();
415
+ return env.Null();
416
+ }
417
+ int call_id = info[0].As<Napi::Number>().Int32Value();
418
+
419
+ if (!info[1].IsString()) {
420
+ Napi::TypeError::New(env, "params must be a JSON string.")
421
+ .ThrowAsJavaScriptException();
422
+ return env.Null();
423
+ }
424
+ const string json = info[1].As<Napi::String>().Utf8Value();
425
+
426
+ int res = pjw_call_send_bfsk(call_id, json.c_str());
427
+
428
+ if (res != 0) {
429
+ Napi::Error::New(env, pjw_get_error()).ThrowAsJavaScriptException();
430
+ return env.Null();
431
+ }
432
+
433
+ return env.Null();
434
+ }
435
+
402
436
  Napi::Value call_reinvite(const Napi::CallbackInfo &info) {
403
437
  Napi::Env env = info.Env();
404
438
 
@@ -637,6 +671,141 @@ Napi::Value call_start_speech_recog(const Napi::CallbackInfo &info) {
637
671
  return env.Null();
638
672
  }
639
673
 
674
+ Napi::Value call_start_inband_dtmf_detection(const Napi::CallbackInfo &info) {
675
+ Napi::Env env = info.Env();
676
+
677
+ if (info.Length() != 2) {
678
+ Napi::Error::New(env,
679
+ "Wrong number of arguments. Expected: call_id, params.")
680
+ .ThrowAsJavaScriptException();
681
+ return env.Null();
682
+ }
683
+
684
+ if (!info[0].IsNumber()) {
685
+ Napi::TypeError::New(env, "call_id must be number.")
686
+ .ThrowAsJavaScriptException();
687
+ return env.Null();
688
+ }
689
+ int call_id = info[0].As<Napi::Number>().Int32Value();
690
+
691
+ if (!info[1].IsString()) {
692
+ Napi::TypeError::New(env, "params must be a JSON string.")
693
+ .ThrowAsJavaScriptException();
694
+ return env.Null();
695
+ }
696
+ const string json = info[1].As<Napi::String>().Utf8Value();
697
+
698
+ int res = pjw_call_start_inband_dtmf_detection(call_id, json.c_str());
699
+
700
+ if (res != 0) {
701
+ Napi::Error::New(env, pjw_get_error()).ThrowAsJavaScriptException();
702
+ return env.Null();
703
+ }
704
+
705
+ return env.Null();
706
+ }
707
+
708
+ Napi::Value call_stop_inband_dtmf_detection(const Napi::CallbackInfo &info) {
709
+ Napi::Env env = info.Env();
710
+
711
+ if (info.Length() != 2) {
712
+ Napi::Error::New(env, "Wrong number of arguments. Expected: call_id")
713
+ .ThrowAsJavaScriptException();
714
+ return env.Null();
715
+ }
716
+
717
+ if (!info[0].IsNumber()) {
718
+ Napi::TypeError::New(env, "call_id must be number.")
719
+ .ThrowAsJavaScriptException();
720
+ return env.Null();
721
+ }
722
+ int call_id = info[0].As<Napi::Number>().Int32Value();
723
+
724
+ if (!info[1].IsString()) {
725
+ Napi::TypeError::New(env, "params must be a JSON string.")
726
+ .ThrowAsJavaScriptException();
727
+ return env.Null();
728
+ }
729
+ const string json = info[1].As<Napi::String>().Utf8Value();
730
+
731
+ int res = pjw_call_stop_inband_dtmf_detection(call_id, json.c_str());
732
+
733
+ if (res != 0) {
734
+ Napi::Error::New(env, pjw_get_error()).ThrowAsJavaScriptException();
735
+ return env.Null();
736
+ }
737
+
738
+ return env.Null();
739
+ }
740
+
741
+ Napi::Value call_start_bfsk_detection(const Napi::CallbackInfo &info) {
742
+ Napi::Env env = info.Env();
743
+
744
+ if (info.Length() != 2) {
745
+ Napi::Error::New(env,
746
+ "Wrong number of arguments. Expected: call_id, params.")
747
+ .ThrowAsJavaScriptException();
748
+ return env.Null();
749
+ }
750
+
751
+ if (!info[0].IsNumber()) {
752
+ Napi::TypeError::New(env, "call_id must be number.")
753
+ .ThrowAsJavaScriptException();
754
+ return env.Null();
755
+ }
756
+ int call_id = info[0].As<Napi::Number>().Int32Value();
757
+
758
+ if (!info[1].IsString()) {
759
+ Napi::TypeError::New(env, "params must be a JSON string.")
760
+ .ThrowAsJavaScriptException();
761
+ return env.Null();
762
+ }
763
+ const string json = info[1].As<Napi::String>().Utf8Value();
764
+
765
+ int res = pjw_call_start_bfsk_detection(call_id, json.c_str());
766
+
767
+ if (res != 0) {
768
+ Napi::Error::New(env, pjw_get_error()).ThrowAsJavaScriptException();
769
+ return env.Null();
770
+ }
771
+
772
+ return env.Null();
773
+ }
774
+
775
+ Napi::Value call_stop_bfsk_detection(const Napi::CallbackInfo &info) {
776
+ Napi::Env env = info.Env();
777
+
778
+ if (info.Length() != 2) {
779
+ Napi::Error::New(env, "Wrong number of arguments. Expected: call_id")
780
+ .ThrowAsJavaScriptException();
781
+ return env.Null();
782
+ }
783
+
784
+ if (!info[0].IsNumber()) {
785
+ Napi::TypeError::New(env, "call_id must be number.")
786
+ .ThrowAsJavaScriptException();
787
+ return env.Null();
788
+ }
789
+ int call_id = info[0].As<Napi::Number>().Int32Value();
790
+
791
+ if (!info[1].IsString()) {
792
+ Napi::TypeError::New(env, "params must be a JSON string.")
793
+ .ThrowAsJavaScriptException();
794
+ return env.Null();
795
+ }
796
+ const string json = info[1].As<Napi::String>().Utf8Value();
797
+
798
+ int res = pjw_call_stop_bfsk_detection(call_id, json.c_str());
799
+
800
+ if (res != 0) {
801
+ Napi::Error::New(env, pjw_get_error()).ThrowAsJavaScriptException();
802
+ return env.Null();
803
+ }
804
+
805
+ return env.Null();
806
+ }
807
+
808
+
640
809
 
641
810
  Napi::Value call_stop_record_wav(const Napi::CallbackInfo &info) {
642
811
  Napi::Env env = info.Env();
@@ -1395,25 +1564,26 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
1395
1564
  exports.Set("call_respond", Napi::Function::New(env, call_respond));
1396
1565
  exports.Set("call_terminate", Napi::Function::New(env, call_terminate));
1397
1566
  exports.Set("call_send_dtmf", Napi::Function::New(env, call_send_dtmf));
1567
+ exports.Set("call_send_bfsk", Napi::Function::New(env, call_send_bfsk));
1398
1568
  exports.Set("call_reinvite", Napi::Function::New(env, call_reinvite));
1399
1569
  exports.Set("call_send_request", Napi::Function::New(env, call_send_request));
1400
- exports.Set("call_start_record_wav",
1401
- Napi::Function::New(env, call_start_record_wav));
1402
- exports.Set("call_start_play_wav",
1403
- Napi::Function::New(env, call_start_play_wav));
1404
- exports.Set("call_start_fax", Napi::Function::New(env, call_start_fax));
1405
1570
 
1571
+ exports.Set("call_start_record_wav", Napi::Function::New(env, call_start_record_wav));
1572
+ exports.Set("call_start_play_wav", Napi::Function::New(env, call_start_play_wav));
1573
+ exports.Set("call_start_fax", Napi::Function::New(env, call_start_fax));
1406
1574
  exports.Set("call_start_speech_synth", Napi::Function::New(env, call_start_speech_synth));
1407
-
1408
1575
  exports.Set("call_start_speech_recog", Napi::Function::New(env, call_start_speech_recog));
1576
+ exports.Set("call_start_inband_dtmf_detection", Napi::Function::New(env, call_start_inband_dtmf_detection));
1577
+ exports.Set("call_start_bfsk_detection", Napi::Function::New(env, call_start_bfsk_detection));
1409
1578
 
1410
- exports.Set("call_stop_record_wav",
1411
- Napi::Function::New(env, call_stop_record_wav));
1412
- exports.Set("call_stop_play_wav",
1413
- Napi::Function::New(env, call_stop_play_wav));
1579
+ exports.Set("call_stop_record_wav", Napi::Function::New(env, call_stop_record_wav));
1580
+ exports.Set("call_stop_play_wav", Napi::Function::New(env, call_stop_play_wav));
1414
1581
  exports.Set("call_stop_fax", Napi::Function::New(env, call_stop_fax));
1415
1582
  exports.Set("call_stop_speech_synth", Napi::Function::New(env, call_stop_speech_synth));
1416
1583
  exports.Set("call_stop_speech_recog", Napi::Function::New(env, call_stop_speech_recog));
1584
+ exports.Set("call_stop_inband_dtmf_detection", Napi::Function::New(env, call_stop_inband_dtmf_detection));
1585
+ exports.Set("call_stop_bfsk_detection", Napi::Function::New(env, call_stop_bfsk_detection));
1586
+
1417
1587
  exports.Set("call_get_stream_stat",
1418
1588
  Napi::Function::New(env, call_get_stream_stat));
1419
1589
  // exports.Set("call_refer", Napi::Function::New(env, call_refer));
@@ -47,6 +47,14 @@ int make_evt_dtmf(char *dest, int size, long call_id, int digits_len,
47
47
  call_id, digits_len, digits, mode, media_id);
48
48
  }
49
49
 
50
+ int make_evt_bfsk(char *dest, int size, long call_id, int bits_len,
51
+ const char *bits, int media_id) {
52
+ return snprintf(dest, size,
53
+ "{\"event\": \"bfsk\", \"call_id\": %ld, \"bits\": "
54
+ "\"%.*s\", \"media_id\": %i}",
55
+ call_id, bits_len, bits, media_id);
56
+ }
57
+
50
58
  int make_evt_call_ended(char *dest, int size, long call_id, int sip_msg_len,
51
59
  const char *sip_msg) {
52
60
  printf("make_evt_call_ended sip_msg_len=%i sip_msg=%p\n", sip_msg_len,
@@ -17,6 +17,9 @@ int make_evt_media_update(char *dest, int size, long call_id,
17
17
  int make_evt_dtmf(char *dest, int size, long call_id, int digits_len,
18
18
  const char *digits, int mode, int media_id);
19
19
 
20
+ int make_evt_bfsk(char *dest, int size, long call_id, int bits_len,
21
+ const char *bits, int media_id);
22
+
20
23
  int make_evt_call_ended(char *dest, int size, long call_id, int sip_msg_len,
21
24
  const char *sip_msg);
22
25
 
@@ -0,0 +1,23 @@
1
+ #ifndef __PJMEDIA_BFSK_DET_H__
2
+ #define __PJMEDIA_BFSK_DET_H__
3
+
4
+ #include <pjmedia/port.h>
5
+
6
+ PJ_BEGIN_DECL
7
+
8
+ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
9
+ unsigned clock_rate,
10
+ unsigned channel_count,
11
+ unsigned samples_per_frame,
12
+ unsigned bits_per_sample,
13
+ void (*cb)(pjmedia_port*,
14
+ void *user_data,
15
+ int bit),
16
+ void *user_data,
17
+ int freq_zero,
18
+ int freq_one,
19
+ pjmedia_port **p_port);
20
+
21
+ PJ_END_DECL
22
+
23
+ #endif /* __PJMEDIA_BFSK_DET_H__ */
@@ -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,
@@ -0,0 +1,289 @@
1
+ /* $Id: bfsk_det.c 0000 2024-09-08 08:11:53Z mayamatakeshi $ */
2
+ /*
3
+ * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+ #include <pjmedia/bfsk_det.h>
22
+ #include <pjmedia/errno.h>
23
+ #include <pjmedia/port.h>
24
+ #include <pj/assert.h>
25
+ #include <pj/pool.h>
26
+ #include <pj/string.h>
27
+
28
+ #include <math.h>
29
+
30
+ #define SIGNATURE PJMEDIA_SIGNATURE('b', 'f', 'd', 't')
31
+ #define THIS_FILE "bfsk_det.c"
32
+
33
+ #if 0
34
+ # define TRACE_(expr) PJ_LOG(4,expr)
35
+ #else
36
+ # define TRACE_(expr)
37
+ #endif
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
+
123
+ static pj_status_t bfsk_det_put_frame(pjmedia_port *this_port,
124
+ pjmedia_frame *frame);
125
+ static pj_status_t bfsk_det_on_destroy(pjmedia_port *this_port);
126
+
127
+ struct bfsk_det
128
+ {
129
+ struct pjmedia_port base;
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
+
140
+ void (*bfsk_cb)(pjmedia_port*, void*, int);
141
+ void *bfsk_cb_user_data;
142
+ };
143
+
144
+ /*
145
+ static void bfsk_det_bit_callback(void *user_data, int bit)
146
+ {
147
+ printf("bfsk_det_bit_callback got bit=%i\n", bit);
148
+ if(bit != 0 && bit != 1) return;
149
+
150
+ struct bfsk_det *dport = (struct bfsk_det*)user_data;
151
+
152
+ TRACE_((THIS_FILE, "bfsk_det bit detected: %c", bit));
153
+
154
+ if(!dport->bfsk_cb) return;
155
+
156
+ dport->bfsk_cb((pjmedia_port*)dport,
157
+ dport->bfsk_cb_user_data,
158
+ bit);
159
+ }
160
+ */
161
+
162
+ PJ_DEF(pj_status_t) pjmedia_bfsk_det_create( pj_pool_t *pool,
163
+ unsigned clock_rate,
164
+ unsigned channel_count,
165
+ unsigned samples_per_frame,
166
+ unsigned bits_per_sample,
167
+ void (*cb)(pjmedia_port*,
168
+ void *user_data,
169
+ int bit),
170
+ void *user_data,
171
+ int freq_zero,
172
+ int freq_one,
173
+ pjmedia_port **p_port)
174
+ {
175
+ printf("pjmedia_bfsk_det_create\n");
176
+ struct bfsk_det *det;
177
+
178
+ printf("p1\n");
179
+ const pj_str_t name = pj_str("bfsk_det");
180
+
181
+ PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
182
+ samples_per_frame && bits_per_sample == 16 &&
183
+ p_port != NULL, PJ_EINVAL);
184
+
185
+ PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
186
+
187
+ printf("p2\n");
188
+
189
+ det = PJ_POOL_ZALLOC_T(pool, struct bfsk_det);
190
+ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
191
+ printf("p3\n");
192
+
193
+ pjmedia_port_info_init(&det->base.info, &name, SIGNATURE, clock_rate,
194
+ channel_count, bits_per_sample, samples_per_frame);
195
+
196
+ det->base.put_frame = &bfsk_det_put_frame;
197
+ det->base.on_destroy = &bfsk_det_on_destroy;
198
+
199
+ printf("p5\n");
200
+
201
+ det->bfsk_cb = cb;
202
+ det->bfsk_cb_user_data = user_data;
203
+
204
+ printf("p6\n");
205
+
206
+ det->clock_rate = clock_rate;
207
+ det->freq_zero = freq_zero;
208
+ det->freq_one = freq_one;
209
+
210
+ float threshold = 0.1;
211
+
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);
217
+
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");
224
+
225
+ TRACE_((THIS_FILE, "bfsk_det created: clock_rate=%u channel_count=%u samples_per_frame=%u bits_per_frame=%u", clock_rate,
226
+ channel_count, samples_per_frame, bits_per_sample));
227
+
228
+ printf("fsk_rx_init done\n");
229
+
230
+ *p_port = &det->base;
231
+ return PJ_SUCCESS;
232
+ }
233
+
234
+ static pj_status_t bfsk_det_put_frame(pjmedia_port *this_port,
235
+ pjmedia_frame *frame)
236
+ {
237
+ printf("bfsk_det_put_frame\n");
238
+ if(frame->type != PJMEDIA_FRAME_TYPE_AUDIO) return PJ_SUCCESS;
239
+
240
+ struct bfsk_det *dport = (struct bfsk_det*) this_port;
241
+
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
+ }
282
+
283
+ return PJ_SUCCESS;
284
+ }
285
+
286
+ static pj_status_t bfsk_det_on_destroy(pjmedia_port *this_port)
287
+ {
288
+ return PJ_SUCCESS;
289
+ }
@@ -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);