RTPencode.cc revision ee1879ca40ffe4af9bb9613e03eacc5c2c4881fc
1/* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11// TODO(hlundin): Reformat file to meet style guide. 12 13/* header includes */ 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#ifdef WIN32 18#include <winsock2.h> 19#endif 20#ifdef WEBRTC_LINUX 21#include <netinet/in.h> 22#endif 23 24#include <assert.h> 25 26#include <algorithm> 27 28#include "webrtc/typedefs.h" 29// needed for NetEqDecoder 30#include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" 31#include "webrtc/modules/audio_coding/neteq/include/neteq.h" 32 33/************************/ 34/* Define payload types */ 35/************************/ 36 37#include "PayloadTypes.h" 38 39/*********************/ 40/* Misc. definitions */ 41/*********************/ 42 43#define STOPSENDTIME 3000 44#define RESTARTSENDTIME 0 // 162500 45#define FIRSTLINELEN 40 46#define CHECK_NOT_NULL(a) \ 47 if ((a) == 0) { \ 48 printf("\n %s \n line: %d \nerror at %s\n", __FILE__, __LINE__, #a); \ 49 return (-1); \ 50 } 51 52//#define MULTIPLE_SAME_TIMESTAMP 53#define REPEAT_PACKET_DISTANCE 17 54#define REPEAT_PACKET_COUNT 1 // number of extra packets to send 55 56//#define INSERT_OLD_PACKETS 57#define OLD_PACKET 5 // how many seconds too old should the packet be? 58 59//#define TIMESTAMP_WRAPAROUND 60 61//#define RANDOM_DATA 62//#define RANDOM_PAYLOAD_DATA 63#define RANDOM_SEED 10 64 65//#define INSERT_DTMF_PACKETS 66//#define NO_DTMF_OVERDUB 67#define DTMF_PACKET_INTERVAL 2000 68#define DTMF_DURATION 500 69 70#define STEREO_MODE_FRAME 0 71#define STEREO_MODE_SAMPLE_1 1 // 1 octet per sample 72#define STEREO_MODE_SAMPLE_2 2 // 2 octets per sample 73 74/*************************/ 75/* Function declarations */ 76/*************************/ 77 78void NetEQTest_GetCodec_and_PT(char* name, 79 webrtc::NetEqDecoder* codec, 80 int* PT, 81 size_t frameLen, 82 int* fs, 83 int* bitrate, 84 int* useRed); 85int NetEQTest_init_coders(webrtc::NetEqDecoder coder, 86 size_t enc_frameSize, 87 int bitrate, 88 int sampfreq, 89 int vad, 90 size_t numChannels); 91void defineCodecs(webrtc::NetEqDecoder* usedCodec, int* noOfCodecs); 92int NetEQTest_free_coders(webrtc::NetEqDecoder coder, size_t numChannels); 93size_t NetEQTest_encode(webrtc::NetEqDecoder coder, 94 int16_t* indata, 95 size_t frameLen, 96 unsigned char* encoded, 97 int sampleRate, 98 int* vad, 99 int useVAD, 100 int bitrate, 101 size_t numChannels); 102void makeRTPheader(unsigned char* rtp_data, 103 int payloadType, 104 int seqNo, 105 uint32_t timestamp, 106 uint32_t ssrc); 107int makeRedundantHeader(unsigned char* rtp_data, 108 int* payloadType, 109 int numPayloads, 110 uint32_t* timestamp, 111 uint16_t* blockLen, 112 int seqNo, 113 uint32_t ssrc); 114size_t makeDTMFpayload(unsigned char* payload_data, 115 int Event, 116 int End, 117 int Volume, 118 int Duration); 119void stereoDeInterleave(int16_t* audioSamples, size_t numSamples); 120void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride); 121 122/*********************/ 123/* Codec definitions */ 124/*********************/ 125 126#include "webrtc_vad.h" 127 128#if ((defined CODEC_PCM16B) || (defined NETEQ_ARBITRARY_CODEC)) 129#include "pcm16b.h" 130#endif 131#ifdef CODEC_G711 132#include "g711_interface.h" 133#endif 134#ifdef CODEC_G729 135#include "G729Interface.h" 136#endif 137#ifdef CODEC_G729_1 138#include "G729_1Interface.h" 139#endif 140#ifdef CODEC_AMR 141#include "AMRInterface.h" 142#include "AMRCreation.h" 143#endif 144#ifdef CODEC_AMRWB 145#include "AMRWBInterface.h" 146#include "AMRWBCreation.h" 147#endif 148#ifdef CODEC_ILBC 149#include "ilbc.h" 150#endif 151#if (defined CODEC_ISAC || defined CODEC_ISAC_SWB) 152#include "isac.h" 153#endif 154#ifdef NETEQ_ISACFIX_CODEC 155#include "isacfix.h" 156#ifdef CODEC_ISAC 157#error Cannot have both ISAC and ISACfix defined. Please de-select one. 158#endif 159#endif 160#ifdef CODEC_G722 161#include "g722_interface.h" 162#endif 163#ifdef CODEC_G722_1_24 164#include "G722_1Interface.h" 165#endif 166#ifdef CODEC_G722_1_32 167#include "G722_1Interface.h" 168#endif 169#ifdef CODEC_G722_1_16 170#include "G722_1Interface.h" 171#endif 172#ifdef CODEC_G722_1C_24 173#include "G722_1Interface.h" 174#endif 175#ifdef CODEC_G722_1C_32 176#include "G722_1Interface.h" 177#endif 178#ifdef CODEC_G722_1C_48 179#include "G722_1Interface.h" 180#endif 181#ifdef CODEC_G726 182#include "G726Creation.h" 183#include "G726Interface.h" 184#endif 185#ifdef CODEC_GSMFR 186#include "GSMFRInterface.h" 187#include "GSMFRCreation.h" 188#endif 189#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 190 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 191#include "webrtc_cng.h" 192#endif 193#if ((defined CODEC_SPEEX_8) || (defined CODEC_SPEEX_16)) 194#include "SpeexInterface.h" 195#endif 196 197/***********************************/ 198/* Global codec instance variables */ 199/***********************************/ 200 201WebRtcVadInst* VAD_inst[2]; 202 203#ifdef CODEC_G722 204G722EncInst* g722EncState[2]; 205#endif 206 207#ifdef CODEC_G722_1_24 208G722_1_24_encinst_t* G722_1_24enc_inst[2]; 209#endif 210#ifdef CODEC_G722_1_32 211G722_1_32_encinst_t* G722_1_32enc_inst[2]; 212#endif 213#ifdef CODEC_G722_1_16 214G722_1_16_encinst_t* G722_1_16enc_inst[2]; 215#endif 216#ifdef CODEC_G722_1C_24 217G722_1C_24_encinst_t* G722_1C_24enc_inst[2]; 218#endif 219#ifdef CODEC_G722_1C_32 220G722_1C_32_encinst_t* G722_1C_32enc_inst[2]; 221#endif 222#ifdef CODEC_G722_1C_48 223G722_1C_48_encinst_t* G722_1C_48enc_inst[2]; 224#endif 225#ifdef CODEC_G726 226G726_encinst_t* G726enc_inst[2]; 227#endif 228#ifdef CODEC_G729 229G729_encinst_t* G729enc_inst[2]; 230#endif 231#ifdef CODEC_G729_1 232G729_1_inst_t* G729_1_inst[2]; 233#endif 234#ifdef CODEC_AMR 235AMR_encinst_t* AMRenc_inst[2]; 236int16_t AMR_bitrate; 237#endif 238#ifdef CODEC_AMRWB 239AMRWB_encinst_t* AMRWBenc_inst[2]; 240int16_t AMRWB_bitrate; 241#endif 242#ifdef CODEC_ILBC 243IlbcEncoderInstance* iLBCenc_inst[2]; 244#endif 245#ifdef CODEC_ISAC 246ISACStruct* ISAC_inst[2]; 247#endif 248#ifdef NETEQ_ISACFIX_CODEC 249ISACFIX_MainStruct* ISAC_inst[2]; 250#endif 251#ifdef CODEC_ISAC_SWB 252ISACStruct* ISACSWB_inst[2]; 253#endif 254#ifdef CODEC_GSMFR 255GSMFR_encinst_t* GSMFRenc_inst[2]; 256#endif 257#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 258 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 259CNG_enc_inst* CNGenc_inst[2]; 260#endif 261#ifdef CODEC_SPEEX_8 262SPEEX_encinst_t* SPEEX8enc_inst[2]; 263#endif 264#ifdef CODEC_SPEEX_16 265SPEEX_encinst_t* SPEEX16enc_inst[2]; 266#endif 267 268int main(int argc, char* argv[]) { 269 size_t packet_size; 270 int fs; 271 webrtc::NetEqDecoder usedCodec; 272 int payloadType; 273 int bitrate = 0; 274 int useVAD, vad; 275 int useRed = 0; 276 size_t len, enc_len; 277 int16_t org_data[4000]; 278 unsigned char rtp_data[8000]; 279 int16_t seqNo = 0xFFF; 280 uint32_t ssrc = 1235412312; 281 uint32_t timestamp = 0xAC1245; 282 uint16_t length, plen; 283 uint32_t offset; 284 double sendtime = 0; 285 int red_PT[2] = {0}; 286 uint32_t red_TS[2] = {0}; 287 uint16_t red_len[2] = {0}; 288 size_t RTPheaderLen = 12; 289 uint8_t red_data[8000]; 290#ifdef INSERT_OLD_PACKETS 291 uint16_t old_length, old_plen; 292 size_t old_enc_len; 293 int first_old_packet = 1; 294 unsigned char old_rtp_data[8000]; 295 size_t packet_age = 0; 296#endif 297#ifdef INSERT_DTMF_PACKETS 298 int NTone = 1; 299 int DTMFfirst = 1; 300 uint32_t DTMFtimestamp; 301 bool dtmfSent = false; 302#endif 303 bool usingStereo = false; 304 size_t stereoMode = 0; 305 size_t numChannels = 1; 306 307 /* check number of parameters */ 308 if ((argc != 6) && (argc != 7)) { 309 /* print help text and exit */ 310 printf("Application to encode speech into an RTP stream.\n"); 311 printf("The program reads a PCM file and encodes is using the specified " 312 "codec.\n"); 313 printf("The coded speech is packetized in RTP packest and written to the " 314 "output file.\n"); 315 printf("The format of the RTP stream file is simlilar to that of " 316 "rtpplay,\n"); 317 printf("but with the receive time euqal to 0 for all packets.\n"); 318 printf("Usage:\n\n"); 319 printf("%s PCMfile RTPfile frameLen codec useVAD bitrate\n", argv[0]); 320 printf("where:\n"); 321 322 printf("PCMfile : PCM speech input file\n\n"); 323 324 printf("RTPfile : RTP stream output file\n\n"); 325 326 printf("frameLen : 80...960... Number of samples per packet (limit " 327 "depends on codec)\n\n"); 328 329 printf("codecName\n"); 330#ifdef CODEC_PCM16B 331 printf(" : pcm16b 16 bit PCM (8kHz)\n"); 332#endif 333#ifdef CODEC_PCM16B_WB 334 printf(" : pcm16b_wb 16 bit PCM (16kHz)\n"); 335#endif 336#ifdef CODEC_PCM16B_32KHZ 337 printf(" : pcm16b_swb32 16 bit PCM (32kHz)\n"); 338#endif 339#ifdef CODEC_PCM16B_48KHZ 340 printf(" : pcm16b_swb48 16 bit PCM (48kHz)\n"); 341#endif 342#ifdef CODEC_G711 343 printf(" : pcma g711 A-law (8kHz)\n"); 344#endif 345#ifdef CODEC_G711 346 printf(" : pcmu g711 u-law (8kHz)\n"); 347#endif 348#ifdef CODEC_G729 349 printf(" : g729 G729 (8kHz and 8kbps) CELP (One-Three " 350 "frame(s)/packet)\n"); 351#endif 352#ifdef CODEC_G729_1 353 printf(" : g729.1 G729.1 (16kHz) variable rate (8--32 " 354 "kbps)\n"); 355#endif 356#ifdef CODEC_G722_1_16 357 printf(" : g722.1_16 G722.1 coder (16kHz) (g722.1 with " 358 "16kbps)\n"); 359#endif 360#ifdef CODEC_G722_1_24 361 printf(" : g722.1_24 G722.1 coder (16kHz) (the 24kbps " 362 "version)\n"); 363#endif 364#ifdef CODEC_G722_1_32 365 printf(" : g722.1_32 G722.1 coder (16kHz) (the 32kbps " 366 "version)\n"); 367#endif 368#ifdef CODEC_G722_1C_24 369 printf(" : g722.1C_24 G722.1 C coder (32kHz) (the 24kbps " 370 "version)\n"); 371#endif 372#ifdef CODEC_G722_1C_32 373 printf(" : g722.1C_32 G722.1 C coder (32kHz) (the 32kbps " 374 "version)\n"); 375#endif 376#ifdef CODEC_G722_1C_48 377 printf(" : g722.1C_48 G722.1 C coder (32kHz) (the 48kbps " 378 "version)\n"); 379#endif 380 381#ifdef CODEC_G726 382 printf(" : g726_16 G726 coder (8kHz) 16kbps\n"); 383 printf(" : g726_24 G726 coder (8kHz) 24kbps\n"); 384 printf(" : g726_32 G726 coder (8kHz) 32kbps\n"); 385 printf(" : g726_40 G726 coder (8kHz) 40kbps\n"); 386#endif 387#ifdef CODEC_AMR 388 printf(" : AMRXk Adaptive Multi Rate CELP codec " 389 "(8kHz)\n"); 390 printf(" X = 4.75, 5.15, 5.9, 6.7, 7.4, 7.95, " 391 "10.2 or 12.2\n"); 392#endif 393#ifdef CODEC_AMRWB 394 printf(" : AMRwbXk Adaptive Multi Rate Wideband CELP " 395 "codec (16kHz)\n"); 396 printf(" X = 7, 9, 12, 14, 16, 18, 20, 23 or " 397 "24\n"); 398#endif 399#ifdef CODEC_ILBC 400 printf(" : ilbc iLBC codec (8kHz and 13.8kbps)\n"); 401#endif 402#ifdef CODEC_ISAC 403 printf(" : isac iSAC (16kHz and 32.0 kbps). To set " 404 "rate specify a rate parameter as last parameter\n"); 405#endif 406#ifdef CODEC_ISAC_SWB 407 printf(" : isacswb iSAC SWB (32kHz and 32.0-52.0 kbps). " 408 "To set rate specify a rate parameter as last parameter\n"); 409#endif 410#ifdef CODEC_GSMFR 411 printf(" : gsmfr GSM FR codec (8kHz and 13kbps)\n"); 412#endif 413#ifdef CODEC_G722 414 printf(" : g722 g722 coder (16kHz) (the 64kbps " 415 "version)\n"); 416#endif 417#ifdef CODEC_SPEEX_8 418 printf(" : speex8 speex coder (8 kHz)\n"); 419#endif 420#ifdef CODEC_SPEEX_16 421 printf(" : speex16 speex coder (16 kHz)\n"); 422#endif 423#ifdef CODEC_RED 424#ifdef CODEC_G711 425 printf(" : red_pcm Redundancy RTP packet with 2*G711A " 426 "frames\n"); 427#endif 428#ifdef CODEC_ISAC 429 printf(" : red_isac Redundancy RTP packet with 2*iSAC " 430 "frames\n"); 431#endif 432#endif 433 printf("\n"); 434 435#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 436 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 437 printf("useVAD : 0 Voice Activity Detection is switched off\n"); 438 printf(" : 1 Voice Activity Detection is switched on\n\n"); 439#else 440 printf("useVAD : 0 Voice Activity Detection switched off (on not " 441 "supported)\n\n"); 442#endif 443 printf("bitrate : Codec bitrate in bps (only applies to vbr " 444 "codecs)\n\n"); 445 446 return (0); 447 } 448 449 FILE* in_file = fopen(argv[1], "rb"); 450 CHECK_NOT_NULL(in_file); 451 printf("Input file: %s\n", argv[1]); 452 FILE* out_file = fopen(argv[2], "wb"); 453 CHECK_NOT_NULL(out_file); 454 printf("Output file: %s\n\n", argv[2]); 455 int packet_size_int = atoi(argv[3]); 456 if (packet_size_int <= 0) { 457 printf("Packet size %d must be positive", packet_size_int); 458 return -1; 459 } 460 printf("Packet size: %d\n", packet_size_int); 461 packet_size = static_cast<size_t>(packet_size_int); 462 463 // check for stereo 464 if (argv[4][strlen(argv[4]) - 1] == '*') { 465 // use stereo 466 usingStereo = true; 467 numChannels = 2; 468 argv[4][strlen(argv[4]) - 1] = '\0'; 469 } 470 471 NetEQTest_GetCodec_and_PT(argv[4], &usedCodec, &payloadType, packet_size, &fs, 472 &bitrate, &useRed); 473 474 if (useRed) { 475 RTPheaderLen = 12 + 4 + 1; /* standard RTP = 12; 4 bytes per redundant 476 payload, except last one which is 1 byte */ 477 } 478 479 useVAD = atoi(argv[5]); 480#if !(defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 481 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 482 if (useVAD != 0) { 483 printf("Error: this simulation does not support VAD/DTX/CNG\n"); 484 } 485#endif 486 487 // check stereo type 488 if (usingStereo) { 489 switch (usedCodec) { 490 // sample based codecs 491 case webrtc::NetEqDecoder::kDecoderPCMu: 492 case webrtc::NetEqDecoder::kDecoderPCMa: 493 case webrtc::NetEqDecoder::kDecoderG722: { 494 // 1 octet per sample 495 stereoMode = STEREO_MODE_SAMPLE_1; 496 break; 497 } 498 case webrtc::NetEqDecoder::kDecoderPCM16B: 499 case webrtc::NetEqDecoder::kDecoderPCM16Bwb: 500 case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz: 501 case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz: { 502 // 2 octets per sample 503 stereoMode = STEREO_MODE_SAMPLE_2; 504 break; 505 } 506 507 // fixed-rate frame codecs (with internal VAD) 508 default: { 509 printf("Cannot use codec %s as stereo codec\n", argv[4]); 510 exit(0); 511 } 512 } 513 } 514 515 if ((usedCodec == webrtc::NetEqDecoder::kDecoderISAC) || 516 (usedCodec == webrtc::NetEqDecoder::kDecoderISACswb)) { 517 if (argc != 7) { 518 if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) { 519 bitrate = 32000; 520 printf("Running iSAC at default bitrate of 32000 bps (to specify " 521 "explicitly add the bps as last parameter)\n"); 522 } else // (usedCodec==webrtc::kDecoderISACswb) 523 { 524 bitrate = 56000; 525 printf("Running iSAC at default bitrate of 56000 bps (to specify " 526 "explicitly add the bps as last parameter)\n"); 527 } 528 } else { 529 bitrate = atoi(argv[6]); 530 if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) { 531 if ((bitrate < 10000) || (bitrate > 32000)) { 532 printf("Error: iSAC bitrate must be between 10000 and 32000 bps (%i " 533 "is invalid)\n", bitrate); 534 exit(0); 535 } 536 printf("Running iSAC at bitrate of %i bps\n", bitrate); 537 } else // (usedCodec==webrtc::kDecoderISACswb) 538 { 539 if ((bitrate < 32000) || (bitrate > 56000)) { 540 printf("Error: iSAC SWB bitrate must be between 32000 and 56000 bps " 541 "(%i is invalid)\n", bitrate); 542 exit(0); 543 } 544 } 545 } 546 } else { 547 if (argc == 7) { 548 printf("Error: Bitrate parameter can only be specified for iSAC, G.723, " 549 "and G.729.1\n"); 550 exit(0); 551 } 552 } 553 554 if (useRed) { 555 printf("Redundancy engaged. "); 556 } 557 printf("Used codec: %i\n", static_cast<int>(usedCodec)); 558 printf("Payload type: %i\n", payloadType); 559 560 NetEQTest_init_coders(usedCodec, packet_size, bitrate, fs, useVAD, 561 numChannels); 562 563 /* write file header */ 564 // fprintf(out_file, "#!RTPencode%s\n", "1.0"); 565 fprintf(out_file, "#!rtpplay%s \n", 566 "1.0"); // this is the string that rtpplay needs 567 uint32_t dummy_variable = 0; // should be converted to network endian format, 568 // but does not matter when 0 569 if (fwrite(&dummy_variable, 4, 1, out_file) != 1) { 570 return -1; 571 } 572 if (fwrite(&dummy_variable, 4, 1, out_file) != 1) { 573 return -1; 574 } 575 if (fwrite(&dummy_variable, 4, 1, out_file) != 1) { 576 return -1; 577 } 578 if (fwrite(&dummy_variable, 2, 1, out_file) != 1) { 579 return -1; 580 } 581 if (fwrite(&dummy_variable, 2, 1, out_file) != 1) { 582 return -1; 583 } 584 585#ifdef TIMESTAMP_WRAPAROUND 586 timestamp = 0xFFFFFFFF - fs * 10; /* should give wrap-around in 10 seconds */ 587#endif 588#if defined(RANDOM_DATA) | defined(RANDOM_PAYLOAD_DATA) 589 srand(RANDOM_SEED); 590#endif 591 592 /* if redundancy is used, the first redundant payload is zero length */ 593 red_len[0] = 0; 594 595 /* read first frame */ 596 len = fread(org_data, 2, packet_size * numChannels, in_file) / numChannels; 597 598 /* de-interleave if stereo */ 599 if (usingStereo) { 600 stereoDeInterleave(org_data, len * numChannels); 601 } 602 603 while (len == packet_size) { 604#ifdef INSERT_DTMF_PACKETS 605 dtmfSent = false; 606 607 if (sendtime >= NTone * DTMF_PACKET_INTERVAL) { 608 if (sendtime < NTone * DTMF_PACKET_INTERVAL + DTMF_DURATION) { 609 // tone has not ended 610 if (DTMFfirst == 1) { 611 DTMFtimestamp = timestamp; // save this timestamp 612 DTMFfirst = 0; 613 } 614 makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, seqNo, DTMFtimestamp, ssrc); 615 enc_len = makeDTMFpayload( 616 &rtp_data[12], NTone % 12, 0, 4, 617 (int)(sendtime - NTone * DTMF_PACKET_INTERVAL) * (fs / 1000) + len); 618 } else { 619 // tone has ended 620 makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, seqNo, DTMFtimestamp, ssrc); 621 enc_len = makeDTMFpayload(&rtp_data[12], NTone % 12, 1, 4, 622 DTMF_DURATION * (fs / 1000)); 623 NTone++; 624 DTMFfirst = 1; 625 } 626 627 /* write RTP packet to file */ 628 length = htons(static_cast<unsigned short>(12 + enc_len + 8)); 629 plen = htons(static_cast<unsigned short>(12 + enc_len)); 630 offset = (uint32_t)sendtime; //(timestamp/(fs/1000)); 631 offset = htonl(offset); 632 if (fwrite(&length, 2, 1, out_file) != 1) { 633 return -1; 634 } 635 if (fwrite(&plen, 2, 1, out_file) != 1) { 636 return -1; 637 } 638 if (fwrite(&offset, 4, 1, out_file) != 1) { 639 return -1; 640 } 641 if (fwrite(rtp_data, 12 + enc_len, 1, out_file) != 1) { 642 return -1; 643 } 644 645 dtmfSent = true; 646 } 647#endif 648 649#ifdef NO_DTMF_OVERDUB 650 /* If DTMF is sent, we should not send any speech packets during the same 651 * time */ 652 if (dtmfSent) { 653 enc_len = 0; 654 } else { 655#endif 656 /* encode frame */ 657 enc_len = 658 NetEQTest_encode(usedCodec, org_data, packet_size, &rtp_data[12], fs, 659 &vad, useVAD, bitrate, numChannels); 660 661 if (usingStereo && stereoMode != STEREO_MODE_FRAME && vad == 1) { 662 // interleave the encoded payload for sample-based codecs (not for CNG) 663 stereoInterleave(&rtp_data[12], enc_len, stereoMode); 664 } 665#ifdef NO_DTMF_OVERDUB 666 } 667#endif 668 669 if (enc_len > 0 && 670 (sendtime <= STOPSENDTIME || sendtime > RESTARTSENDTIME)) { 671 if (useRed) { 672 if (red_len[0] > 0) { 673 memmove(&rtp_data[RTPheaderLen + red_len[0]], &rtp_data[12], enc_len); 674 memcpy(&rtp_data[RTPheaderLen], red_data, red_len[0]); 675 676 red_len[1] = static_cast<uint16_t>(enc_len); 677 red_TS[1] = timestamp; 678 if (vad) 679 red_PT[1] = payloadType; 680 else 681 red_PT[1] = NETEQ_CODEC_CN_PT; 682 683 makeRedundantHeader(rtp_data, red_PT, 2, red_TS, red_len, seqNo++, 684 ssrc); 685 686 enc_len += red_len[0] + RTPheaderLen - 12; 687 } else { // do not use redundancy payload for this packet, i.e., only 688 // last payload 689 memmove(&rtp_data[RTPheaderLen - 4], &rtp_data[12], enc_len); 690 // memcpy(&rtp_data[RTPheaderLen], red_data, red_len[0]); 691 692 red_len[1] = static_cast<uint16_t>(enc_len); 693 red_TS[1] = timestamp; 694 if (vad) 695 red_PT[1] = payloadType; 696 else 697 red_PT[1] = NETEQ_CODEC_CN_PT; 698 699 makeRedundantHeader(rtp_data, red_PT, 2, red_TS, red_len, seqNo++, 700 ssrc); 701 702 enc_len += red_len[0] + RTPheaderLen - 4 - 703 12; // 4 is length of redundancy header (not used) 704 } 705 } else { 706 /* make RTP header */ 707 if (vad) // regular speech data 708 makeRTPheader(rtp_data, payloadType, seqNo++, timestamp, ssrc); 709 else // CNG data 710 makeRTPheader(rtp_data, NETEQ_CODEC_CN_PT, seqNo++, timestamp, ssrc); 711 } 712#ifdef MULTIPLE_SAME_TIMESTAMP 713 int mult_pack = 0; 714 do { 715#endif // MULTIPLE_SAME_TIMESTAMP 716 /* write RTP packet to file */ 717 length = htons(static_cast<unsigned short>(12 + enc_len + 8)); 718 plen = htons(static_cast<unsigned short>(12 + enc_len)); 719 offset = (uint32_t)sendtime; 720 //(timestamp/(fs/1000)); 721 offset = htonl(offset); 722 if (fwrite(&length, 2, 1, out_file) != 1) { 723 return -1; 724 } 725 if (fwrite(&plen, 2, 1, out_file) != 1) { 726 return -1; 727 } 728 if (fwrite(&offset, 4, 1, out_file) != 1) { 729 return -1; 730 } 731#ifdef RANDOM_DATA 732 for (size_t k = 0; k < 12 + enc_len; k++) { 733 rtp_data[k] = rand() + rand(); 734 } 735#endif 736#ifdef RANDOM_PAYLOAD_DATA 737 for (size_t k = 12; k < 12 + enc_len; k++) { 738 rtp_data[k] = rand() + rand(); 739 } 740#endif 741 if (fwrite(rtp_data, 12 + enc_len, 1, out_file) != 1) { 742 return -1; 743 } 744#ifdef MULTIPLE_SAME_TIMESTAMP 745 } while ((seqNo % REPEAT_PACKET_DISTANCE == 0) && 746 (mult_pack++ < REPEAT_PACKET_COUNT)); 747#endif // MULTIPLE_SAME_TIMESTAMP 748 749#ifdef INSERT_OLD_PACKETS 750 if (packet_age >= OLD_PACKET * fs) { 751 if (!first_old_packet) { 752 // send the old packet 753 if (fwrite(&old_length, 2, 1, out_file) != 1) { 754 return -1; 755 } 756 if (fwrite(&old_plen, 2, 1, out_file) != 1) { 757 return -1; 758 } 759 if (fwrite(&offset, 4, 1, out_file) != 1) { 760 return -1; 761 } 762 if (fwrite(old_rtp_data, 12 + old_enc_len, 1, out_file) != 1) { 763 return -1; 764 } 765 } 766 // store current packet as old 767 old_length = length; 768 old_plen = plen; 769 memcpy(old_rtp_data, rtp_data, 12 + enc_len); 770 old_enc_len = enc_len; 771 first_old_packet = 0; 772 packet_age = 0; 773 } 774 packet_age += packet_size; 775#endif 776 777 if (useRed) { 778/* move data to redundancy store */ 779#ifdef CODEC_ISAC 780 if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) { 781 assert(!usingStereo); // Cannot handle stereo yet 782 red_len[0] = WebRtcIsac_GetRedPayload(ISAC_inst[0], red_data); 783 } else { 784#endif 785 memcpy(red_data, &rtp_data[RTPheaderLen + red_len[0]], enc_len); 786 red_len[0] = red_len[1]; 787#ifdef CODEC_ISAC 788 } 789#endif 790 red_TS[0] = red_TS[1]; 791 red_PT[0] = red_PT[1]; 792 } 793 } 794 795 /* read next frame */ 796 len = fread(org_data, 2, packet_size * numChannels, in_file) / numChannels; 797 /* de-interleave if stereo */ 798 if (usingStereo) { 799 stereoDeInterleave(org_data, len * numChannels); 800 } 801 802 if (payloadType == NETEQ_CODEC_G722_PT) 803 timestamp += len >> 1; 804 else 805 timestamp += len; 806 807 sendtime += (double)len / (fs / 1000); 808 } 809 810 NetEQTest_free_coders(usedCodec, numChannels); 811 fclose(in_file); 812 fclose(out_file); 813 printf("Done!\n"); 814 815 return (0); 816} 817 818/****************/ 819/* Subfunctions */ 820/****************/ 821 822void NetEQTest_GetCodec_and_PT(char* name, 823 webrtc::NetEqDecoder* codec, 824 int* PT, 825 size_t frameLen, 826 int* fs, 827 int* bitrate, 828 int* useRed) { 829 *bitrate = 0; /* Default bitrate setting */ 830 *useRed = 0; /* Default no redundancy */ 831 832 if (!strcmp(name, "pcmu")) { 833 *codec = webrtc::NetEqDecoder::kDecoderPCMu; 834 *PT = NETEQ_CODEC_PCMU_PT; 835 *fs = 8000; 836 } else if (!strcmp(name, "pcma")) { 837 *codec = webrtc::NetEqDecoder::kDecoderPCMa; 838 *PT = NETEQ_CODEC_PCMA_PT; 839 *fs = 8000; 840 } else if (!strcmp(name, "pcm16b")) { 841 *codec = webrtc::NetEqDecoder::kDecoderPCM16B; 842 *PT = NETEQ_CODEC_PCM16B_PT; 843 *fs = 8000; 844 } else if (!strcmp(name, "pcm16b_wb")) { 845 *codec = webrtc::NetEqDecoder::kDecoderPCM16Bwb; 846 *PT = NETEQ_CODEC_PCM16B_WB_PT; 847 *fs = 16000; 848 } else if (!strcmp(name, "pcm16b_swb32")) { 849 *codec = webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz; 850 *PT = NETEQ_CODEC_PCM16B_SWB32KHZ_PT; 851 *fs = 32000; 852 } else if (!strcmp(name, "pcm16b_swb48")) { 853 *codec = webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz; 854 *PT = NETEQ_CODEC_PCM16B_SWB48KHZ_PT; 855 *fs = 48000; 856 } else if (!strcmp(name, "g722")) { 857 *codec = webrtc::NetEqDecoder::kDecoderG722; 858 *PT = NETEQ_CODEC_G722_PT; 859 *fs = 16000; 860 } else if ((!strcmp(name, "ilbc")) && 861 ((frameLen % 240 == 0) || (frameLen % 160 == 0))) { 862 *fs = 8000; 863 *codec = webrtc::NetEqDecoder::kDecoderILBC; 864 *PT = NETEQ_CODEC_ILBC_PT; 865 } else if (!strcmp(name, "isac")) { 866 *fs = 16000; 867 *codec = webrtc::NetEqDecoder::kDecoderISAC; 868 *PT = NETEQ_CODEC_ISAC_PT; 869 } else if (!strcmp(name, "isacswb")) { 870 *fs = 32000; 871 *codec = webrtc::NetEqDecoder::kDecoderISACswb; 872 *PT = NETEQ_CODEC_ISACSWB_PT; 873 } else if (!strcmp(name, "red_pcm")) { 874 *codec = webrtc::NetEqDecoder::kDecoderPCMa; 875 *PT = NETEQ_CODEC_PCMA_PT; /* this will be the PT for the sub-headers */ 876 *fs = 8000; 877 *useRed = 1; 878 } else if (!strcmp(name, "red_isac")) { 879 *codec = webrtc::NetEqDecoder::kDecoderISAC; 880 *PT = NETEQ_CODEC_ISAC_PT; /* this will be the PT for the sub-headers */ 881 *fs = 16000; 882 *useRed = 1; 883 } else { 884 printf("Error: Not a supported codec (%s)\n", name); 885 exit(0); 886 } 887} 888 889int NetEQTest_init_coders(webrtc::NetEqDecoder coder, 890 size_t enc_frameSize, 891 int bitrate, 892 int sampfreq, 893 int vad, 894 size_t numChannels) { 895 int ok = 0; 896 897 for (size_t k = 0; k < numChannels; k++) { 898 VAD_inst[k] = WebRtcVad_Create(); 899 if (!VAD_inst[k]) { 900 printf("Error: Couldn't allocate memory for VAD instance\n"); 901 exit(0); 902 } 903 ok = WebRtcVad_Init(VAD_inst[k]); 904 if (ok == -1) { 905 printf("Error: Initialization of VAD struct failed\n"); 906 exit(0); 907 } 908 909#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 910 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 911 ok = WebRtcCng_CreateEnc(&CNGenc_inst[k]); 912 if (ok != 0) { 913 printf("Error: Couldn't allocate memory for CNG encoding instance\n"); 914 exit(0); 915 } 916 if (sampfreq <= 16000) { 917 ok = WebRtcCng_InitEnc(CNGenc_inst[k], sampfreq, 200, 5); 918 if (ok == -1) { 919 printf("Error: Initialization of CNG struct failed. Error code %d\n", 920 WebRtcCng_GetErrorCodeEnc(CNGenc_inst[k])); 921 exit(0); 922 } 923 } 924#endif 925 926 switch (coder) { 927#ifdef CODEC_PCM16B 928 case webrtc::NetEqDecoder::kDecoderPCM16B: 929#endif 930#ifdef CODEC_PCM16B_WB 931 case webrtc::NetEqDecoder::kDecoderPCM16Bwb: 932#endif 933#ifdef CODEC_PCM16B_32KHZ 934 case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz: 935#endif 936#ifdef CODEC_PCM16B_48KHZ 937 case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz: 938#endif 939#ifdef CODEC_G711 940 case webrtc::NetEqDecoder::kDecoderPCMu: 941 case webrtc::NetEqDecoder::kDecoderPCMa: 942#endif 943 // do nothing 944 break; 945#ifdef CODEC_G729 946 case webrtc::kDecoderG729: 947 if (sampfreq == 8000) { 948 if ((enc_frameSize == 80) || (enc_frameSize == 160) || 949 (enc_frameSize == 240) || (enc_frameSize == 320) || 950 (enc_frameSize == 400) || (enc_frameSize == 480)) { 951 ok = WebRtcG729_CreateEnc(&G729enc_inst[k]); 952 if (ok != 0) { 953 printf("Error: Couldn't allocate memory for G729 encoding " 954 "instance\n"); 955 exit(0); 956 } 957 } else { 958 printf("\nError: g729 only supports 10, 20, 30, 40, 50 or 60 " 959 "ms!!\n\n"); 960 exit(0); 961 } 962 WebRtcG729_EncoderInit(G729enc_inst[k], vad); 963 if ((vad == 1) && (enc_frameSize != 80)) { 964 printf("\nError - This simulation only supports VAD for G729 at " 965 "10ms packets (not %" PRIuS "ms)\n", (enc_frameSize >> 3)); 966 } 967 } else { 968 printf("\nError - g729 is only developed for 8kHz \n"); 969 exit(0); 970 } 971 break; 972#endif 973#ifdef CODEC_G729_1 974 case webrtc::kDecoderG729_1: 975 if (sampfreq == 16000) { 976 if ((enc_frameSize == 320) || (enc_frameSize == 640) || 977 (enc_frameSize == 960)) { 978 ok = WebRtcG7291_Create(&G729_1_inst[k]); 979 if (ok != 0) { 980 printf("Error: Couldn't allocate memory for G.729.1 codec " 981 "instance\n"); 982 exit(0); 983 } 984 } else { 985 printf("\nError: G.729.1 only supports 20, 40 or 60 ms!!\n\n"); 986 exit(0); 987 } 988 if (!(((bitrate >= 12000) && (bitrate <= 32000) && 989 (bitrate % 2000 == 0)) || 990 (bitrate == 8000))) { 991 /* must be 8, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, or 32 kbps */ 992 printf("\nError: G.729.1 bitrate must be 8000 or 12000--32000 in " 993 "steps of 2000 bps\n"); 994 exit(0); 995 } 996 WebRtcG7291_EncoderInit(G729_1_inst[k], bitrate, 0 /* flag8kHz*/, 997 0 /*flagG729mode*/); 998 } else { 999 printf("\nError - G.729.1 input is always 16 kHz \n"); 1000 exit(0); 1001 } 1002 break; 1003#endif 1004#ifdef CODEC_SPEEX_8 1005 case webrtc::kDecoderSPEEX_8: 1006 if (sampfreq == 8000) { 1007 if ((enc_frameSize == 160) || (enc_frameSize == 320) || 1008 (enc_frameSize == 480)) { 1009 ok = WebRtcSpeex_CreateEnc(&SPEEX8enc_inst[k], sampfreq); 1010 if (ok != 0) { 1011 printf("Error: Couldn't allocate memory for Speex encoding " 1012 "instance\n"); 1013 exit(0); 1014 } 1015 } else { 1016 printf("\nError: Speex only supports 20, 40, and 60 ms!!\n\n"); 1017 exit(0); 1018 } 1019 if ((vad == 1) && (enc_frameSize != 160)) { 1020 printf("\nError - This simulation only supports VAD for Speex at " 1021 "20ms packets (not %" PRIuS "ms)\n", 1022 (enc_frameSize >> 3)); 1023 vad = 0; 1024 } 1025 ok = WebRtcSpeex_EncoderInit(SPEEX8enc_inst[k], 0 /*vbr*/, 1026 3 /*complexity*/, vad); 1027 if (ok != 0) 1028 exit(0); 1029 } else { 1030 printf("\nError - Speex8 called with sample frequency other than 8 " 1031 "kHz.\n\n"); 1032 } 1033 break; 1034#endif 1035#ifdef CODEC_SPEEX_16 1036 case webrtc::kDecoderSPEEX_16: 1037 if (sampfreq == 16000) { 1038 if ((enc_frameSize == 320) || (enc_frameSize == 640) || 1039 (enc_frameSize == 960)) { 1040 ok = WebRtcSpeex_CreateEnc(&SPEEX16enc_inst[k], sampfreq); 1041 if (ok != 0) { 1042 printf("Error: Couldn't allocate memory for Speex encoding " 1043 "instance\n"); 1044 exit(0); 1045 } 1046 } else { 1047 printf("\nError: Speex only supports 20, 40, and 60 ms!!\n\n"); 1048 exit(0); 1049 } 1050 if ((vad == 1) && (enc_frameSize != 320)) { 1051 printf("\nError - This simulation only supports VAD for Speex at " 1052 "20ms packets (not %" PRIuS "ms)\n", 1053 (enc_frameSize >> 4)); 1054 vad = 0; 1055 } 1056 ok = WebRtcSpeex_EncoderInit(SPEEX16enc_inst[k], 0 /*vbr*/, 1057 3 /*complexity*/, vad); 1058 if (ok != 0) 1059 exit(0); 1060 } else { 1061 printf("\nError - Speex16 called with sample frequency other than 16 " 1062 "kHz.\n\n"); 1063 } 1064 break; 1065#endif 1066 1067#ifdef CODEC_G722_1_16 1068 case webrtc::kDecoderG722_1_16: 1069 if (sampfreq == 16000) { 1070 ok = WebRtcG7221_CreateEnc16(&G722_1_16enc_inst[k]); 1071 if (ok != 0) { 1072 printf("Error: Couldn't allocate memory for G.722.1 instance\n"); 1073 exit(0); 1074 } 1075 if (enc_frameSize == 320) { 1076 } else { 1077 printf("\nError: G722.1 only supports 20 ms!!\n\n"); 1078 exit(0); 1079 } 1080 WebRtcG7221_EncoderInit16((G722_1_16_encinst_t*)G722_1_16enc_inst[k]); 1081 } else { 1082 printf("\nError - G722.1 is only developed for 16kHz \n"); 1083 exit(0); 1084 } 1085 break; 1086#endif 1087#ifdef CODEC_G722_1_24 1088 case webrtc::kDecoderG722_1_24: 1089 if (sampfreq == 16000) { 1090 ok = WebRtcG7221_CreateEnc24(&G722_1_24enc_inst[k]); 1091 if (ok != 0) { 1092 printf("Error: Couldn't allocate memory for G.722.1 instance\n"); 1093 exit(0); 1094 } 1095 if (enc_frameSize == 320) { 1096 } else { 1097 printf("\nError: G722.1 only supports 20 ms!!\n\n"); 1098 exit(0); 1099 } 1100 WebRtcG7221_EncoderInit24((G722_1_24_encinst_t*)G722_1_24enc_inst[k]); 1101 } else { 1102 printf("\nError - G722.1 is only developed for 16kHz \n"); 1103 exit(0); 1104 } 1105 break; 1106#endif 1107#ifdef CODEC_G722_1_32 1108 case webrtc::kDecoderG722_1_32: 1109 if (sampfreq == 16000) { 1110 ok = WebRtcG7221_CreateEnc32(&G722_1_32enc_inst[k]); 1111 if (ok != 0) { 1112 printf("Error: Couldn't allocate memory for G.722.1 instance\n"); 1113 exit(0); 1114 } 1115 if (enc_frameSize == 320) { 1116 } else { 1117 printf("\nError: G722.1 only supports 20 ms!!\n\n"); 1118 exit(0); 1119 } 1120 WebRtcG7221_EncoderInit32((G722_1_32_encinst_t*)G722_1_32enc_inst[k]); 1121 } else { 1122 printf("\nError - G722.1 is only developed for 16kHz \n"); 1123 exit(0); 1124 } 1125 break; 1126#endif 1127#ifdef CODEC_G722_1C_24 1128 case webrtc::kDecoderG722_1C_24: 1129 if (sampfreq == 32000) { 1130 ok = WebRtcG7221C_CreateEnc24(&G722_1C_24enc_inst[k]); 1131 if (ok != 0) { 1132 printf("Error: Couldn't allocate memory for G.722.1C instance\n"); 1133 exit(0); 1134 } 1135 if (enc_frameSize == 640) { 1136 } else { 1137 printf("\nError: G722.1 C only supports 20 ms!!\n\n"); 1138 exit(0); 1139 } 1140 WebRtcG7221C_EncoderInit24( 1141 (G722_1C_24_encinst_t*)G722_1C_24enc_inst[k]); 1142 } else { 1143 printf("\nError - G722.1 C is only developed for 32kHz \n"); 1144 exit(0); 1145 } 1146 break; 1147#endif 1148#ifdef CODEC_G722_1C_32 1149 case webrtc::kDecoderG722_1C_32: 1150 if (sampfreq == 32000) { 1151 ok = WebRtcG7221C_CreateEnc32(&G722_1C_32enc_inst[k]); 1152 if (ok != 0) { 1153 printf("Error: Couldn't allocate memory for G.722.1C instance\n"); 1154 exit(0); 1155 } 1156 if (enc_frameSize == 640) { 1157 } else { 1158 printf("\nError: G722.1 C only supports 20 ms!!\n\n"); 1159 exit(0); 1160 } 1161 WebRtcG7221C_EncoderInit32( 1162 (G722_1C_32_encinst_t*)G722_1C_32enc_inst[k]); 1163 } else { 1164 printf("\nError - G722.1 C is only developed for 32kHz \n"); 1165 exit(0); 1166 } 1167 break; 1168#endif 1169#ifdef CODEC_G722_1C_48 1170 case webrtc::kDecoderG722_1C_48: 1171 if (sampfreq == 32000) { 1172 ok = WebRtcG7221C_CreateEnc48(&G722_1C_48enc_inst[k]); 1173 if (ok != 0) { 1174 printf("Error: Couldn't allocate memory for G.722.1C instance\n"); 1175 exit(0); 1176 } 1177 if (enc_frameSize == 640) { 1178 } else { 1179 printf("\nError: G722.1 C only supports 20 ms!!\n\n"); 1180 exit(0); 1181 } 1182 WebRtcG7221C_EncoderInit48( 1183 (G722_1C_48_encinst_t*)G722_1C_48enc_inst[k]); 1184 } else { 1185 printf("\nError - G722.1 C is only developed for 32kHz \n"); 1186 exit(0); 1187 } 1188 break; 1189#endif 1190#ifdef CODEC_G722 1191 case webrtc::NetEqDecoder::kDecoderG722: 1192 if (sampfreq == 16000) { 1193 if (enc_frameSize % 2 == 0) { 1194 } else { 1195 printf( 1196 "\nError - g722 frames must have an even number of " 1197 "enc_frameSize\n"); 1198 exit(0); 1199 } 1200 WebRtcG722_CreateEncoder(&g722EncState[k]); 1201 WebRtcG722_EncoderInit(g722EncState[k]); 1202 } else { 1203 printf("\nError - g722 is only developed for 16kHz \n"); 1204 exit(0); 1205 } 1206 break; 1207#endif 1208#ifdef CODEC_AMR 1209 case webrtc::kDecoderAMR: 1210 if (sampfreq == 8000) { 1211 ok = WebRtcAmr_CreateEnc(&AMRenc_inst[k]); 1212 if (ok != 0) { 1213 printf( 1214 "Error: Couldn't allocate memory for AMR encoding instance\n"); 1215 exit(0); 1216 } 1217 if ((enc_frameSize == 160) || (enc_frameSize == 320) || 1218 (enc_frameSize == 480)) { 1219 } else { 1220 printf("\nError - AMR must have a multiple of 160 enc_frameSize\n"); 1221 exit(0); 1222 } 1223 WebRtcAmr_EncoderInit(AMRenc_inst[k], vad); 1224 WebRtcAmr_EncodeBitmode(AMRenc_inst[k], AMRBandwidthEfficient); 1225 AMR_bitrate = bitrate; 1226 } else { 1227 printf("\nError - AMR is only developed for 8kHz \n"); 1228 exit(0); 1229 } 1230 break; 1231#endif 1232#ifdef CODEC_AMRWB 1233 case webrtc::kDecoderAMRWB: 1234 if (sampfreq == 16000) { 1235 ok = WebRtcAmrWb_CreateEnc(&AMRWBenc_inst[k]); 1236 if (ok != 0) { 1237 printf("Error: Couldn't allocate memory for AMRWB encoding " 1238 "instance\n"); 1239 exit(0); 1240 } 1241 if (((enc_frameSize / 320) > 3) || ((enc_frameSize % 320) != 0)) { 1242 printf("\nError - AMRwb must have frameSize of 20, 40 or 60ms\n"); 1243 exit(0); 1244 } 1245 WebRtcAmrWb_EncoderInit(AMRWBenc_inst[k], vad); 1246 if (bitrate == 7000) { 1247 AMRWB_bitrate = AMRWB_MODE_7k; 1248 } else if (bitrate == 9000) { 1249 AMRWB_bitrate = AMRWB_MODE_9k; 1250 } else if (bitrate == 12000) { 1251 AMRWB_bitrate = AMRWB_MODE_12k; 1252 } else if (bitrate == 14000) { 1253 AMRWB_bitrate = AMRWB_MODE_14k; 1254 } else if (bitrate == 16000) { 1255 AMRWB_bitrate = AMRWB_MODE_16k; 1256 } else if (bitrate == 18000) { 1257 AMRWB_bitrate = AMRWB_MODE_18k; 1258 } else if (bitrate == 20000) { 1259 AMRWB_bitrate = AMRWB_MODE_20k; 1260 } else if (bitrate == 23000) { 1261 AMRWB_bitrate = AMRWB_MODE_23k; 1262 } else if (bitrate == 24000) { 1263 AMRWB_bitrate = AMRWB_MODE_24k; 1264 } 1265 WebRtcAmrWb_EncodeBitmode(AMRWBenc_inst[k], AMRBandwidthEfficient); 1266 1267 } else { 1268 printf("\nError - AMRwb is only developed for 16kHz \n"); 1269 exit(0); 1270 } 1271 break; 1272#endif 1273#ifdef CODEC_ILBC 1274 case webrtc::NetEqDecoder::kDecoderILBC: 1275 if (sampfreq == 8000) { 1276 ok = WebRtcIlbcfix_EncoderCreate(&iLBCenc_inst[k]); 1277 if (ok != 0) { 1278 printf("Error: Couldn't allocate memory for iLBC encoding " 1279 "instance\n"); 1280 exit(0); 1281 } 1282 if ((enc_frameSize == 160) || (enc_frameSize == 240) || 1283 (enc_frameSize == 320) || (enc_frameSize == 480)) { 1284 } else { 1285 printf("\nError - iLBC only supports 160, 240, 320 and 480 " 1286 "enc_frameSize (20, 30, 40 and 60 ms)\n"); 1287 exit(0); 1288 } 1289 if ((enc_frameSize == 160) || (enc_frameSize == 320)) { 1290 /* 20 ms version */ 1291 WebRtcIlbcfix_EncoderInit(iLBCenc_inst[k], 20); 1292 } else { 1293 /* 30 ms version */ 1294 WebRtcIlbcfix_EncoderInit(iLBCenc_inst[k], 30); 1295 } 1296 } else { 1297 printf("\nError - iLBC is only developed for 8kHz \n"); 1298 exit(0); 1299 } 1300 break; 1301#endif 1302#ifdef CODEC_ISAC 1303 case webrtc::NetEqDecoder::kDecoderISAC: 1304 if (sampfreq == 16000) { 1305 ok = WebRtcIsac_Create(&ISAC_inst[k]); 1306 if (ok != 0) { 1307 printf("Error: Couldn't allocate memory for iSAC instance\n"); 1308 exit(0); 1309 } 1310 if ((enc_frameSize == 480) || (enc_frameSize == 960)) { 1311 } else { 1312 printf("\nError - iSAC only supports frameSize (30 and 60 ms)\n"); 1313 exit(0); 1314 } 1315 WebRtcIsac_EncoderInit(ISAC_inst[k], 1); 1316 if ((bitrate < 10000) || (bitrate > 32000)) { 1317 printf("\nError - iSAC bitrate has to be between 10000 and 32000 " 1318 "bps (not %i)\n", 1319 bitrate); 1320 exit(0); 1321 } 1322 WebRtcIsac_Control(ISAC_inst[k], bitrate, 1323 static_cast<int>(enc_frameSize >> 4)); 1324 } else { 1325 printf("\nError - iSAC only supports 480 or 960 enc_frameSize (30 or " 1326 "60 ms)\n"); 1327 exit(0); 1328 } 1329 break; 1330#endif 1331#ifdef NETEQ_ISACFIX_CODEC 1332 case webrtc::kDecoderISAC: 1333 if (sampfreq == 16000) { 1334 ok = WebRtcIsacfix_Create(&ISAC_inst[k]); 1335 if (ok != 0) { 1336 printf("Error: Couldn't allocate memory for iSAC instance\n"); 1337 exit(0); 1338 } 1339 if ((enc_frameSize == 480) || (enc_frameSize == 960)) { 1340 } else { 1341 printf("\nError - iSAC only supports frameSize (30 and 60 ms)\n"); 1342 exit(0); 1343 } 1344 WebRtcIsacfix_EncoderInit(ISAC_inst[k], 1); 1345 if ((bitrate < 10000) || (bitrate > 32000)) { 1346 printf("\nError - iSAC bitrate has to be between 10000 and 32000 " 1347 "bps (not %i)\n", bitrate); 1348 exit(0); 1349 } 1350 WebRtcIsacfix_Control(ISAC_inst[k], bitrate, enc_frameSize >> 4); 1351 } else { 1352 printf("\nError - iSAC only supports 480 or 960 enc_frameSize (30 or " 1353 "60 ms)\n"); 1354 exit(0); 1355 } 1356 break; 1357#endif 1358#ifdef CODEC_ISAC_SWB 1359 case webrtc::NetEqDecoder::kDecoderISACswb: 1360 if (sampfreq == 32000) { 1361 ok = WebRtcIsac_Create(&ISACSWB_inst[k]); 1362 if (ok != 0) { 1363 printf("Error: Couldn't allocate memory for iSAC SWB instance\n"); 1364 exit(0); 1365 } 1366 if (enc_frameSize == 960) { 1367 } else { 1368 printf("\nError - iSAC SWB only supports frameSize 30 ms\n"); 1369 exit(0); 1370 } 1371 ok = WebRtcIsac_SetEncSampRate(ISACSWB_inst[k], 32000); 1372 if (ok != 0) { 1373 printf("Error: Couldn't set sample rate for iSAC SWB instance\n"); 1374 exit(0); 1375 } 1376 WebRtcIsac_EncoderInit(ISACSWB_inst[k], 1); 1377 if ((bitrate < 32000) || (bitrate > 56000)) { 1378 printf("\nError - iSAC SWB bitrate has to be between 32000 and " 1379 "56000 bps (not %i)\n", bitrate); 1380 exit(0); 1381 } 1382 WebRtcIsac_Control(ISACSWB_inst[k], bitrate, 1383 static_cast<int>(enc_frameSize >> 5)); 1384 } else { 1385 printf("\nError - iSAC SWB only supports 960 enc_frameSize (30 " 1386 "ms)\n"); 1387 exit(0); 1388 } 1389 break; 1390#endif 1391#ifdef CODEC_GSMFR 1392 case webrtc::kDecoderGSMFR: 1393 if (sampfreq == 8000) { 1394 ok = WebRtcGSMFR_CreateEnc(&GSMFRenc_inst[k]); 1395 if (ok != 0) { 1396 printf("Error: Couldn't allocate memory for GSM FR encoding " 1397 "instance\n"); 1398 exit(0); 1399 } 1400 if ((enc_frameSize == 160) || (enc_frameSize == 320) || 1401 (enc_frameSize == 480)) { 1402 } else { 1403 printf("\nError - GSM FR must have a multiple of 160 " 1404 "enc_frameSize\n"); 1405 exit(0); 1406 } 1407 WebRtcGSMFR_EncoderInit(GSMFRenc_inst[k], 0); 1408 } else { 1409 printf("\nError - GSM FR is only developed for 8kHz \n"); 1410 exit(0); 1411 } 1412 break; 1413#endif 1414 default: 1415 printf("Error: unknown codec in call to NetEQTest_init_coders.\n"); 1416 exit(0); 1417 break; 1418 } 1419 1420 if (ok != 0) { 1421 return (ok); 1422 } 1423 } // end for 1424 1425 return (0); 1426} 1427 1428int NetEQTest_free_coders(webrtc::NetEqDecoder coder, size_t numChannels) { 1429 for (size_t k = 0; k < numChannels; k++) { 1430 WebRtcVad_Free(VAD_inst[k]); 1431#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ 1432 defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) 1433 WebRtcCng_FreeEnc(CNGenc_inst[k]); 1434#endif 1435 1436 switch (coder) { 1437#ifdef CODEC_PCM16B 1438 case webrtc::NetEqDecoder::kDecoderPCM16B: 1439#endif 1440#ifdef CODEC_PCM16B_WB 1441 case webrtc::NetEqDecoder::kDecoderPCM16Bwb: 1442#endif 1443#ifdef CODEC_PCM16B_32KHZ 1444 case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz: 1445#endif 1446#ifdef CODEC_PCM16B_48KHZ 1447 case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz: 1448#endif 1449#ifdef CODEC_G711 1450 case webrtc::NetEqDecoder::kDecoderPCMu: 1451 case webrtc::NetEqDecoder::kDecoderPCMa: 1452#endif 1453 // do nothing 1454 break; 1455#ifdef CODEC_G729 1456 case webrtc::NetEqDecoder::kDecoderG729: 1457 WebRtcG729_FreeEnc(G729enc_inst[k]); 1458 break; 1459#endif 1460#ifdef CODEC_G729_1 1461 case webrtc::NetEqDecoder::kDecoderG729_1: 1462 WebRtcG7291_Free(G729_1_inst[k]); 1463 break; 1464#endif 1465#ifdef CODEC_SPEEX_8 1466 case webrtc::NetEqDecoder::kDecoderSPEEX_8: 1467 WebRtcSpeex_FreeEnc(SPEEX8enc_inst[k]); 1468 break; 1469#endif 1470#ifdef CODEC_SPEEX_16 1471 case webrtc::NetEqDecoder::kDecoderSPEEX_16: 1472 WebRtcSpeex_FreeEnc(SPEEX16enc_inst[k]); 1473 break; 1474#endif 1475 1476#ifdef CODEC_G722_1_16 1477 case webrtc::NetEqDecoder::kDecoderG722_1_16: 1478 WebRtcG7221_FreeEnc16(G722_1_16enc_inst[k]); 1479 break; 1480#endif 1481#ifdef CODEC_G722_1_24 1482 case webrtc::NetEqDecoder::kDecoderG722_1_24: 1483 WebRtcG7221_FreeEnc24(G722_1_24enc_inst[k]); 1484 break; 1485#endif 1486#ifdef CODEC_G722_1_32 1487 case webrtc::NetEqDecoder::kDecoderG722_1_32: 1488 WebRtcG7221_FreeEnc32(G722_1_32enc_inst[k]); 1489 break; 1490#endif 1491#ifdef CODEC_G722_1C_24 1492 case webrtc::NetEqDecoder::kDecoderG722_1C_24: 1493 WebRtcG7221C_FreeEnc24(G722_1C_24enc_inst[k]); 1494 break; 1495#endif 1496#ifdef CODEC_G722_1C_32 1497 case webrtc::NetEqDecoder::kDecoderG722_1C_32: 1498 WebRtcG7221C_FreeEnc32(G722_1C_32enc_inst[k]); 1499 break; 1500#endif 1501#ifdef CODEC_G722_1C_48 1502 case webrtc::NetEqDecoder::kDecoderG722_1C_48: 1503 WebRtcG7221C_FreeEnc48(G722_1C_48enc_inst[k]); 1504 break; 1505#endif 1506#ifdef CODEC_G722 1507 case webrtc::NetEqDecoder::kDecoderG722: 1508 WebRtcG722_FreeEncoder(g722EncState[k]); 1509 break; 1510#endif 1511#ifdef CODEC_AMR 1512 case webrtc::NetEqDecoder::kDecoderAMR: 1513 WebRtcAmr_FreeEnc(AMRenc_inst[k]); 1514 break; 1515#endif 1516#ifdef CODEC_AMRWB 1517 case webrtc::NetEqDecoder::kDecoderAMRWB: 1518 WebRtcAmrWb_FreeEnc(AMRWBenc_inst[k]); 1519 break; 1520#endif 1521#ifdef CODEC_ILBC 1522 case webrtc::NetEqDecoder::kDecoderILBC: 1523 WebRtcIlbcfix_EncoderFree(iLBCenc_inst[k]); 1524 break; 1525#endif 1526#ifdef CODEC_ISAC 1527 case webrtc::NetEqDecoder::kDecoderISAC: 1528 WebRtcIsac_Free(ISAC_inst[k]); 1529 break; 1530#endif 1531#ifdef NETEQ_ISACFIX_CODEC 1532 case webrtc::NetEqDecoder::kDecoderISAC: 1533 WebRtcIsacfix_Free(ISAC_inst[k]); 1534 break; 1535#endif 1536#ifdef CODEC_ISAC_SWB 1537 case webrtc::NetEqDecoder::kDecoderISACswb: 1538 WebRtcIsac_Free(ISACSWB_inst[k]); 1539 break; 1540#endif 1541#ifdef CODEC_GSMFR 1542 case webrtc::NetEqDecoder::kDecoderGSMFR: 1543 WebRtcGSMFR_FreeEnc(GSMFRenc_inst[k]); 1544 break; 1545#endif 1546 default: 1547 printf("Error: unknown codec in call to NetEQTest_init_coders.\n"); 1548 exit(0); 1549 break; 1550 } 1551 } 1552 1553 return (0); 1554} 1555 1556size_t NetEQTest_encode(webrtc::NetEqDecoder coder, 1557 int16_t* indata, 1558 size_t frameLen, 1559 unsigned char* encoded, 1560 int sampleRate, 1561 int* vad, 1562 int useVAD, 1563 int bitrate, 1564 size_t numChannels) { 1565 size_t cdlen = 0; 1566 int16_t* tempdata; 1567 static int first_cng = 1; 1568 size_t tempLen; 1569 *vad = 1; 1570 1571 // check VAD first 1572 if (useVAD) { 1573 *vad = 0; 1574 1575 size_t sampleRate_10 = static_cast<size_t>(10 * sampleRate / 1000); 1576 size_t sampleRate_20 = static_cast<size_t>(20 * sampleRate / 1000); 1577 size_t sampleRate_30 = static_cast<size_t>(30 * sampleRate / 1000); 1578 for (size_t k = 0; k < numChannels; k++) { 1579 tempLen = frameLen; 1580 tempdata = &indata[k * frameLen]; 1581 int localVad = 0; 1582 /* Partition the signal and test each chunk for VAD. 1583 All chunks must be VAD=0 to produce a total VAD=0. */ 1584 while (tempLen >= sampleRate_10) { 1585 if ((tempLen % sampleRate_30) == 0) { // tempLen is multiple of 30ms 1586 localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata, 1587 sampleRate_30); 1588 tempdata += sampleRate_30; 1589 tempLen -= sampleRate_30; 1590 } else if (tempLen >= sampleRate_20) { // tempLen >= 20ms 1591 localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata, 1592 sampleRate_20); 1593 tempdata += sampleRate_20; 1594 tempLen -= sampleRate_20; 1595 } else { // use 10ms 1596 localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata, 1597 sampleRate_10); 1598 tempdata += sampleRate_10; 1599 tempLen -= sampleRate_10; 1600 } 1601 } 1602 1603 // aggregate all VAD decisions over all channels 1604 *vad |= localVad; 1605 } 1606 1607 if (!*vad) { 1608 // all channels are silent 1609 cdlen = 0; 1610 for (size_t k = 0; k < numChannels; k++) { 1611 WebRtcCng_Encode(CNGenc_inst[k], &indata[k * frameLen], 1612 (frameLen <= 640 ? frameLen : 640) /* max 640 */, 1613 encoded, &tempLen, first_cng); 1614 encoded += tempLen; 1615 cdlen += tempLen; 1616 } 1617 *vad = 0; 1618 first_cng = 0; 1619 return (cdlen); 1620 } 1621 } 1622 1623 // loop over all channels 1624 size_t totalLen = 0; 1625 1626 for (size_t k = 0; k < numChannels; k++) { 1627 /* Encode with the selected coder type */ 1628 if (coder == webrtc::NetEqDecoder::kDecoderPCMu) { /*g711 u-law */ 1629#ifdef CODEC_G711 1630 cdlen = WebRtcG711_EncodeU(indata, frameLen, encoded); 1631#endif 1632 } else if (coder == webrtc::NetEqDecoder::kDecoderPCMa) { /*g711 A-law */ 1633#ifdef CODEC_G711 1634 cdlen = WebRtcG711_EncodeA(indata, frameLen, encoded); 1635 } 1636#endif 1637#ifdef CODEC_PCM16B 1638 else if ((coder == webrtc::NetEqDecoder::kDecoderPCM16B) || 1639 (coder == webrtc::NetEqDecoder::kDecoderPCM16Bwb) || 1640 (coder == webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz) || 1641 (coder == webrtc::NetEqDecoder:: 1642 kDecoderPCM16Bswb48kHz)) { /*pcm16b (8kHz, 16kHz, 1643 32kHz or 48kHz) */ 1644 cdlen = WebRtcPcm16b_Encode(indata, frameLen, encoded); 1645 } 1646#endif 1647#ifdef CODEC_G722 1648 else if (coder == webrtc::NetEqDecoder::kDecoderG722) { /*g722 */ 1649 cdlen = WebRtcG722_Encode(g722EncState[k], indata, frameLen, encoded); 1650 assert(cdlen == frameLen >> 1); 1651 } 1652#endif 1653#ifdef CODEC_ILBC 1654 else if (coder == webrtc::NetEqDecoder::kDecoderILBC) { /*iLBC */ 1655 cdlen = static_cast<size_t>(std::max( 1656 WebRtcIlbcfix_Encode(iLBCenc_inst[k], indata, frameLen, encoded), 0)); 1657 } 1658#endif 1659#if (defined(CODEC_ISAC) || \ 1660 defined(NETEQ_ISACFIX_CODEC)) // TODO(hlundin): remove all 1661 // NETEQ_ISACFIX_CODEC 1662 else if (coder == webrtc::NetEqDecoder::kDecoderISAC) { /*iSAC */ 1663 int noOfCalls = 0; 1664 int res = 0; 1665 while (res <= 0) { 1666#ifdef CODEC_ISAC /* floating point */ 1667 res = 1668 WebRtcIsac_Encode(ISAC_inst[k], &indata[noOfCalls * 160], encoded); 1669#else /* fixed point */ 1670 res = WebRtcIsacfix_Encode(ISAC_inst[k], &indata[noOfCalls * 160], 1671 encoded); 1672#endif 1673 noOfCalls++; 1674 } 1675 cdlen = static_cast<size_t>(res); 1676 } 1677#endif 1678#ifdef CODEC_ISAC_SWB 1679 else if (coder == webrtc::NetEqDecoder::kDecoderISACswb) { /* iSAC SWB */ 1680 int noOfCalls = 0; 1681 int res = 0; 1682 while (res <= 0) { 1683 res = WebRtcIsac_Encode(ISACSWB_inst[k], &indata[noOfCalls * 320], 1684 encoded); 1685 noOfCalls++; 1686 } 1687 cdlen = static_cast<size_t>(res); 1688 } 1689#endif 1690 indata += frameLen; 1691 encoded += cdlen; 1692 totalLen += cdlen; 1693 1694 } // end for 1695 1696 first_cng = 1; 1697 return (totalLen); 1698} 1699 1700void makeRTPheader(unsigned char* rtp_data, 1701 int payloadType, 1702 int seqNo, 1703 uint32_t timestamp, 1704 uint32_t ssrc) { 1705 rtp_data[0] = 0x80; 1706 rtp_data[1] = payloadType & 0xFF; 1707 rtp_data[2] = (seqNo >> 8) & 0xFF; 1708 rtp_data[3] = seqNo & 0xFF; 1709 rtp_data[4] = timestamp >> 24; 1710 rtp_data[5] = (timestamp >> 16) & 0xFF; 1711 rtp_data[6] = (timestamp >> 8) & 0xFF; 1712 rtp_data[7] = timestamp & 0xFF; 1713 rtp_data[8] = ssrc >> 24; 1714 rtp_data[9] = (ssrc >> 16) & 0xFF; 1715 rtp_data[10] = (ssrc >> 8) & 0xFF; 1716 rtp_data[11] = ssrc & 0xFF; 1717} 1718 1719int makeRedundantHeader(unsigned char* rtp_data, 1720 int* payloadType, 1721 int numPayloads, 1722 uint32_t* timestamp, 1723 uint16_t* blockLen, 1724 int seqNo, 1725 uint32_t ssrc) { 1726 int i; 1727 unsigned char* rtpPointer; 1728 uint16_t offset; 1729 1730 /* first create "standard" RTP header */ 1731 makeRTPheader(rtp_data, NETEQ_CODEC_RED_PT, seqNo, timestamp[numPayloads - 1], 1732 ssrc); 1733 1734 rtpPointer = &rtp_data[12]; 1735 1736 /* add one sub-header for each redundant payload (not the primary) */ 1737 for (i = 0; i < numPayloads - 1; i++) { 1738 if (blockLen[i] > 0) { 1739 offset = static_cast<uint16_t>(timestamp[numPayloads - 1] - timestamp[i]); 1740 1741 // Byte |0| |1 2 | 3 | 1742 // Bit |0|1234567|01234567012345|6701234567| 1743 // |F|payload| timestamp | block | 1744 // | | type | offset | length | 1745 rtpPointer[0] = (payloadType[i] & 0x7F) | 0x80; 1746 rtpPointer[1] = (offset >> 6) & 0xFF; 1747 rtpPointer[2] = ((offset & 0x3F) << 2) | ((blockLen[i] >> 8) & 0x03); 1748 rtpPointer[3] = blockLen[i] & 0xFF; 1749 1750 rtpPointer += 4; 1751 } 1752 } 1753 1754 // Bit |0|1234567| 1755 // |0|payload| 1756 // | | type | 1757 rtpPointer[0] = payloadType[numPayloads - 1] & 0x7F; 1758 ++rtpPointer; 1759 1760 return rtpPointer - rtp_data; // length of header in bytes 1761} 1762 1763size_t makeDTMFpayload(unsigned char* payload_data, 1764 int Event, 1765 int End, 1766 int Volume, 1767 int Duration) { 1768 unsigned char E, R, V; 1769 R = 0; 1770 V = (unsigned char)Volume; 1771 if (End == 0) { 1772 E = 0x00; 1773 } else { 1774 E = 0x80; 1775 } 1776 payload_data[0] = (unsigned char)Event; 1777 payload_data[1] = (unsigned char)(E | R | V); 1778 // Duration equals 8 times time_ms, default is 8000 Hz. 1779 payload_data[2] = (unsigned char)((Duration >> 8) & 0xFF); 1780 payload_data[3] = (unsigned char)(Duration & 0xFF); 1781 return (4); 1782} 1783 1784void stereoDeInterleave(int16_t* audioSamples, size_t numSamples) { 1785 int16_t* tempVec; 1786 int16_t* readPtr, *writeL, *writeR; 1787 1788 if (numSamples == 0) 1789 return; 1790 1791 tempVec = (int16_t*)malloc(sizeof(int16_t) * numSamples); 1792 if (tempVec == NULL) { 1793 printf("Error allocating memory\n"); 1794 exit(0); 1795 } 1796 1797 memcpy(tempVec, audioSamples, numSamples * sizeof(int16_t)); 1798 1799 writeL = audioSamples; 1800 writeR = &audioSamples[numSamples / 2]; 1801 readPtr = tempVec; 1802 1803 for (size_t k = 0; k < numSamples; k += 2) { 1804 *writeL = *readPtr; 1805 readPtr++; 1806 *writeR = *readPtr; 1807 readPtr++; 1808 writeL++; 1809 writeR++; 1810 } 1811 1812 free(tempVec); 1813} 1814 1815void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride) { 1816 unsigned char* ptrL, *ptrR; 1817 unsigned char temp[10]; 1818 1819 if (stride > 10) { 1820 exit(0); 1821 } 1822 1823 if (dataLen % 1 != 0) { 1824 // must be even number of samples 1825 printf("Error: cannot interleave odd sample number\n"); 1826 exit(0); 1827 } 1828 1829 ptrL = data + stride; 1830 ptrR = &data[dataLen / 2]; 1831 1832 while (ptrL < ptrR) { 1833 // copy from right pointer to temp 1834 memcpy(temp, ptrR, stride); 1835 1836 // shift data between pointers 1837 memmove(ptrL + stride, ptrL, ptrR - ptrL); 1838 1839 // copy from temp to left pointer 1840 memcpy(ptrL, temp, stride); 1841 1842 // advance pointers 1843 ptrL += stride * 2; 1844 ptrR += stride; 1845 } 1846} 1847