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.
- package/DEV.md +55 -0
- package/README.md +8 -2
- package/binding.gyp +1 -0
- package/build_deps.sh +2 -1
- package/index.js +7 -0
- package/package.json +1 -1
- 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/samples/100_calls.js +4 -0
- package/samples/16_audio_streams.js +2 -0
- package/samples/183_session_progress.js +2 -0
- package/samples/delayed_media.js +2 -0
- package/samples/four_audio_streams_two_refused.js +7 -4
- package/samples/mrcp_and_audio.simplified_media.js +2 -0
- package/samples/multiple_audio_streams.js +2 -0
- package/samples/refuse_telephone_event.js +3 -0
- package/samples/reinvite_and_dtmf.js +3 -0
- package/samples/reinvite_audio_audio.js +2 -0
- package/samples/reinvite_with_hold_unhold.js +2 -0
- package/samples/rtp_and_srtp.js +3 -0
- package/samples/rtp_and_srtp.rtp_refused.js +3 -0
- package/samples/send_and_receive_bfsk.js.future +171 -0
- package/samples/srtp.js +3 -0
- package/samples/tcp.js +2 -0
- package/samples/text_to_speech.js +3 -0
- package/samples/two_audio_streams.js +4 -0
- package/samples/two_audio_streams.port_zero.js +4 -0
- package/samples_extra/ws_speech_server.bfsk.js +154 -0
- package/samples_extra/ws_speech_server.dtmf.js +5 -21
- package/samples_extra/ws_speech_server.google.js +8 -10
- package/samples_extra/ws_speech_server.send_bfsk.js +156 -0
- package/samples_extra/ws_speech_server.start_bfsk_detection.js.future +164 -0
- package/src/addon.cpp +180 -10
- package/src/event_templates.cpp +8 -0
- package/src/event_templates.hpp +3 -0
- package/src/pjmedia/include/pjmedia/bfsk_det.h +23 -0
- package/src/pjmedia/include/pjmedia/ws_speech_port.h +1 -0
- package/src/pjmedia/src/pjmedia/bfsk_det.c +289 -0
- package/src/pjmedia/src/pjmedia/ws_speech_port.cpp +8 -0
- package/src/sip.cpp +552 -35
- package/src/sip.cpp.old +9236 -0
- 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
|
-
|
|
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));
|
package/src/event_templates.cpp
CHANGED
|
@@ -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,
|
package/src/event_templates.hpp
CHANGED
|
@@ -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__ */
|
|
@@ -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);
|