@babblevoice/projectrtp 2.5.34 → 2.5.38

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.
@@ -6,6 +6,7 @@
6
6
  #include <string>
7
7
 
8
8
  #include <memory>
9
+ #include <vector>
9
10
 
10
11
 
11
12
  #include <sys/types.h>
@@ -25,6 +26,8 @@
25
26
  #define SOUNDFILENUMBUFFERS 8
26
27
  #define MAXNUMBEROFCHANNELS 2
27
28
 
29
+ typedef std::vector< int16_t > soundbuffer;
30
+
28
31
  typedef struct {
29
32
  /* RIFF Header */
30
33
  uint8_t riff_header[ 4 ]; /* Contains "RIFF" */
@@ -83,12 +86,14 @@ protected:
83
86
  wavheader ourwavheader;
84
87
 
85
88
  /* asynchronous variables */
86
- int currentcbindex;
89
+ u_int8_t currentcbindex;
87
90
  aiocb cbwavheader;
88
91
  aiocb cbwavblock[ SOUNDFILENUMBUFFERS ];
89
92
 
90
93
  /* buffer for data */
91
- uint8_t *buffer;
94
+ soundbuffer buffer[ SOUNDFILENUMBUFFERS ];
95
+
96
+ std::atomic_bool filelock;
92
97
  };
93
98
 
94
99
 
@@ -109,14 +114,20 @@ public:
109
114
  bool complete( void );
110
115
 
111
116
  void setposition( long mseconds );
117
+
112
118
  long getposition( void );
113
119
 
114
120
  inline bool isopen( void ) { return this->file != -1; }
115
121
 
116
122
  private:
117
123
  long offtomsecs( void );
124
+ void parseheader( void );
125
+
126
+ /* called by us - so we have a lock */
127
+ void realsetposition( long mseconds );
118
128
 
119
- int blocksize;
129
+ size_t bytecount;
130
+ size_t samplecount;
120
131
  bool badheader;
121
132
  bool headerread;
122
133
  bool bodyread;
@@ -1,4 +1,6 @@
1
1
 
2
+ /* needed to build on ubuntu */
3
+ #include <utility>
2
4
 
3
5
  #include <iostream>
4
6
  #include "projectrtpsoundsoup.h"
@@ -3,6 +3,9 @@
3
3
  A very (very) simple STUN implimentation.
4
4
  */
5
5
 
6
+ /* needed to build on ubuntu */
7
+ #include <utility>
8
+
6
9
  /* printf when required */
7
10
  #include <cstdio>
8
11
 
@@ -41,8 +41,11 @@ module.exports = async ( mstimeout ) => {
41
41
  channela.echo()
42
42
 
43
43
  await utils.waitbetween( 0, 500 )
44
+ /* include settings which terminate the recording before OR after the channel closes */
44
45
  channela.record( {
45
- "file": recording
46
+ "file": recording,
47
+ "maxduration": utils.waitbetween( 50, mstimeout * 2 ),
48
+ "finishbelowpower": 200
46
49
  } )
47
50
 
48
51
  }
package/stress/index.js CHANGED
@@ -14,6 +14,8 @@ scenarios.push( require( "./echodualrecordpower.scenario.js" ) )
14
14
  scenarios.push( require( "./echodualrecordpausestop.scenario.js" ) )
15
15
  scenarios.push( require( "./mix2.scenario.js" ) )
16
16
  scenarios.push( require( "./mixunmix.scenario.js" ) )
17
+ scenarios.push( require( "./playbackthenmix.scenario.js" ) )
18
+ scenarios.push( require( "./playbackrecordtoofast.scenario.js" ) )
17
19
 
18
20
  /*
19
21
  The purpose of this script is to load up projectrtp to expose any issues with timing.
@@ -23,7 +25,7 @@ folder is for.
23
25
  We have a problem with "we should never get here - we have no more buffer available on port"
24
26
  */
25
27
 
26
- const maxnumberofsessions = 200
28
+ const maxnumberofsessions = 1000
27
29
  const secondsruntime = 3600*12
28
30
  const minmscalllength = 50
