@babblevoice/projectrtp 2.4.17 → 2.5.20
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/README.md +3 -70
- package/package.json +6 -4
- package/src/globals.h +2 -0
- package/src/projectrtpbuffer.cpp +30 -6
- package/src/projectrtpbuffer.h +14 -3
- package/src/projectrtpchannel.cpp +110 -56
- package/src/projectrtpchannel.h +6 -0
- package/src/projectrtpchannelmux.cpp +8 -10
- package/src/projectrtpcodecx.cpp +10 -7
- package/src/projectrtpcodecx.h +17 -2
- package/src/projectrtppacket.cpp +16 -41
- package/src/projectrtppacket.h +0 -2
- package/src/projectrtprawsound.cpp +23 -6
- package/src/projectrtprawsound.h +3 -2
- package/src/projectrtpsoundfile.cpp +4 -1
- package/src/projectrtptonegen.cpp +26 -43
- package/test/interface/projectrtpchannel.js +10 -10
- package/test/interface/projectrtpdtmf.js +86 -2
- package/test/interface/projectrtpmix.js +1 -2
- package/test/interface/transcode.js +657 -0
package/src/projectrtpcodecx.cpp
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
#include <iostream>
|
|
3
|
+
#include <cstdlib>
|
|
4
|
+
#include <iomanip>
|
|
3
5
|
#include <math.h>
|
|
4
6
|
|
|
5
7
|
#include "projectrtpcodecx.h"
|
|
@@ -320,10 +322,10 @@ bool codecx::ilbctol16( void ) {
|
|
|
320
322
|
|
|
321
323
|
if( -1 == l168klength ) {
|
|
322
324
|
this->l168kref.size( 0 );
|
|
323
|
-
this->l168kref.dirty( false );
|
|
324
325
|
return false;
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
this->l168kref.dirty( false );
|
|
327
329
|
this->l168kref.size( l168klength );
|
|
328
330
|
return true;
|
|
329
331
|
}
|
|
@@ -518,9 +520,10 @@ rawsound& codecx::requirel16( void )
|
|
|
518
520
|
return this->l168kref;
|
|
519
521
|
}
|
|
520
522
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
523
|
+
/**
|
|
524
|
+
* Obtain a reference to a rawsound for the codec type pt. i.e. we alrteady have
|
|
525
|
+
* the input sound and based on the format we want to convert it to that
|
|
526
|
+
* format.
|
|
524
527
|
*/
|
|
525
528
|
rawsound& codecx::getref( int pt ) {
|
|
526
529
|
/* If we have already have or converted this packet... */
|
|
@@ -558,7 +561,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
558
561
|
return this->g722ref;
|
|
559
562
|
}
|
|
560
563
|
case PCMAPAYLOADTYPE: {
|
|
561
|
-
if( this->pcmuref.size() > 0 ) {
|
|
564
|
+
if( !this->pcmuref.isdirty() && this->pcmuref.size() > 0 ) {
|
|
562
565
|
this->ulaw2alaw();
|
|
563
566
|
} else {
|
|
564
567
|
this->requirenarrowband();
|
|
@@ -567,7 +570,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
567
570
|
return this->pcmaref;
|
|
568
571
|
}
|
|
569
572
|
case PCMUPAYLOADTYPE: {
|
|
570
|
-
if( this->pcmaref.size() > 0 ) {
|
|
573
|
+
if( !this->pcmaref.isdirty() && this->pcmaref.size() > 0 ) {
|
|
571
574
|
this->alaw2ulaw();
|
|
572
575
|
} else {
|
|
573
576
|
this->requirenarrowband();
|
|
@@ -586,7 +589,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
586
589
|
}
|
|
587
590
|
|
|
588
591
|
/* We should ever get here unless an invalid param has been passed in */
|
|
589
|
-
std::cerr << "codecx::getref call with bad pt" << std::endl;
|
|
592
|
+
std::cerr << "codecx::getref call with bad pt: " << pt << std::endl;
|
|
590
593
|
return this->pcmuref;
|
|
591
594
|
}
|
|
592
595
|
|
package/src/projectrtpcodecx.h
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
#ifndef PROJECTRTPCODECX_H
|
|
4
4
|
#define PROJECTRTPCODECX_H
|
|
5
5
|
|
|
6
|
+
#include <iostream>
|
|
7
|
+
#include <cstdlib>
|
|
6
8
|
|
|
7
9
|
#include <ilbc.h>
|
|
8
10
|
#include <spandsp.h>
|
|
@@ -127,6 +129,8 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
127
129
|
|
|
128
130
|
switch( outpayloadtype ) {
|
|
129
131
|
case ILBCPAYLOADTYPE: {
|
|
132
|
+
pk->setpayloadlength( ILBC20PAYLOADBYTES );
|
|
133
|
+
|
|
130
134
|
if( !c.ilbcref.isdirty() ) {
|
|
131
135
|
pk->copy( c.ilbcref.c_str(), c.ilbcref.size() * c.ilbcref.getbytespersample() );
|
|
132
136
|
return pk;
|
|
@@ -135,6 +139,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
135
139
|
break;
|
|
136
140
|
}
|
|
137
141
|
case G722PAYLOADTYPE: {
|
|
142
|
+
pk->setpayloadlength( G722PAYLOADBYTES );
|
|
138
143
|
if( !c.g722ref.isdirty() ) {
|
|
139
144
|
pk->copy( c.g722ref.c_str(), c.g722ref.size() * c.g722ref.getbytespersample() );
|
|
140
145
|
return pk;
|
|
@@ -143,6 +148,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
143
148
|
break;
|
|
144
149
|
}
|
|
145
150
|
case PCMAPAYLOADTYPE: {
|
|
151
|
+
pk->setpayloadlength( G711PAYLOADBYTES );
|
|
146
152
|
if( !c.pcmaref.isdirty() ) {
|
|
147
153
|
pk->copy( c.pcmaref.c_str(), c.pcmaref.size() * c.pcmaref.getbytespersample() );
|
|
148
154
|
return pk;
|
|
@@ -151,6 +157,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
151
157
|
break;
|
|
152
158
|
}
|
|
153
159
|
case PCMUPAYLOADTYPE: {
|
|
160
|
+
pk->setpayloadlength( G711PAYLOADBYTES );
|
|
154
161
|
if( !c.pcmuref.isdirty() ) {
|
|
155
162
|
pk->copy( c.pcmuref.c_str(), c.pcmuref.size() * c.pcmuref.getbytespersample() );
|
|
156
163
|
return pk;
|
|
@@ -159,6 +166,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
159
166
|
break;
|
|
160
167
|
}
|
|
161
168
|
case L168KPAYLOADTYPE: {
|
|
169
|
+
pk->setpayloadlength( L16NARROWBANDBYTES );
|
|
162
170
|
if( !c.l168kref.isdirty() ) {
|
|
163
171
|
pk->copy( c.l168kref.c_str(), c.l168kref.size() * c.l168kref.getbytespersample() );
|
|
164
172
|
return pk;
|
|
@@ -168,6 +176,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
case L1616KPAYLOADTYPE: {
|
|
179
|
+
pk->setpayloadlength( L16WIDEBANDBYTES );
|
|
171
180
|
if( !c.l1616kref.isdirty() ) {
|
|
172
181
|
pk->copy( c.l1616kref.c_str(), c.l1616kref.size() * c.l1616kref.getbytespersample() );
|
|
173
182
|
return pk;
|
|
@@ -175,10 +184,16 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
175
184
|
c.l1616kref = rawsound( *pk, true );
|
|
176
185
|
break;
|
|
177
186
|
}
|
|
187
|
+
default: {
|
|
188
|
+
/* this should not happen */
|
|
189
|
+
std::cerr << "Unknown CODEC when encoding: " << outpayloadtype << std::endl;
|
|
190
|
+
return pk;
|
|
191
|
+
}
|
|
178
192
|
}
|
|
179
193
|
|
|
180
|
-
|
|
181
|
-
|
|
194
|
+
/* encode */
|
|
195
|
+
c.getref( outpayloadtype );
|
|
196
|
+
|
|
182
197
|
return pk;
|
|
183
198
|
}
|
|
184
199
|
|
package/src/projectrtppacket.cpp
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
#ifdef TESTSUITE
|
|
3
2
|
#include <iostream>
|
|
3
|
+
#include <cstdlib>
|
|
4
4
|
#include <iomanip>
|
|
5
|
-
#endif
|
|
6
5
|
|
|
7
6
|
#include "projectrtppacket.h"
|
|
8
7
|
#include "globals.h"
|
|
@@ -43,7 +42,7 @@ void rtppacket::copy( rtppacket *src )
|
|
|
43
42
|
src->pk + 12 + ( src->getpacketcsrccount() * 4 ),
|
|
44
43
|
src->getpayloadlength() );
|
|
45
44
|
|
|
46
|
-
this->length = src->
|
|
45
|
+
this->length = src->length;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
/*!md
|
|
@@ -139,28 +138,11 @@ uint8_t rtppacket::getpayloadtype( void )
|
|
|
139
138
|
/*!md
|
|
140
139
|
## setpayloadtype
|
|
141
140
|
As it says. We also set the length of the packet to a default amount for that CODEC.
|
|
141
|
+
If setting a dynamic payloadtype - don't mess with the length as we won't know it
|
|
142
|
+
and it must already be set.
|
|
142
143
|
*/
|
|
143
|
-
void rtppacket::setpayloadtype( uint8_t pt )
|
|
144
|
-
{
|
|
144
|
+
void rtppacket::setpayloadtype( uint8_t pt ) {
|
|
145
145
|
this->pk[ 1 ] = ( this->pk[ 1 ] & 0x80 ) | ( pt & 0x7f );
|
|
146
|
-
|
|
147
|
-
switch( pt )
|
|
148
|
-
{
|
|
149
|
-
case ILBC20PAYLOADBYTES:
|
|
150
|
-
{
|
|
151
|
-
this->length = 12 + ILBC20PAYLOADBYTES;
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
case ILBC30PAYLOADBYTES:
|
|
155
|
-
{
|
|
156
|
-
this->length = 12 + ILBC30PAYLOADBYTES;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
default:
|
|
160
|
-
{
|
|
161
|
-
this->length = 12 + G711PAYLOADBYTES;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
146
|
}
|
|
165
147
|
|
|
166
148
|
/*!md
|
|
@@ -243,8 +225,7 @@ uint32_t rtppacket::getcsrc( uint8_t index )
|
|
|
243
225
|
## getpayload
|
|
244
226
|
Returns a pointer to the start of the payload.
|
|
245
227
|
*/
|
|
246
|
-
uint8_t *rtppacket::getpayload( void )
|
|
247
|
-
{
|
|
228
|
+
uint8_t *rtppacket::getpayload( void ) {
|
|
248
229
|
uint8_t *ptr = this->pk;
|
|
249
230
|
ptr += 12;
|
|
250
231
|
ptr += ( this->getpacketcsrccount() * 4 );
|
|
@@ -256,11 +237,9 @@ uint8_t *rtppacket::getpayload( void )
|
|
|
256
237
|
## getpayloadlength
|
|
257
238
|
As it says.
|
|
258
239
|
*/
|
|
259
|
-
uint16_t rtppacket::getpayloadlength( void )
|
|
260
|
-
{
|
|
240
|
+
uint16_t rtppacket::getpayloadlength( void ) {
|
|
261
241
|
|
|
262
|
-
if( this->length < ( 12 - ( (size_t)this->getpacketcsrccount() * 4 ) ) )
|
|
263
|
-
{
|
|
242
|
+
if( this->length < ( 12 - ( (size_t) this->getpacketcsrccount() * 4 ) ) ) {
|
|
264
243
|
fprintf( stderr, "RTP Packet has a nonsense size\n" );
|
|
265
244
|
return 0;
|
|
266
245
|
}
|
|
@@ -271,30 +250,26 @@ uint16_t rtppacket::getpayloadlength( void )
|
|
|
271
250
|
## setpayloadlength
|
|
272
251
|
As it says.
|
|
273
252
|
*/
|
|
274
|
-
void rtppacket::setpayloadlength( size_t length )
|
|
275
|
-
{
|
|
253
|
+
void rtppacket::setpayloadlength( size_t length ) {
|
|
276
254
|
this->length = 12 + ( this->getpacketcsrccount() * 4 ) + length;
|
|
277
255
|
}
|
|
278
256
|
|
|
279
|
-
|
|
280
|
-
/* show the contents to cout */
|
|
257
|
+
/* dump the contents to cout */
|
|
281
258
|
void rtppacket::dump() {
|
|
282
259
|
std::cout << "=================BEGIN=================" << std::endl;
|
|
283
|
-
std::cout << "length: " << this->length << std::endl;
|
|
284
|
-
std::cout << "payload length: " << this->getpayloadlength() << std::endl;
|
|
260
|
+
std::cout << "length: " << std::dec << this->length << std::endl;
|
|
261
|
+
std::cout << "payload length: " << std::dec << this->getpayloadlength() << std::endl;
|
|
285
262
|
std::cout << "marker: " << +this->getpacketmarker() << std::endl;
|
|
286
263
|
std::cout << "pt: " << +this->getpayloadtype() << std::endl;
|
|
287
|
-
std::cout << "sn: " << this->getsequencenumber() << std::endl;
|
|
288
|
-
std::cout << "ts: " << this->gettimestamp() << std::endl;
|
|
289
|
-
std::cout << "ssrc: " << this->getssrc() << std::endl;
|
|
264
|
+
std::cout << "sn: " << std::dec << this->getsequencenumber() << std::endl;
|
|
265
|
+
std::cout << "ts: " << std::dec << this->gettimestamp() << std::endl;
|
|
266
|
+
std::cout << "ssrc: " << std::dec << this->getssrc() << std::endl;
|
|
290
267
|
|
|
291
268
|
auto v = this->getpayload();
|
|
292
269
|
for( auto i = 0; i < this->getpayloadlength(); i ++ ) {
|
|
293
270
|
std::cout << std::showbase << std::setfill( '0' ) << std::setw( 2 ) << std::hex << std::right << +(*(v+i)) << ' ';
|
|
294
|
-
if( 0 == i % 16 ) std::cout << std::endl;
|
|
271
|
+
if( 0 != i && 0 == i % 16 ) std::cout << std::endl;
|
|
295
272
|
}
|
|
296
273
|
std::cout << std::dec;
|
|
297
|
-
|
|
298
274
|
std::cout << std::endl << "=================END===================" << std::endl;
|
|
299
275
|
}
|
|
300
|
-
#endif
|
package/src/projectrtppacket.h
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
#include <iostream> // cerr
|
|
3
|
+
#include <cstdlib>
|
|
4
|
+
#include <iomanip>
|
|
3
5
|
|
|
4
6
|
#include "projectrtprawsound.h"
|
|
5
7
|
#include "projectrtpcodecx.h"
|
|
@@ -241,15 +243,12 @@ void rawsound::malloc( size_t samplecount, size_t bytespersample, int format )
|
|
|
241
243
|
this->bytespersample = bytespersample;
|
|
242
244
|
this->format = format;
|
|
243
245
|
size_t requiredsize = samplecount * bytespersample;
|
|
244
|
-
if( L1616KPAYLOADTYPE == format )
|
|
245
|
-
{
|
|
246
|
+
if( L1616KPAYLOADTYPE == format ) {
|
|
246
247
|
requiredsize = requiredsize * 2;
|
|
247
248
|
}
|
|
248
249
|
|
|
249
|
-
if( this->allocatedlength > 0 )
|
|
250
|
-
|
|
251
|
-
if( this->allocatedlength >= requiredsize )
|
|
252
|
-
{
|
|
250
|
+
if( this->allocatedlength > 0 ) {
|
|
251
|
+
if( this->allocatedlength >= requiredsize ) {
|
|
253
252
|
return;
|
|
254
253
|
}
|
|
255
254
|
|
|
@@ -354,3 +353,21 @@ rawsound& rawsound::operator-=( codecx& rhs )
|
|
|
354
353
|
|
|
355
354
|
return *this;
|
|
356
355
|
}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
void rawsound::dump() {
|
|
359
|
+
|
|
360
|
+
std::cout << "=================BEGIN=================" << std::endl;
|
|
361
|
+
std::cout << "samples: " << std::dec << this->samples << std::endl;
|
|
362
|
+
std::cout << "bytespersample: " << std::dec << this->bytespersample << std::endl;
|
|
363
|
+
std::cout << "format: " << std::dec << this->format << std::endl;
|
|
364
|
+
|
|
365
|
+
auto v = this->data;
|
|
366
|
+
size_t len = this->samples * this->bytespersample;
|
|
367
|
+
for( size_t i = 0; i < len; i ++ ) {
|
|
368
|
+
std::cout << std::showbase << std::setfill( '0' ) << std::setw( 2 ) << std::hex << std::right << +(*(v+i)) << ' ';
|
|
369
|
+
if( 0 != i && 0 == i % 16 ) std::cout << std::endl;
|
|
370
|
+
}
|
|
371
|
+
std::cout << std::dec;
|
|
372
|
+
std::cout << std::endl << "=================END===================" << std::endl;
|
|
373
|
+
}
|
package/src/projectrtprawsound.h
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
#include "projectrtppacket.h"
|
|
7
7
|
|
|
8
8
|
class codecx;
|
|
9
|
-
class rawsound
|
|
10
|
-
{
|
|
9
|
+
class rawsound {
|
|
11
10
|
public:
|
|
12
11
|
rawsound();
|
|
13
12
|
rawsound( uint8_t *ptr, std::size_t samples, int format, uint16_t samplerate );
|
|
@@ -39,6 +38,8 @@ public:
|
|
|
39
38
|
rawsound& operator+=( codecx& rhs );
|
|
40
39
|
rawsound& operator-=( codecx& rhs );
|
|
41
40
|
|
|
41
|
+
void dump();
|
|
42
|
+
|
|
42
43
|
private:
|
|
43
44
|
void frompt( int payloadtype );
|
|
44
45
|
|
|
@@ -605,7 +605,10 @@ static napi_value wavinfo( napi_env env, napi_callback_info info ) {
|
|
|
605
605
|
return NULL;
|
|
606
606
|
}
|
|
607
607
|
|
|
608
|
-
read( fd, &hd, sizeof( wavheader ) )
|
|
608
|
+
if( sizeof( wavheader ) != read( fd, &hd, sizeof( wavheader ) ) ) {
|
|
609
|
+
napi_throw_type_error( env, "0", "Bad wav header" );
|
|
610
|
+
goto done;
|
|
611
|
+
}
|
|
609
612
|
|
|
610
613
|
if( 'R' != hd.riff_header[ 0 ] ||
|
|
611
614
|
'I' != hd.riff_header[ 1 ] ||
|
|
@@ -51,13 +51,11 @@ static void gentone( int16_t *outbuffer, int sizeofblock, double startfrequency,
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
static void gen( std::string tone, std::string filename )
|
|
55
|
-
{
|
|
54
|
+
static void gen( std::string tone, std::string filename ) {
|
|
56
55
|
vectorofstrings freqscadence;
|
|
57
56
|
boost::split( freqscadence, tone, boost::is_any_of( ":" ) );
|
|
58
57
|
|
|
59
|
-
if( 2 != freqscadence.size() )
|
|
60
|
-
{
|
|
58
|
+
if( 2 != freqscadence.size() ) {
|
|
61
59
|
std::cerr << "You must supply a cadence, eg. 400:1000" << std::endl;
|
|
62
60
|
return;
|
|
63
61
|
}
|
|
@@ -76,8 +74,7 @@ static void gen( std::string tone, std::string filename )
|
|
|
76
74
|
vectorofstrings cadenceparts;
|
|
77
75
|
int cadencepos = 0;
|
|
78
76
|
int cadencetotal = 0;
|
|
79
|
-
for( it = frequencies.begin(); it != frequencies.end(); it++ )
|
|
80
|
-
{
|
|
77
|
+
for( it = frequencies.begin(); it != frequencies.end(); it++ ) {
|
|
81
78
|
cadencetotal += std::atoi( cadences[ cadencepos ].c_str() );
|
|
82
79
|
cadencepos = ( cadencepos + 1 ) % cadences.size();
|
|
83
80
|
}
|
|
@@ -94,8 +91,7 @@ static void gen( std::string tone, std::string filename )
|
|
|
94
91
|
/* 3. Generate tones */
|
|
95
92
|
int pos = 0;
|
|
96
93
|
cadencepos = 0;
|
|
97
|
-
for( it = frequencies.begin(); it != frequencies.end(); it++ )
|
|
98
|
-
{
|
|
94
|
+
for( it = frequencies.begin(); it != frequencies.end(); it++ ) {
|
|
99
95
|
/* Current cadence. */
|
|
100
96
|
int cadence = std::atoi( cadences[ cadencepos ].c_str() );
|
|
101
97
|
cadencepos = ( cadencepos + 1 ) % cadences.size();
|
|
@@ -109,14 +105,12 @@ static void gen( std::string tone, std::string filename )
|
|
|
109
105
|
boost::split( freqamp, *it, boost::is_any_of( "*" ) );
|
|
110
106
|
double startamp = 1;
|
|
111
107
|
double endamp = 1;
|
|
112
|
-
if( freqamp.size() > 1 )
|
|
113
|
-
{
|
|
108
|
+
if( freqamp.size() > 1 ) {
|
|
114
109
|
vectorofstrings ampfromto;
|
|
115
110
|
boost::split( ampfromto, freqamp[ 1 ], boost::is_any_of( "~" ) );
|
|
116
111
|
startamp = std::atof( ampfromto[ 0 ].c_str() );
|
|
117
112
|
endamp = startamp;
|
|
118
|
-
if( ampfromto.size() > 1 )
|
|
119
|
-
{
|
|
113
|
+
if( ampfromto.size() > 1 ) {
|
|
120
114
|
endamp = std::atof( ampfromto[ 1 ].c_str() );
|
|
121
115
|
}
|
|
122
116
|
}
|
|
@@ -127,27 +121,20 @@ static void gen( std::string tone, std::string filename )
|
|
|
127
121
|
double endfreq = -1;
|
|
128
122
|
|
|
129
123
|
std::size_t found = freqamp[ 0 ].find_first_of( "+x~" );
|
|
130
|
-
if( std::string::npos == found )
|
|
131
|
-
{
|
|
124
|
+
if( std::string::npos == found ) {
|
|
132
125
|
startfreq = std::atof( freqparts[ 0 ].c_str() );
|
|
133
126
|
gentone( outbuffer, sizeofblock, startfreq, startfreq, startamp, endamp, outwavheader.sample_rate );
|
|
134
127
|
goto continueloop;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
case '+':
|
|
141
|
-
{
|
|
142
|
-
for( auto freqit = freqparts.begin(); freqit != freqparts.end(); freqit++ )
|
|
143
|
-
{
|
|
128
|
+
} else {
|
|
129
|
+
switch( freqamp[ 0 ][ found ] ) {
|
|
130
|
+
case '+': {
|
|
131
|
+
for( auto freqit = freqparts.begin(); freqit != freqparts.end(); freqit++ ) {
|
|
144
132
|
startfreq = std::atof( freqit->c_str() );
|
|
145
133
|
gentone( outbuffer, sizeofblock, startfreq, startfreq, startamp, endamp, outwavheader.sample_rate );
|
|
146
134
|
}
|
|
147
135
|
break;
|
|
148
136
|
}
|
|
149
|
-
case '~':
|
|
150
|
-
{
|
|
137
|
+
case '~': {
|
|
151
138
|
startfreq = std::atof( freqparts[ 0 ].c_str() );
|
|
152
139
|
endfreq = std::atof( freqparts[ 1 ].c_str() );
|
|
153
140
|
gentone( outbuffer, sizeofblock, startfreq, endfreq, startamp, endamp, outwavheader.sample_rate );
|
|
@@ -164,39 +151,35 @@ continueloop:
|
|
|
164
151
|
/* Write */
|
|
165
152
|
int file = open( filename.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
|
|
166
153
|
off_t position = lseek( file, 0, SEEK_END );
|
|
167
|
-
if( 0 == position )
|
|
168
|
-
|
|
169
|
-
write( file,
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
else
|
|
173
|
-
{
|
|
154
|
+
if( 0 == position ) {
|
|
155
|
+
if( -1 == write( file, &outwavheader, sizeof( wavheader ) ) ) std::cerr << "Error writing to tone file" << std::endl;
|
|
156
|
+
if( -1 == write( file, readbuffer, outwavheader.chunksize ) ) std::cerr << "Error writing to tone file" << std::endl;
|
|
157
|
+
} else {
|
|
174
158
|
wavheader currentheader;
|
|
175
159
|
lseek( file, 0, SEEK_SET );
|
|
176
|
-
read( file, ¤theader, sizeof( wavheader ) )
|
|
160
|
+
if( sizeof( wavheader ) != read( file, ¤theader, sizeof( wavheader ) ) ) {
|
|
161
|
+
std::cerr << "Error reading existing tone file" << std::endl;
|
|
162
|
+
goto cleanuupgen;
|
|
163
|
+
}
|
|
177
164
|
lseek( file, 0, SEEK_END );
|
|
178
165
|
|
|
179
166
|
if( currentheader.audio_format == outwavheader.audio_format &&
|
|
180
|
-
currentheader.sample_rate == outwavheader.sample_rate )
|
|
181
|
-
{
|
|
167
|
+
currentheader.sample_rate == outwavheader.sample_rate ) {
|
|
182
168
|
/* Ok, good enough! */
|
|
183
169
|
currentheader.chunksize += outwavheader.chunksize;
|
|
184
170
|
currentheader.subchunksize += outwavheader.subchunksize;
|
|
185
171
|
|
|
186
172
|
lseek( file, 0, SEEK_SET );
|
|
187
|
-
write( file, ¤theader, sizeof( wavheader ) );
|
|
173
|
+
if( -1 == write( file, ¤theader, sizeof( wavheader ) ) ) std::cerr << "Error writing to tone file" << std::endl;
|
|
188
174
|
lseek( file, 0, SEEK_END );
|
|
189
|
-
write( file, readbuffer, outwavheader.chunksize );
|
|
190
|
-
}
|
|
191
|
-
else
|
|
192
|
-
{
|
|
175
|
+
if( -1 == write( file, readbuffer, outwavheader.chunksize ) ) std::cerr << "Error writing to tone file" << std::endl;
|
|
176
|
+
} else {
|
|
193
177
|
std::cerr << "File format to append should be the same" << std::endl;
|
|
194
178
|
}
|
|
195
179
|
}
|
|
196
180
|
|
|
197
|
-
|
|
198
|
-
if( nullptr != readbuffer )
|
|
199
|
-
{
|
|
181
|
+
cleanuupgen:
|
|
182
|
+
if( nullptr != readbuffer ) {
|
|
200
183
|
delete[] readbuffer;
|
|
201
184
|
}
|
|
202
185
|
|
|
@@ -381,8 +381,7 @@ describe( "rtpchannel", function() {
|
|
|
381
381
|
lastts = ts
|
|
382
382
|
|
|
383
383
|
receviedpkcount++
|
|
384
|
-
|
|
385
|
-
if( 185 == receviedpkcount ) channel.close()
|
|
384
|
+
|
|
386
385
|
} )
|
|
387
386
|
|
|
388
387
|
this.timeout( 15000 )
|
|
@@ -390,8 +389,7 @@ describe( "rtpchannel", function() {
|
|
|
390
389
|
|
|
391
390
|
server.bind()
|
|
392
391
|
|
|
393
|
-
|
|
394
|
-
const finished = new Promise( ( r ) => done = r )
|
|
392
|
+
|
|
395
393
|
let closedstats = {}
|
|
396
394
|
server.on( "listening", async function() {
|
|
397
395
|
|
|
@@ -402,7 +400,6 @@ describe( "rtpchannel", function() {
|
|
|
402
400
|
if( "close" === d.action ) {
|
|
403
401
|
closedstats = d
|
|
404
402
|
server.close()
|
|
405
|
-
done()
|
|
406
403
|
}
|
|
407
404
|
} )
|
|
408
405
|
|
|
@@ -410,7 +407,7 @@ describe( "rtpchannel", function() {
|
|
|
410
407
|
|
|
411
408
|
/* send a packet every 20mS x 50 */
|
|
412
409
|
let i
|
|
413
|
-
for( i = 0;
|
|
410
|
+
for( i = 0; 120 > i; i++ ) {
|
|
414
411
|
sendpk( i, i, channel.local.port, server )
|
|
415
412
|
}
|
|
416
413
|
|
|
@@ -425,7 +422,10 @@ describe( "rtpchannel", function() {
|
|
|
425
422
|
}
|
|
426
423
|
} )
|
|
427
424
|
|
|
428
|
-
await
|
|
425
|
+
await new Promise( resolve => setTimeout( resolve, 6500 ) )
|
|
426
|
+
// @ts-ignore
|
|
427
|
+
channel.close()
|
|
428
|
+
await new Promise( resolve => setTimeout( resolve, 50 ) )
|
|
429
429
|
|
|
430
430
|
/*
|
|
431
431
|
We should receive
|
|
@@ -435,10 +435,10 @@ describe( "rtpchannel", function() {
|
|
|
435
435
|
*/
|
|
436
436
|
expect( receviedpkcount ).to.equal( closedstats.stats.out.count )
|
|
437
437
|
expect( closedstats.stats.in.count ).to.equal( 300 )
|
|
438
|
-
expect( closedstats.stats.out.count ).to.be.
|
|
438
|
+
expect( closedstats.stats.out.count ).to.be.above( 250 )
|
|
439
439
|
expect( totalsndiff ).to.equal( 0 ) // received should be reordered
|
|
440
|
-
expect( totaltsdiff ).to.be.within(
|
|
441
|
-
expect( lastsn - firstsn ).to.be.within(
|
|
440
|
+
expect( totaltsdiff ).to.be.within( 5000, 18400 ) // Allow some loss in test
|
|
441
|
+
expect( lastsn - firstsn ).to.be.within( 250, 300 )
|
|
442
442
|
} )
|
|
443
443
|
|
|
444
444
|
it( "create channel echo whilst wrapping the sn", function( done ) {
|
|
@@ -23,6 +23,21 @@ function sendpayload( sendtime, pk, dstport, server ) {
|
|
|
23
23
|
}, sendtime )
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Limitation of not parsing ccrc.
|
|
28
|
+
* @param { Buffer } packet
|
|
29
|
+
* @return { object }
|
|
30
|
+
*/
|
|
31
|
+
function parsepk( packet ) {
|
|
32
|
+
return {
|
|
33
|
+
sn: packet.readUInt16BE( 2 ),
|
|
34
|
+
ts: packet.readUInt32BE( 4 ),
|
|
35
|
+
pt: packet.readUInt8( 1 ) & 0x7f,
|
|
36
|
+
ssrc: packet.readUInt32BE( 8 ),
|
|
37
|
+
payload: new Uint8Array( packet.slice( 12 ) )
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
/* helper functions */
|
|
27
42
|
function sendpk( sn, ts, sendtime, dstport, server, pt = 0, ssrc ) {
|
|
28
43
|
|
|
@@ -253,6 +268,74 @@ describe( "dtmf", function() {
|
|
|
253
268
|
expect( dtmfpkcount ).to.equal( 3*3 )
|
|
254
269
|
} )
|
|
255
270
|
|
|
271
|
+
it( "2 channels mixing and request rtp server to send 2833 to one with dynamic payloadtype", async function() {
|
|
272
|
+
|
|
273
|
+
/* create our RTP/UDP endpoint */
|
|
274
|
+
const clienta = dgram.createSocket( "udp4" )
|
|
275
|
+
const clientb = dgram.createSocket( "udp4" )
|
|
276
|
+
|
|
277
|
+
const rfc2833pt = 44
|
|
278
|
+
|
|
279
|
+
let dtmfpkcount = 0
|
|
280
|
+
clienta.on( "message", function( msg ) {
|
|
281
|
+
if( rfc2833pt == ( 0x7f & msg [ 1 ] ) ) {
|
|
282
|
+
dtmfpkcount++
|
|
283
|
+
} else {
|
|
284
|
+
expect( msg.length ).to.equal( 172 )
|
|
285
|
+
expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
|
|
286
|
+
}
|
|
287
|
+
} )
|
|
288
|
+
|
|
289
|
+
clientb.on( "message", function( msg ) {
|
|
290
|
+
if( 101 == ( 0x7f & msg [ 1 ] ) ) {
|
|
291
|
+
expect( true ).to.equal( false ) //here = bad
|
|
292
|
+
dtmfpkcount++
|
|
293
|
+
}
|
|
294
|
+
clientb.send( msg, channelb.local.port, "localhost" )
|
|
295
|
+
} )
|
|
296
|
+
|
|
297
|
+
this.timeout( 3000 )
|
|
298
|
+
this.slow( 2500 )
|
|
299
|
+
|
|
300
|
+
clienta.bind()
|
|
301
|
+
await new Promise( ( resolve ) => { clienta.on( "listening", () => resolve() ) } )
|
|
302
|
+
clientb.bind()
|
|
303
|
+
await new Promise( ( resolve ) => { clientb.on( "listening", () => resolve() ) } )
|
|
304
|
+
|
|
305
|
+
const ouraport = clienta.address().port
|
|
306
|
+
const ourbport = clientb.address().port
|
|
307
|
+
|
|
308
|
+
let done
|
|
309
|
+
const finished = new Promise( ( r ) => { done = r } )
|
|
310
|
+
|
|
311
|
+
const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ouraport, "codec": 0, rfc2833pt } }, function( d ) {
|
|
312
|
+
if( "close" === d.action ) channelb.close()
|
|
313
|
+
} )
|
|
314
|
+
|
|
315
|
+
const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ourbport, "codec": 0 } }, function( d ) {
|
|
316
|
+
if( "close" === d.action ) done()
|
|
317
|
+
} )
|
|
318
|
+
|
|
319
|
+
expect( channela.mix( channelb ) ).to.be.true
|
|
320
|
+
|
|
321
|
+
/* send a packet every 20mS x 70 */
|
|
322
|
+
for( let i = 0; 50 > i; i ++ ) {
|
|
323
|
+
sendpk( i, i*160, i*20, channela.local.port, clienta )
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 400 ) } )
|
|
327
|
+
channela.dtmf( "*9F" )
|
|
328
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 800 ) } )
|
|
329
|
+
channela.close()
|
|
330
|
+
|
|
331
|
+
await finished
|
|
332
|
+
|
|
333
|
+
clienta.close()
|
|
334
|
+
clientb.close()
|
|
335
|
+
|
|
336
|
+
expect( dtmfpkcount ).to.equal( 3*3 )
|
|
337
|
+
} )
|
|
338
|
+
|
|
256
339
|
it( "3 channels mixing and request rtp server to send 2833 to one", async function() {
|
|
257
340
|
|
|
258
341
|
/* create our RTP/UDP endpoint */
|
|
@@ -262,11 +345,12 @@ describe( "dtmf", function() {
|
|
|
262
345
|
|
|
263
346
|
let dtmfpkcount = 0
|
|
264
347
|
clienta.on( "message", function( msg ) {
|
|
265
|
-
|
|
348
|
+
const pk = parsepk( msg )
|
|
349
|
+
if( 101 == pk.pt ) {
|
|
266
350
|
dtmfpkcount++
|
|
267
351
|
} else {
|
|
268
352
|
expect( msg.length ).to.equal( 172 )
|
|
269
|
-
expect(
|
|
353
|
+
expect( pk.pt ).to.equal( 0 )
|
|
270
354
|
}
|
|
271
355
|
} )
|
|
272
356
|
|
|
@@ -904,8 +904,7 @@ describe( "channel mix", function() {
|
|
|
904
904
|
expect( endpointbpkcountzero ).to.be.within( 65, 75 )
|
|
905
905
|
expect( endpointcpkcountzero ).to.be.within( 65, 75 )
|
|
906
906
|
expect( endpointapkcountnotzero ).to.be.within( 4, 12 )
|
|
907
|
-
expect( endpointbpkcountnotzero ).to.be.within( 4
|
|
908
|
-
, 12 )
|
|
907
|
+
expect( endpointbpkcountnotzero ).to.be.within( 4, 12 )
|
|
909
908
|
expect( endpointcpkcountnotzero ).to.be.below( 2 )
|
|
910
909
|
|
|
911
910
|
await finished
|