@babblevoice/projectrtp 2.4.17 → 2.5.22
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 +5 -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 +23 -15
- package/src/projectrtpchannelmux.h +4 -2
- package/src/projectrtpcodecx.cpp +72 -96
- package/src/projectrtpcodecx.h +18 -5
- package/src/projectrtppacket.cpp +16 -41
- package/src/projectrtppacket.h +0 -2
- package/src/projectrtprawsound.cpp +56 -75
- package/src/projectrtprawsound.h +3 -2
- package/src/projectrtpsoundfile.cpp +4 -1
- package/src/projectrtptonegen.cpp +26 -43
- package/test/interface/pcap.js +2 -2
- package/test/interface/pcaps/440hzinbackgroundg722.pcap +0 -0
- package/test/interface/projectrtpchannel.js +10 -10
- package/test/interface/projectrtpdtmf.js +88 -4
- package/test/interface/projectrtpmix.js +1 -2
- package/test/interface/transcode.js +821 -0
|
@@ -15,7 +15,8 @@ projectchannelmux::projectchannelmux( boost::asio::io_context &iocontext ):
|
|
|
15
15
|
newchannels(),
|
|
16
16
|
newchannelslock( false ),
|
|
17
17
|
added(),
|
|
18
|
-
subtracted()
|
|
18
|
+
subtracted(),
|
|
19
|
+
active( false ) {
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
projectchannelmux::~projectchannelmux() {
|
|
@@ -29,22 +30,24 @@ projectchannelmux::pointer projectchannelmux::create( boost::asio::io_context &i
|
|
|
29
30
|
void projectchannelmux::mixall( void ) {
|
|
30
31
|
/* First decide on a common rate (if we only have 8K channels it is pointless
|
|
31
32
|
upsampling them all and wasting resources) */
|
|
32
|
-
int
|
|
33
|
+
int l16format = L168KPAYLOADTYPE;
|
|
33
34
|
size_t insize = L16PAYLOADSAMPLES;
|
|
34
35
|
|
|
35
36
|
for( auto& chan: this->channels ) {
|
|
36
37
|
switch( chan->codec ) {
|
|
37
38
|
case G722PAYLOADTYPE:
|
|
38
39
|
case L1616KPAYLOADTYPE: {
|
|
39
|
-
|
|
40
|
+
l16format = L1616KPAYLOADTYPE;
|
|
41
|
+
insize = L1616PAYLOADSAMPLES;
|
|
40
42
|
goto endofforloop;
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
endofforloop:
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
this->
|
|
48
|
+
/* allocate the max needed */
|
|
49
|
+
this->added.malloc( insize, sizeof( int16_t ), l16format );
|
|
50
|
+
this->subtracted.malloc( insize, sizeof( int16_t ), l16format );
|
|
48
51
|
this->added.zero();
|
|
49
52
|
|
|
50
53
|
/* We first have to add them all up */
|
|
@@ -186,6 +189,8 @@ Our timer handler.
|
|
|
186
189
|
void projectchannelmux::handletick( const boost::system::error_code& error ) {
|
|
187
190
|
if ( error == boost::asio::error::operation_aborted ) return;
|
|
188
191
|
|
|
192
|
+
if( !this->active ) return;
|
|
193
|
+
|
|
189
194
|
this->checkfornewmixes();
|
|
190
195
|
|
|
191
196
|
/* Check for channels which have request removal */
|
|
@@ -193,19 +198,13 @@ void projectchannelmux::handletick( const boost::system::error_code& error ) {
|
|
|
193
198
|
|
|
194
199
|
if( 0 == this->channels.size() ) {
|
|
195
200
|
/* We're done */
|
|
201
|
+
this->active = false;
|
|
196
202
|
return;
|
|
197
203
|
}
|
|
198
204
|
|
|
199
205
|
for( auto& chan: this->channels ) {
|
|
200
206
|
chan->startticktimer();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
for( auto& chan: this->channels ) {
|
|
204
207
|
chan->checkfornewrecorders();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
for( auto& chan: this->channels ) {
|
|
208
|
-
chan->dtlsnegotiate();
|
|
209
208
|
chan->incrtsout();
|
|
210
209
|
}
|
|
211
210
|
|
|
@@ -219,14 +218,15 @@ void projectchannelmux::handletick( const boost::system::error_code& error ) {
|
|
|
219
218
|
chan->senddtmf();
|
|
220
219
|
chan->writerecordings();
|
|
221
220
|
chan->checkidlerecv();
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
for( auto& chan: this->channels ) {
|
|
225
221
|
chan->endticktimer();
|
|
226
222
|
}
|
|
227
223
|
|
|
228
224
|
/* The last thing we do */
|
|
229
225
|
this->setnexttick();
|
|
226
|
+
|
|
227
|
+
for( auto& chan: this->channels ) {
|
|
228
|
+
chan->endticktimer();
|
|
229
|
+
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
void projectchannelmux::setnexttick( void ) {
|
|
@@ -239,6 +239,10 @@ void projectchannelmux::setnexttick( void ) {
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
void projectchannelmux::go( void ) {
|
|
242
|
+
|
|
243
|
+
if( this->active ) return;
|
|
244
|
+
this->active = true;
|
|
245
|
+
|
|
242
246
|
this->nexttick = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds( 20 );
|
|
243
247
|
|
|
244
248
|
this->tick.expires_after( this->nexttick - std::chrono::high_resolution_clock::now() );
|
|
@@ -293,12 +297,15 @@ void projectchannelmux::checkfornewmixes( void ) {
|
|
|
293
297
|
|
|
294
298
|
void projectchannelmux::addchannel( projectrtpchannelptr chan ) {
|
|
295
299
|
AQUIRESPINLOCK( this->newchannelslock );
|
|
300
|
+
chan->mixing = true;
|
|
296
301
|
this->newchannels.push_back( chan );
|
|
297
302
|
RELEASESPINLOCK( this->newchannelslock );
|
|
298
303
|
}
|
|
299
304
|
|
|
300
305
|
void projectchannelmux::addchannels( projectrtpchannelptr chana, projectrtpchannelptr chanb ) {
|
|
301
306
|
AQUIRESPINLOCK( this->newchannelslock );
|
|
307
|
+
chana->mixing = true;
|
|
308
|
+
chanb->mixing = true;
|
|
302
309
|
this->newchannels.push_back( chana );
|
|
303
310
|
this->newchannels.push_back( chanb );
|
|
304
311
|
RELEASESPINLOCK( this->newchannelslock );
|
|
@@ -313,6 +320,7 @@ void projectchannelmux::postrtpdata( projectrtpchannelptr srcchan, projectrtpcha
|
|
|
313
320
|
rtppacket *dst = dstchan->gettempoutbuf();
|
|
314
321
|
|
|
315
322
|
if( nullptr == dst ) {
|
|
323
|
+
dstchan->outpkdropcount++;
|
|
316
324
|
fprintf( stderr, "We have a null out buffer\n" );
|
|
317
325
|
return;
|
|
318
326
|
}
|
|
@@ -22,8 +22,8 @@ typedef std::shared_ptr< projectrtpchannel > projectrtpchannelptr;
|
|
|
22
22
|
typedef std::list< projectrtpchannelptr > projectchanptrlist;
|
|
23
23
|
|
|
24
24
|
class projectchannelmux:
|
|
25
|
-
public std::enable_shared_from_this< projectchannelmux >
|
|
26
|
-
|
|
25
|
+
public std::enable_shared_from_this< projectchannelmux > {
|
|
26
|
+
|
|
27
27
|
public:
|
|
28
28
|
projectchannelmux( boost::asio::io_context &iocontext );
|
|
29
29
|
~projectchannelmux();
|
|
@@ -58,6 +58,8 @@ private:
|
|
|
58
58
|
|
|
59
59
|
rawsound added;
|
|
60
60
|
rawsound subtracted;
|
|
61
|
+
|
|
62
|
+
bool active;
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
#endif /* PROJECTRTPCHANNELMUX_H */
|
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"
|
|
@@ -85,7 +87,6 @@ codecx::codecx() :
|
|
|
85
87
|
ilbcencoder( nullptr ),
|
|
86
88
|
ilbcdecoder( nullptr ),
|
|
87
89
|
lpfilter(),
|
|
88
|
-
resamplelastsample( 0 ),
|
|
89
90
|
l168kref(),
|
|
90
91
|
l1616kref(),
|
|
91
92
|
pcmaref(),
|
|
@@ -144,7 +145,6 @@ Do enough to manage missing packets.
|
|
|
144
145
|
void codecx::restart( void ) {
|
|
145
146
|
this->lpfilter.reset();
|
|
146
147
|
this->dcpowerfilter.reset();
|
|
147
|
-
this->resamplelastsample = 0;
|
|
148
148
|
this->_hasdata = false;
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -158,19 +158,17 @@ bool codecx::alaw2ulaw( void ) {
|
|
|
158
158
|
if( this->pcmaref.isdirty() ) return false;
|
|
159
159
|
|
|
160
160
|
uint8_t *inbufptr, *outbufptr;
|
|
161
|
-
size_t insize;
|
|
162
161
|
|
|
163
|
-
insize = this->pcmaref.size();
|
|
164
162
|
inbufptr = this->pcmaref.c_str();
|
|
165
163
|
outbufptr = this->pcmuref.c_str();
|
|
166
|
-
this->pcmuref.size(
|
|
164
|
+
this->pcmuref.size( G711PAYLOADBYTES );
|
|
167
165
|
|
|
168
166
|
if( nullptr == outbufptr || nullptr == inbufptr ) {
|
|
169
167
|
std::cerr << "PCMA NULLPTR shouldn't happen (" << (void*)outbufptr << ", " << (void*)inbufptr << ")" << std::endl;
|
|
170
168
|
return false;
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
for( size_t i = 0; i <
|
|
171
|
+
for( size_t i = 0; i < G711PAYLOADBYTES; i++ ) {
|
|
174
172
|
*outbufptr = alaw_to_ulaw_table[ *inbufptr ];
|
|
175
173
|
inbufptr++;
|
|
176
174
|
outbufptr++;
|
|
@@ -185,19 +183,17 @@ bool codecx::ulaw2alaw( void ) {
|
|
|
185
183
|
if( this->pcmuref.isdirty() ) return false;
|
|
186
184
|
|
|
187
185
|
uint8_t *inbufptr, *outbufptr;
|
|
188
|
-
size_t insize;
|
|
189
186
|
|
|
190
|
-
insize = this->pcmuref.size();
|
|
191
187
|
inbufptr = this->pcmuref.c_str();
|
|
192
188
|
outbufptr = this->pcmaref.c_str();
|
|
193
|
-
this->pcmaref.size(
|
|
189
|
+
this->pcmaref.size( G711PAYLOADBYTES );
|
|
194
190
|
|
|
195
191
|
if( nullptr == outbufptr || nullptr == inbufptr ) {
|
|
196
192
|
std::cerr << "PCMU NULLPTR shouldn't happen(" << (void*)outbufptr << ", " << (void*)inbufptr << ")" << std::endl;
|
|
197
193
|
return false;
|
|
198
194
|
}
|
|
199
195
|
|
|
200
|
-
for( size_t i = 0; i <
|
|
196
|
+
for( size_t i = 0; i < G711PAYLOADBYTES; i++ ) {
|
|
201
197
|
*outbufptr = ulaw_to_alaw_table[ *inbufptr ];
|
|
202
198
|
inbufptr++;
|
|
203
199
|
outbufptr++;
|
|
@@ -215,25 +211,22 @@ bool codecx::g711tol16( void )
|
|
|
215
211
|
{
|
|
216
212
|
uint8_t *in;
|
|
217
213
|
int16_t *convert;
|
|
218
|
-
size_t insize;
|
|
219
214
|
|
|
220
215
|
if( this->pcmaref.size() > 0 && !this->pcmaref.isdirty() ) {
|
|
221
216
|
in = this->pcmaref.c_str();
|
|
222
217
|
convert = _pcmatol16;
|
|
223
|
-
insize = this->pcmaref.size();
|
|
224
218
|
} else if ( this->pcmuref.size() > 0 && !this->pcmuref.isdirty() ) {
|
|
225
219
|
in = this->pcmuref.c_str();
|
|
226
220
|
convert = _pcmutol16;
|
|
227
|
-
insize = this->pcmuref.size();
|
|
228
221
|
} else {
|
|
229
222
|
return false;
|
|
230
223
|
}
|
|
231
224
|
|
|
232
|
-
this->l168kref.malloc(
|
|
225
|
+
this->l168kref.malloc( G711PAYLOADSAMPLES, sizeof( int16_t ), L168KPAYLOADTYPE );
|
|
233
226
|
|
|
234
227
|
int16_t *out = ( int16_t * ) this->l168kref.c_str();
|
|
235
228
|
|
|
236
|
-
for( size_t i = 0; i <
|
|
229
|
+
for( size_t i = 0; i < G711PAYLOADSAMPLES; i++ ) {
|
|
237
230
|
*out = convert[ *in ];
|
|
238
231
|
in++;
|
|
239
232
|
out++;
|
|
@@ -255,11 +248,10 @@ bool codecx::l16topcma( void )
|
|
|
255
248
|
uint8_t *out = this->pcmaref.c_str();
|
|
256
249
|
|
|
257
250
|
int16_t *in;
|
|
258
|
-
size_t l168klength = this->l168kref.size();
|
|
259
251
|
in = ( int16_t * ) this->l168kref.c_str();
|
|
260
252
|
|
|
261
253
|
uint16_t index;
|
|
262
|
-
for( size_t i = 0; i <
|
|
254
|
+
for( size_t i = 0; i < G711PAYLOADBYTES; i++ ) {
|
|
263
255
|
index = *in + 32768;
|
|
264
256
|
*out = _l16topcma[ index ];
|
|
265
257
|
in++;
|
|
@@ -279,11 +271,10 @@ bool codecx::l16topcmu( void ) {
|
|
|
279
271
|
uint8_t *out = this->pcmuref.c_str();;
|
|
280
272
|
|
|
281
273
|
int16_t *in;
|
|
282
|
-
size_t l168klength = this->l168kref.size();
|
|
283
274
|
in = ( int16_t * ) this->l168kref.c_str();
|
|
284
275
|
|
|
285
276
|
uint16_t index;
|
|
286
|
-
for( size_t i = 0; i <
|
|
277
|
+
for( size_t i = 0; i < G711PAYLOADBYTES; i++ ) {
|
|
287
278
|
index = *in + 32768;
|
|
288
279
|
*out = _l16topcmu[ index ];
|
|
289
280
|
in++;
|
|
@@ -313,43 +304,16 @@ bool codecx::ilbctol16( void ) {
|
|
|
313
304
|
|
|
314
305
|
int16_t l168klength = WebRtcIlbcfix_Decode( this->ilbcdecoder,
|
|
315
306
|
( ilbcencodedval ) this->ilbcref.c_str(),
|
|
316
|
-
|
|
307
|
+
ILBC20PAYLOADBYTES,
|
|
317
308
|
( ilbcdecodedval )this->l168kref.c_str(),
|
|
318
309
|
&speechType
|
|
319
310
|
);
|
|
320
311
|
|
|
321
312
|
if( -1 == l168klength ) {
|
|
322
|
-
this->l168kref.size( 0 );
|
|
323
|
-
this->l168kref.dirty( false );
|
|
324
313
|
return false;
|
|
325
314
|
}
|
|
326
315
|
|
|
327
|
-
this->l168kref.
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/*!md
|
|
332
|
-
## l16tog722
|
|
333
|
-
As it says.
|
|
334
|
-
*/
|
|
335
|
-
bool codecx::l16tog722( void ) {
|
|
336
|
-
if( 0 == this->l1616kref.size() ) return false;
|
|
337
|
-
if( this->l1616kref.isdirty() ) return false;
|
|
338
|
-
|
|
339
|
-
if( nullptr == this->g722encoder ) {
|
|
340
|
-
this->g722encoder = g722_encode_init( NULL, 64000, G722_PACKED );
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
int len = g722_encode( this->g722encoder, this->g722ref.c_str(), ( int16_t * ) this->l1616kref.c_str(), this->g722ref.size() * 2 );
|
|
344
|
-
|
|
345
|
-
if( len > 0 ) {
|
|
346
|
-
this->g722ref.size( len );
|
|
347
|
-
this->g722ref.dirty( false );
|
|
348
|
-
} else {
|
|
349
|
-
std::cerr << "g722_encode didn't encode any data" << std::endl;
|
|
350
|
-
this->g722ref.size( 0 );
|
|
351
|
-
}
|
|
352
|
-
|
|
316
|
+
this->l168kref.dirty( false );
|
|
353
317
|
return true;
|
|
354
318
|
}
|
|
355
319
|
|
|
@@ -373,11 +337,10 @@ bool codecx::l16toilbc( void ) {
|
|
|
373
337
|
|
|
374
338
|
int16_t len = WebRtcIlbcfix_Encode( this->ilbcencoder,
|
|
375
339
|
( ilbcdecodedval ) this->l168kref.c_str(),
|
|
376
|
-
|
|
340
|
+
L16PAYLOADSAMPLES,
|
|
377
341
|
( ilbcencodedval ) this->ilbcref.c_str()
|
|
378
342
|
);
|
|
379
343
|
if ( len > 0 ) {
|
|
380
|
-
this->ilbcref.size( len );
|
|
381
344
|
this->ilbcref.dirty( false );
|
|
382
345
|
return true;
|
|
383
346
|
}
|
|
@@ -388,6 +351,33 @@ bool codecx::l16toilbc( void ) {
|
|
|
388
351
|
}
|
|
389
352
|
|
|
390
353
|
|
|
354
|
+
/*!md
|
|
355
|
+
## l16tog722
|
|
356
|
+
As it says.
|
|
357
|
+
*/
|
|
358
|
+
bool codecx::l16tog722( void ) {
|
|
359
|
+
|
|
360
|
+
if( 0 == this->l1616kref.size() ) return false;
|
|
361
|
+
if( this->l1616kref.isdirty() ) return false;
|
|
362
|
+
|
|
363
|
+
if( nullptr == this->g722encoder ) {
|
|
364
|
+
this->g722encoder = g722_encode_init( NULL, 64000, G722_PACKED );
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// TODO - when we convert to g722 - 722 buffer is always output -so malloc need sto be able to detect that.
|
|
368
|
+
//this->g722ref.malloc( G722PAYLOADSAMPLES, sizeof( int8_t ), G722PAYLOADTYPE );
|
|
369
|
+
|
|
370
|
+
int len = g722_encode( this->g722encoder, this->g722ref.c_str(), ( int16_t * ) this->l1616kref.c_str(), L1616PAYLOADSAMPLES );
|
|
371
|
+
|
|
372
|
+
if( 160 != len ) {
|
|
373
|
+
std::cerr << "g722_encode didn't encode correct length of data" << std::endl;
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
this->g722ref.dirty( false );
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
|
|
391
381
|
/*!md
|
|
392
382
|
## g722tol16
|
|
393
383
|
As it says.
|
|
@@ -396,8 +386,7 @@ bool codecx::g722tol16( void ) {
|
|
|
396
386
|
if( 0 == this->g722ref.size() ) return false;
|
|
397
387
|
if( this->g722ref.isdirty() ) return false;
|
|
398
388
|
|
|
399
|
-
|
|
400
|
-
this->l1616kref.malloc( this->g722ref.size(), sizeof( int16_t ), L1616KPAYLOADTYPE );
|
|
389
|
+
this->l1616kref.malloc( L1616PAYLOADSAMPLES, sizeof( int16_t ), L1616KPAYLOADTYPE );
|
|
401
390
|
|
|
402
391
|
if( nullptr == this->g722decoder ) {
|
|
403
392
|
this->g722decoder = g722_decode_init( NULL, 64000, G722_PACKED );
|
|
@@ -409,9 +398,10 @@ bool codecx::g722tol16( void ) {
|
|
|
409
398
|
size_t l1616klength = g722_decode( this->g722decoder,
|
|
410
399
|
( int16_t * ) this->l1616kref.c_str(),
|
|
411
400
|
this->g722ref.c_str(),
|
|
412
|
-
|
|
401
|
+
G722PAYLOADBYTES );
|
|
413
402
|
|
|
414
|
-
|
|
403
|
+
if( 320 != l1616klength ) return false;
|
|
404
|
+
|
|
415
405
|
this->l1616kref.dirty( false );
|
|
416
406
|
return true;
|
|
417
407
|
}
|
|
@@ -421,23 +411,19 @@ bool codecx::g722tol16( void ) {
|
|
|
421
411
|
Upsample from narrow to wideband. Take each point and interpolate between them. We require the final sample from the last packet to continue the interpolating.
|
|
422
412
|
*/
|
|
423
413
|
bool codecx::l16lowtowideband( void ) {
|
|
424
|
-
size_t l168klength = this->l168kref.size();
|
|
425
414
|
|
|
426
|
-
if( 0 ==
|
|
415
|
+
if( 0 == this->l168kref.size() ) return false;
|
|
427
416
|
if( this->l168kref.isdirty() ) return false;
|
|
428
417
|
|
|
429
|
-
this->l1616kref.malloc(
|
|
418
|
+
this->l1616kref.malloc( L1616PAYLOADSAMPLES, sizeof( int16_t ), L1616KPAYLOADTYPE );
|
|
430
419
|
|
|
431
420
|
int16_t *in = ( int16_t * ) this->l168kref.c_str();
|
|
432
421
|
int16_t *out = ( int16_t * ) this->l1616kref.c_str();
|
|
433
422
|
|
|
434
|
-
for( size_t i = 0; i <
|
|
435
|
-
*out = (
|
|
436
|
-
this->resamplelastsample = *in;
|
|
423
|
+
for( size_t i = 0; i < L16PAYLOADSAMPLES; i++ ) {
|
|
424
|
+
*out = this->lpfilter.execute( *in );
|
|
437
425
|
out++;
|
|
438
|
-
|
|
439
|
-
*out = *in;
|
|
440
|
-
|
|
426
|
+
*out = this->lpfilter.execute( 0 );
|
|
441
427
|
out++;
|
|
442
428
|
in++;
|
|
443
429
|
}
|
|
@@ -455,7 +441,7 @@ bool codecx::requirewideband( void ) {
|
|
|
455
441
|
if( this->g722tol16() ) return true;
|
|
456
442
|
if( !this->g711tol16() )
|
|
457
443
|
{
|
|
458
|
-
if( this->ilbctol16() ) return false;
|
|
444
|
+
if( !this->ilbctol16() ) return false;
|
|
459
445
|
}
|
|
460
446
|
|
|
461
447
|
return this->l16lowtowideband();
|
|
@@ -465,22 +451,20 @@ bool codecx::requirewideband( void ) {
|
|
|
465
451
|
## l16widetolowband
|
|
466
452
|
Downsample our L16 wideband samples to 8K. Pass through filter then grab every other sample.
|
|
467
453
|
*/
|
|
468
|
-
bool codecx::l16widetonarrowband( void )
|
|
469
|
-
{
|
|
470
|
-
size_t l1616klength = this->l1616kref.size();
|
|
454
|
+
bool codecx::l16widetonarrowband( void ) {
|
|
471
455
|
|
|
472
|
-
if( 0 ==
|
|
456
|
+
if( 0 == this->l1616kref.size() ) return false;
|
|
473
457
|
if( this->l1616kref.isdirty() ) return false;
|
|
474
458
|
|
|
475
|
-
this->l168kref.malloc(
|
|
459
|
+
this->l168kref.malloc( L16PAYLOADSAMPLES, sizeof( int16_t ), L168KPAYLOADTYPE );
|
|
476
460
|
|
|
477
461
|
int16_t *out = ( int16_t * ) this->l168kref.c_str();
|
|
478
462
|
int16_t *in = ( int16_t * ) this->l1616kref.c_str();
|
|
479
463
|
|
|
480
|
-
for( size_t i = 0; i <
|
|
481
|
-
lpfilter.execute( *in );
|
|
464
|
+
for( size_t i = 0; i < L16PAYLOADSAMPLES; i++ ) {
|
|
465
|
+
this->lpfilter.execute( *in );
|
|
482
466
|
in++;
|
|
483
|
-
*out = lpfilter.execute( *in );
|
|
467
|
+
*out = this->lpfilter.execute( *in );
|
|
484
468
|
in++;
|
|
485
469
|
out++;
|
|
486
470
|
}
|
|
@@ -518,9 +502,10 @@ rawsound& codecx::requirel16( void )
|
|
|
518
502
|
return this->l168kref;
|
|
519
503
|
}
|
|
520
504
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
505
|
+
/**
|
|
506
|
+
* Obtain a reference to a rawsound for the codec type pt. i.e. we alrteady have
|
|
507
|
+
* the input sound and based on the format we want to convert it to that
|
|
508
|
+
* format.
|
|
524
509
|
*/
|
|
525
510
|
rawsound& codecx::getref( int pt ) {
|
|
526
511
|
/* If we have already have or converted this packet... */
|
|
@@ -558,7 +543,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
558
543
|
return this->g722ref;
|
|
559
544
|
}
|
|
560
545
|
case PCMAPAYLOADTYPE: {
|
|
561
|
-
if( this->pcmuref.size() > 0 ) {
|
|
546
|
+
if( !this->pcmuref.isdirty() && this->pcmuref.size() > 0 ) {
|
|
562
547
|
this->ulaw2alaw();
|
|
563
548
|
} else {
|
|
564
549
|
this->requirenarrowband();
|
|
@@ -567,7 +552,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
567
552
|
return this->pcmaref;
|
|
568
553
|
}
|
|
569
554
|
case PCMUPAYLOADTYPE: {
|
|
570
|
-
if( this->pcmaref.size() > 0 ) {
|
|
555
|
+
if( !this->pcmaref.isdirty() && this->pcmaref.size() > 0 ) {
|
|
571
556
|
this->alaw2ulaw();
|
|
572
557
|
} else {
|
|
573
558
|
this->requirenarrowband();
|
|
@@ -586,7 +571,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
586
571
|
}
|
|
587
572
|
|
|
588
573
|
/* We should ever get here unless an invalid param has been passed in */
|
|
589
|
-
std::cerr << "codecx::getref call with bad pt" << std::endl;
|
|
574
|
+
std::cerr << "codecx::getref call with bad pt: " << pt << std::endl;
|
|
590
575
|
return this->pcmuref;
|
|
591
576
|
}
|
|
592
577
|
|
|
@@ -625,52 +610,43 @@ We pass a packet in, then we can take multiple out - i.e. we may want different
|
|
|
625
610
|
|
|
626
611
|
Have a think about if this is where we want to mix audio data.
|
|
627
612
|
*/
|
|
628
|
-
codecx& operator << ( codecx& c, rtppacket& pk )
|
|
629
|
-
{
|
|
613
|
+
codecx& operator << ( codecx& c, rtppacket& pk ) {
|
|
630
614
|
c.inpkcount++;
|
|
631
615
|
rawsound r = rawsound( pk );
|
|
632
616
|
c << r;
|
|
633
617
|
return c;
|
|
634
618
|
}
|
|
635
619
|
|
|
636
|
-
codecx& operator << ( codecx& c, rawsound& raw )
|
|
637
|
-
{
|
|
620
|
+
codecx& operator << ( codecx& c, rawsound& raw ) {
|
|
638
621
|
int inpayloadtype = raw.getformat();
|
|
639
622
|
|
|
640
|
-
switch( inpayloadtype )
|
|
641
|
-
|
|
642
|
-
case PCMAPAYLOADTYPE:
|
|
643
|
-
{
|
|
623
|
+
switch( inpayloadtype ) {
|
|
624
|
+
case PCMAPAYLOADTYPE: {
|
|
644
625
|
c.pcmaref = raw;
|
|
645
626
|
c._hasdata = true;
|
|
646
627
|
break;
|
|
647
628
|
}
|
|
648
|
-
case PCMUPAYLOADTYPE:
|
|
649
|
-
{
|
|
629
|
+
case PCMUPAYLOADTYPE: {
|
|
650
630
|
c.pcmuref = raw;
|
|
651
631
|
c._hasdata = true;
|
|
652
632
|
break;
|
|
653
633
|
}
|
|
654
|
-
case ILBCPAYLOADTYPE:
|
|
655
|
-
{
|
|
634
|
+
case ILBCPAYLOADTYPE: {
|
|
656
635
|
c.ilbcref = raw;
|
|
657
636
|
c._hasdata = true;
|
|
658
637
|
break;
|
|
659
638
|
}
|
|
660
|
-
case G722PAYLOADTYPE:
|
|
661
|
-
{
|
|
639
|
+
case G722PAYLOADTYPE: {
|
|
662
640
|
c.g722ref = raw;
|
|
663
641
|
c._hasdata = true;
|
|
664
642
|
break;
|
|
665
643
|
}
|
|
666
|
-
case L168KPAYLOADTYPE:
|
|
667
|
-
{
|
|
644
|
+
case L168KPAYLOADTYPE: {
|
|
668
645
|
c.l168kref = raw;
|
|
669
646
|
c._hasdata = true;
|
|
670
647
|
break;
|
|
671
648
|
}
|
|
672
|
-
case L1616KPAYLOADTYPE:
|
|
673
|
-
{
|
|
649
|
+
case L1616KPAYLOADTYPE: {
|
|
674
650
|
c.l1616kref = raw;
|
|
675
651
|
c._hasdata = true;
|
|
676
652
|
break;
|
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>
|
|
@@ -83,10 +85,8 @@ private:
|
|
|
83
85
|
ilbcencinst *ilbcencoder;
|
|
84
86
|
ilbcdecinst *ilbcdecoder;
|
|
85
87
|
|
|
86
|
-
/* If we require downsampling */
|
|
88
|
+
/* If we require up/downsampling */
|
|
87
89
|
lowpass3_4k16k lpfilter;
|
|
88
|
-
/* When we up sample we need to interpolate so need last sample */
|
|
89
|
-
int16_t resamplelastsample;
|
|
90
90
|
|
|
91
91
|
rawsound l168kref;
|
|
92
92
|
rawsound l1616kref;
|
|
@@ -127,6 +127,8 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
127
127
|
|
|
128
128
|
switch( outpayloadtype ) {
|
|
129
129
|
case ILBCPAYLOADTYPE: {
|
|
130
|
+
pk->setpayloadlength( ILBC20PAYLOADBYTES );
|
|
131
|
+
|
|
130
132
|
if( !c.ilbcref.isdirty() ) {
|
|
131
133
|
pk->copy( c.ilbcref.c_str(), c.ilbcref.size() * c.ilbcref.getbytespersample() );
|
|
132
134
|
return pk;
|
|
@@ -135,6 +137,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
135
137
|
break;
|
|
136
138
|
}
|
|
137
139
|
case G722PAYLOADTYPE: {
|
|
140
|
+
pk->setpayloadlength( G722PAYLOADBYTES );
|
|
138
141
|
if( !c.g722ref.isdirty() ) {
|
|
139
142
|
pk->copy( c.g722ref.c_str(), c.g722ref.size() * c.g722ref.getbytespersample() );
|
|
140
143
|
return pk;
|
|
@@ -143,6 +146,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
143
146
|
break;
|
|
144
147
|
}
|
|
145
148
|
case PCMAPAYLOADTYPE: {
|
|
149
|
+
pk->setpayloadlength( G711PAYLOADBYTES );
|
|
146
150
|
if( !c.pcmaref.isdirty() ) {
|
|
147
151
|
pk->copy( c.pcmaref.c_str(), c.pcmaref.size() * c.pcmaref.getbytespersample() );
|
|
148
152
|
return pk;
|
|
@@ -151,6 +155,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
151
155
|
break;
|
|
152
156
|
}
|
|
153
157
|
case PCMUPAYLOADTYPE: {
|
|
158
|
+
pk->setpayloadlength( G711PAYLOADBYTES );
|
|
154
159
|
if( !c.pcmuref.isdirty() ) {
|
|
155
160
|
pk->copy( c.pcmuref.c_str(), c.pcmuref.size() * c.pcmuref.getbytespersample() );
|
|
156
161
|
return pk;
|
|
@@ -159,6 +164,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
159
164
|
break;
|
|
160
165
|
}
|
|
161
166
|
case L168KPAYLOADTYPE: {
|
|
167
|
+
pk->setpayloadlength( L16NARROWBANDBYTES );
|
|
162
168
|
if( !c.l168kref.isdirty() ) {
|
|
163
169
|
pk->copy( c.l168kref.c_str(), c.l168kref.size() * c.l168kref.getbytespersample() );
|
|
164
170
|
return pk;
|
|
@@ -168,6 +174,7 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
case L1616KPAYLOADTYPE: {
|
|
177
|
+
pk->setpayloadlength( L16WIDEBANDBYTES );
|
|
171
178
|
if( !c.l1616kref.isdirty() ) {
|
|
172
179
|
pk->copy( c.l1616kref.c_str(), c.l1616kref.size() * c.l1616kref.getbytespersample() );
|
|
173
180
|
return pk;
|
|
@@ -175,10 +182,16 @@ auto* operator << ( auto *pk, codecx& c ) {
|
|
|
175
182
|
c.l1616kref = rawsound( *pk, true );
|
|
176
183
|
break;
|
|
177
184
|
}
|
|
185
|
+
default: {
|
|
186
|
+
/* this should not happen */
|
|
187
|
+
std::cerr << "Unknown CODEC when encoding: " << outpayloadtype << std::endl;
|
|
188
|
+
return pk;
|
|
189
|
+
}
|
|
178
190
|
}
|
|
179
191
|
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
/* encode */
|
|
193
|
+
c.getref( outpayloadtype );
|
|
194
|
+
|
|
182
195
|
return pk;
|
|
183
196
|
}
|
|
184
197
|
|