29
31
  const maxmscalllength = 1000 * 60 * 10 /* 1000 mS per second 60 seconds per minute , n minutes */
@@ -43,6 +45,7 @@ const run = async () => {
43
45
  if ( "node" === process.argv.slice(2)[0] ) {
44
46
  console.log( "Mode: node as listener" )
45
47
  projectrtp.proxy.addnode( { host: "127.0.0.1", port: 9002 } )
48
+ // @ts-ignore
46
49
  await node.listen( projectrtp, "127.0.0.1", 9002 )
47
50
  } else console.log( "Mode: server as listener" )
48
51
 
@@ -0,0 +1,106 @@
1
+
2
+
3
+ const dgram = require( "dgram" )
4
+
5
+ const projectrtp = require( "../index.js" ).projectrtp
6
+ const fs = require( "fs" )
7
+ const utils = require( "./utils.js" )
8
+
9
+ /*
10
+ js client (too fast) ---> channela (play/record)
11
+ */
12
+
13
+ function sendpk( sn, sendtime, dstport, server, data = undefined, pt = 0, ssrc = 25 ) {
14
+
15
+ const pklength = 172
16
+
17
+ return setTimeout( () => {
18
+
19
+ let payload
20
+ if( undefined !== data ) {
21
+ payload = data
22
+ } else {
23
+ payload = Buffer.alloc( pklength - 12 ).fill( projectrtp.codecx.linear162pcmu( sn ) & 0xff )
24
+ }
25
+
26
+ const subheader = Buffer.alloc( 10 )
27
+
28
+ const ts = sn * 160
29
+
30
+ subheader.writeUInt16BE( ( sn + 100 ) % ( 2**16 ) /* just some offset */ )
31
+ subheader.writeUInt32BE( ts, 2 )
32
+ subheader.writeUInt32BE( ssrc, 6 )
33
+
34
+ const header = Buffer.from( [ 0x80, 0x00 ] )
35
+ header.writeUInt8( pt, 1 ) // payload type
36
+
37
+ const rtppacket = Buffer.concat( [
38
+ header,
39
+ subheader,
40
+ payload ] )
41
+
42
+ server.send( rtppacket, dstport, "localhost" )
43
+ }, sendtime * 17 )
44
+ }
45
+
46
+ async function createclient() {
47
+ const client = dgram.createSocket( "udp4" )
48
+ client.on( "message", function( msg ) {
49
+ } )
50
+
51
+ client.bind()
52
+ await new Promise( ( r ) => { client.on( "listening", function() { r() } ) } )
53
+
54
+ return client
55
+ }
56
+
57
+ module.exports = async ( mstimeout ) => {
58
+
59
+ const acodec = utils.randcodec()
60
+
61
+ utils.log( `Starting playback with record for ${mstimeout} mS but sending packets too quickly` )
62
+ const recording = utils.mktempwav()
63
+
64
+ const clienta = await createclient()
65
+ const clientb = await createclient()
66
+
67
+ const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": clienta.address().port, "codec": acodec } }, async ( d ) => {
68
+ if( "close" === d.action ) {
69
+ utils.logclosechannel( `Playback with record for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
70
+ await fs.promises.unlink( recording ).catch( () => {} )
71
+ }
72
+ } )
73
+
74
+ const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": clientb.address().port, "codec": acodec } }, async ( d ) => {
75
+ if( "close" === d.action ) {
76
+ utils.logclosechannel( `Playback with record for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
77
+ await fs.promises.unlink( recording ).catch( () => {} )
78
+ }recording
79
+ } )
80
+
81
+ utils.lognewchannel()
82
+ utils.lognewchannel()
83
+
84
+ const pkcount = Math.floor( mstimeout / 20 )
85
+ for( let i = 0; i < pkcount; i++ ) {
86
+ sendpk( i, i, channela.local.port, clienta, )
87
+ }
88
+
89
+ for( let i = 0; i < pkcount; i++ ) {
90
+ sendpk( i, i, channelb.local.port, clientb, )
91
+ }
92
+
93
+ await utils.waitbetween( 0, 500 )
94
+ channela.mix( channelb )
95
+
96
+ await utils.waitbetween( 0, 500 )
97
+ channela.record( {
98
+ "file": recording,
99
+ "numchannels": utils.between( 0, 1 )
100
+ } )
101
+
102
+ await utils.wait( mstimeout )
103
+
104
+ clienta.close()
105
+ channela.close()
106
+ }
@@ -0,0 +1,70 @@
1
+
2
+ const projectrtp = require( "../index.js" ).projectrtp
3
+ const utils = require( "./utils.js" )
4
+ const expect = require( "chai" ).expect
5
+
6
+ /**
7
+ * clienta (echo) ---> channela (play/mix)
8
+ * @param { number } mstimeout
9
+ */
10
+ module.exports = async ( mstimeout ) => {
11
+
12
+ const acodec = utils.randcodec()
13
+ const bcodec = utils.randcodec()
14
+
15
+ utils.log( `Starting playback then mix for ${mstimeout} mS` )
16
+
17
+ const clienta = await projectrtp.openchannel( {}, ( d ) => {
18
+ if( "close" === d.action ) {
19
+ channela.close()
20
+ utils.logclosechannel( `Mix 2 after play (clienta) for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
21
+ }
22
+ } )
23
+ utils.lognewchannel()
24
+
25
+ const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": clienta.local.port, "codec": acodec } }, async ( d ) => {
26
+ if( "play" === d.action && "end" === d.event && "channelmixing" === d.reason ) {
27
+ utils.log( "Channel stopped playback because channel mixing" )
28
+ } else if( "close" === d.action ) {
29
+ utils.logclosechannel( `Playback then mix for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
30
+ }
31
+ } )
32
+
33
+ clienta.remote( { "address": "localhost", "port": channela.local.port, "codec": acodec } )
34
+ clienta.echo()
35
+ utils.lognewchannel()
36
+
37
+ channela.play( {
38
+ "loop": true,
39
+ "files": [
40
+ { "wav": "/tmp/ukringing.wav" }
41
+ ]
42
+ } )
43
+
44
+ await utils.waitbetween( 100, 1000 )
45
+
46
+ const clientb = await projectrtp.openchannel( {}, ( d ) => {
47
+ if( "close" === d.action ) {
48
+ channelb.close()
49
+ utils.logclosechannel( `Mix 2 after play (clientb) for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
50
+ }
51
+ } )
52
+ utils.lognewchannel()
53
+
54
+ const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": clientb.local.port, "codec": bcodec } }, ( d ) => {
55
+ if( "close" === d.action ) {
56
+ utils.logclosechannel( `Mix 2 after play (channelb) for ${mstimeout} mS completed with reason '${d.reason}'`, d, mstimeout )
57
+ }
58
+ } )
59
+ clientb.remote( { "address": "localhost", "port": channelb.local.port, "codec": bcodec } )
60
+ utils.lognewchannel()
61
+
62
+ expect( await channela.mix( channelb ) ).to.be.true
63
+ expect( clienta.play( { "loop": true, "files": [ { "wav": "/tmp/ukringing.wav" } ] } ) ).to.be.true
64
+ expect( clientb.echo() ).to.be.true
65
+
66
+ await new Promise( ( r ) => { setTimeout( () => r(), Math.max( mstimeout, 110 ) ) } )
67
+ clienta.close()
68
+ clientb.close()
69
+
70
+ }
package/stress/utils.js CHANGED
@@ -21,8 +21,8 @@ module.exports.logclosechannel = ( message, d, mstimeout ) => {
21
21
  totalcount++
22
22
  module.exports.log( message )
23
23
 
24
- const score = ( d.stats.in["count"] / mstimeout * 20 ).toFixed( 2 )
25
- let scoremsg = ` Score: ${ score }`
24
+ const score = ( d.stats.in["count"] / mstimeout * 20 )
25
+ let scoremsg = ` Score: ${ score.toFixed( 2 ) }`
26
26
 
27
27
  // Colour based on score: red, yellow, green
28
28
  if( 0.25 >= score ) scoremsg = "\x1B[31m" + scoremsg
@@ -50,17 +50,41 @@ module.exports.mktempwav = () => {
50
50
  return "/tmp/project_" + (Math.random() + 1).toString(36).substring(7) + ".wav"
51
51
  }
52
52
 
53
+ /**
54
+ *
55
+ * @param { number } min - lower value
56
+ * @param { number } max - upper value
57
+ * @returns { number }
58
+ */
53
59
  module.exports.between = ( min, max ) => {
54
60
  return Math.floor(
55
61
  Math.random() * ( max - min ) + min
56
62
  )
57
63
  }
58
64
 
65
+ /**
66
+ *
67
+ * @param { number } min - min time mS
68
+ * @param { number } max - max time mS
69
+ * @returns { Promise }
70
+ */
59
71
  module.exports.waitbetween = async ( min, max ) => {
60
- return new Promise( ( resolve ) => { setTimeout( () => resolve(), module.exports.between( min, max ) ) } )
72
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), module.exports.between( min, max ) ) } )
73
+ }
74
+
75
+ /**
76
+ *
77
+ * @param { number } ms
78
+ */
79
+ module.exports.wait = async ( ms ) => {
80
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), ms ) } )
61
81
  }
62
82
 
63
83
  const possiblecodecs = [ 0, 8, 9, 97 ]
84
+ /**
85
+ * Returns random supported CODEC
86
+ * @returns { number }
87
+ */
64
88
  module.exports.randcodec = () => {
65
89
  return possiblecodecs[ module.exports.between( 0, possiblecodecs.length ) ]
66
90
  }
@@ -38,6 +38,26 @@ function parsepk( packet ) {
38
38
  }
39
39
  }
40
40
 
41
+ /**
42
+ * Limitation of not parsing ccrc.
43
+ * @param { Buffer } packet
44
+ * @return { object }
45
+ */
46
+ function parse2833pk( packet ) {
47
+ return {
48
+ sn: packet.readUInt16BE( 2 ),
49
+ ts: packet.readUInt32BE( 4 ),
50
+ pt: packet.readUInt8( 1 ) & 0x7f,
51
+ ssrc: packet.readUInt32BE( 8 ),
52
+ event: {
53
+ id: packet.readUInt8( 12 ),
54
+ eoe: ( packet.readUInt8( 13 ) & 0x80 ) == 0x80,
55
+ volume: packet.readUInt8( 13 ) & 0x7f,
56
+ duration: packet.readUInt16BE( 14 ),
57
+ }
58
+ }
59
+ }
60
+
41
61
  /* helper functions */
42
62
  function sendpk( sn, ts, sendtime, dstport, server, pt = 0, ssrc ) {
43
63
 
@@ -182,7 +202,7 @@ describe( "dtmf", function() {
182
202
 
183
203
  if( "close" === d.action ) {
184
204
  server.close()
185
- expect( dtmfpkcount ).to.equal( 2*6 )
205
+ expect( dtmfpkcount ).to.equal( 2*7 )
186
206
  done()
187
207
  }
188
208
  } )
@@ -206,10 +226,10 @@ describe( "dtmf", function() {
206
226
  const clienta = dgram.createSocket( "udp4" )
207
227
  const clientb = dgram.createSocket( "udp4" )
208
228
 
209
- let dtmfpkcount = 0
229
+ const dtmfpks = []
210
230
  clienta.on( "message", function( msg ) {
211
231
  if( 101 == ( 0x7f & msg [ 1 ] ) ) {
212
- dtmfpkcount++
232
+ dtmfpks.push( parse2833pk( msg ) )
213
233
  } else {
214
234
  expect( msg.length ).to.equal( 172 )
215
235
  expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
@@ -219,7 +239,6 @@ describe( "dtmf", function() {
219
239
  clientb.on( "message", function( msg ) {
220
240
  if( 101 == ( 0x7f & msg [ 1 ] ) ) {
221
241
  expect( true ).to.equal( false ) //here = bad
222
- dtmfpkcount++
223
242
  }
224
243
  clientb.send( msg, channelb.local.port, "localhost" )
225
244
  } )
@@ -263,7 +282,19 @@ describe( "dtmf", function() {
263
282
  clienta.close()
264
283
  clientb.close()
265
284
 
266
- expect( dtmfpkcount ).to.equal( 3*6 )
285
+ expect( dtmfpks.length ).to.equal( 3*7 )
286
+ expect( dtmfpks[ 0 ].event.id ).to.equal( 10 )
287
+ expect( dtmfpks[ 0 ].event.duration ).to.equal( 160 )
288
+ expect( dtmfpks[ 0 ].event.eoe ).to.be.false
289
+
290
+ expect( dtmfpks[ 4 ].event.id ).to.equal( 10 )
291
+ expect( dtmfpks[ 4 ].event.duration ).to.equal( 800 )
292
+ expect( dtmfpks[ 4 ].event.eoe ).to.be.true
293
+
294
+ expect( dtmfpks[ 6 ].event.id ).to.equal( 10 )
295
+ expect( dtmfpks[ 6 ].event.duration ).to.equal( 800 )
296
+ expect( dtmfpks[ 6 ].event.eoe ).to.be.true
297
+
267
298
  } )
268
299
 
269
300
  it( "2 channels mixing and request rtp server to send 2833 to one with dynamic payloadtype", async function() {
@@ -331,7 +362,7 @@ describe( "dtmf", function() {
331
362
  clienta.close()
332
363
  clientb.close()
333
364
 
334
- expect( dtmfpkcount ).to.equal( 3*6 )
365
+ expect( dtmfpkcount ).to.equal( 3*7 )
335
366
  } )
336
367
 
337
368
  it( "3 channels mixing and request rtp server to send 2833 to one", async function() {
@@ -341,11 +372,11 @@ describe( "dtmf", function() {
341
372
  const clientb = dgram.createSocket( "udp4" )
342
373
  const clientc = dgram.createSocket( "udp4" )
343
374
 
344
- let dtmfpkcount = 0
375
+ let dtmfpks = []
345
376
  clienta.on( "message", function( msg ) {
346
377
  const pk = parsepk( msg )
347
378
  if( 101 == pk.pt ) {
348
- dtmfpkcount++
379
+ dtmfpks.push( parse2833pk( msg ) )
349
380
  } else {
350
381
  expect( msg.length ).to.equal( 172 )
351
382
  expect( pk.pt ).to.equal( 0 )
@@ -355,7 +386,6 @@ describe( "dtmf", function() {
355
386
  clientb.on( "message", function( msg ) {
356
387
  if( 101 == ( 0x7f & msg [ 1 ] ) ) {
357
388
  expect( true ).to.equal( false ) //here = bad
358
- dtmfpkcount++
359
389
  }
360
390
  clientb.send( msg, channelb.local.port, "localhost" )
361
391
  } )
@@ -363,7 +393,6 @@ describe( "dtmf", function() {
363
393
  clientc.on( "message", function( msg ) {
364
394
  if( 101 == ( 0x7f & msg [ 1 ] ) ) {
365
395
  expect( true ).to.equal( false ) //here = bad
366
- dtmfpkcount++
367
396
  }
368
397
  clientb.send( msg, channelb.local.port, "localhost" )
369
398
  } )
@@ -407,14 +436,14 @@ describe( "dtmf", function() {
407
436
 
408
437
  await new Promise( ( resolve ) => { setTimeout( () => resolve(), 100 ) } )
409
438
  channela.dtmf( "*9ABD" )
410
- await new Promise( ( resolve ) => { setTimeout( () => resolve(), 900 ) } )
439
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1500 ) } )
411
440
  channela.close()
412
441
 
413
442
  clienta.close()
414
443
  clientb.close()
415
444
  clientc.close()
416
445
 
417
- expect( dtmfpkcount ).to.equal( 5*6 )
446
+ expect( dtmfpks.length ).to.equal( 5*7 )
418
447
 
419
448
  await finished
420
449
  } )
@@ -4,6 +4,7 @@
4
4
  const expect = require( "chai" ).expect
5
5
  const dgram = require( "dgram" )
6
6
  const projectrtp = require( "../../index.js" ).projectrtp
7
+ const fs = require( "node:fs" ).promises
7
8
 
8
9
  function sendpk( sn, sendtime, dstport, server, data = undefined, pt = 0, ssrc = 25 ) {
9
10
 
@@ -41,6 +42,14 @@ function sendpk( sn, sendtime, dstport, server, data = undefined, pt = 0, ssrc =
41
42
 
42
43
  describe( "channel mix", function() {
43
44
 
45
+ this.beforeAll( () => {
46
+ projectrtp.tone.generate( "400+450*0.5/0/400+450*0.5/0:400/200/400/2000", "/tmp/ukringing.wav" )
47
+ } )
48
+
49
+ this.afterAll( async () => {
50
+ await fs.unlink( "/tmp/ukringing.wav" )
51
+ } )
52
+
44
53
  it( "basic mix 2 channels", async function() {
45
54
 
46
55
  this.timeout( 3000 )
@@ -661,6 +670,75 @@ describe( "channel mix", function() {
661
670
 
662
671
  } )
663
672
 
673
+
674
+ it( "playback prompt then mix 2 channels - pcmu <-> g722 with recording", async function() {
675
+
676
+ this.timeout( 3000 )
677
+ this.slow( 2000 )
678
+
679
+ const endpointa = dgram.createSocket( "udp4" )
680
+ const endpointb = dgram.createSocket( "udp4" )
681
+
682
+ let endpointapkcount = 0
683
+ let endpointbpkcount = 0
684
+
685
+ endpointa.on( "message", function( msg ) {
686
+ endpointapkcount++
687
+ expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
688
+ } )
689
+
690
+ endpointb.on( "message", function( msg ) {
691
+
692
+ endpointbpkcount++
693
+ expect( 0x7f & msg [ 1 ] ).to.equal( 9 )
694
+ endpointb.send( msg, channelb.local.port, "localhost" )
695
+ } )
696
+
697
+ endpointa.bind()
698
+ await new Promise( ( resolve ) => { endpointa.on( "listening", function() { resolve() } ) } )
699
+
700
+ endpointb.bind()
701
+ await new Promise( ( resolve ) => { endpointb.on( "listening", function() { resolve() } ) } )
702
+
703
+ let done
704
+ const finished = new Promise( ( r ) => { done = r } )
705
+
706
+ const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointa.address().port, "codec": 0 } }, function( d ) {
707
+ if( "close" === d.action ) channelb.close()
708
+ } )
709
+
710
+ channela.play( { "loop": true, "files": [
711
+ { "wav": "/tmp/ukringing.wav" } ] } )
712
+
713
+ await new Promise( resolve => setTimeout( resolve, 500 ) )
714
+
715
+ const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointb.address().port, "codec": 9 } }, function( d ) {
716
+ if( "close" === d.action ) done()
717
+ } )
718
+
719
+ /* mix */
720
+ expect( channela.mix( channelb ) ).to.be.true
721
+
722
+ channela.record( { "file": "/tmp/g722mix2recording.wav" } )
723
+
724
+ /* Now, when we send UDP on endpointb it passes through our mix then arrives at endpointa */
725
+ for( let i = 0; 50 > i; i ++ ) {
726
+ sendpk( i, i, channela.local.port, endpointa )
727
+ }
728
+
729
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1500 ) } )
730
+
731
+ channela.close()
732
+ endpointa.close()
733
+ endpointb.close()
734
+
735
+ expect( endpointapkcount ).to.be.above( 30 )
736
+ expect( endpointbpkcount ).to.be.above( 30 )
737
+
738
+ await finished
739
+
740
+ } )
741
+
664
742
  it( "mix 3 channels - 1 writer 3 readers", async function() {
665
743
 
666
744
  this.timeout( 3000 )
@@ -470,7 +470,7 @@ describe( "record", function() {
470
470
  server.close()
471
471
 
472
472
  let stats = fs.statSync( "/tmp/dualrecordingpower.wav" )
473
- expect( stats.size ).to.be.within( 30000 , 40000 )
473
+ expect( stats.size ).to.be.within( 30000 , 41000 )
474
474
 
475
475
  stats = fs.statSync( "/tmp/dualrecording.wav" )
476
476
  expect( stats.size ).to.be.within( 110000, 190000 )