blob: 2791db4512b274055f83d16a6365ae443672dd4f [file] [log] [blame]
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
Stand Alone test application for ISACFIX and ISAC LC
******************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "typedefs.h"
#include "isacfix.h"
ISACFIX_MainStruct *ISACfix_inst;
#define FS 16000
typedef struct {
WebRtc_UWord32 arrival_time; /* samples */
WebRtc_UWord32 sample_count; /* samples */
WebRtc_UWord16 rtp_number;
} BottleNeckModel;
void get_arrival_time(int current_framesamples, /* samples */
int packet_size, /* bytes */
int bottleneck, /* excluding headers; bits/s */
BottleNeckModel *BN_data)
{
const int HeaderSize = 35;
int HeaderRate;
HeaderRate = HeaderSize * 8 * FS / current_framesamples; /* bits/s */
/* everything in samples */
BN_data->sample_count = BN_data->sample_count + current_framesamples;
BN_data->arrival_time += ((packet_size + HeaderSize) * 8 * FS) / (bottleneck + HeaderRate);
if (BN_data->arrival_time < BN_data->sample_count)
BN_data->arrival_time = BN_data->sample_count;
BN_data->rtp_number++;
}
/*
#ifdef __cplusplus
extern "C" {
#endif
*/
int main(int argc, char* argv[]){
/* Parameters */
FILE *pInFile, *pOutFile, *pChcFile;
WebRtc_Word8 inFile[40];
WebRtc_Word8 outFile[40];
WebRtc_Word8 chcFile[40];
WebRtc_Word8 codec[10];
WebRtc_Word16 bitrt, spType, size;
WebRtc_UWord16 frameLen;
WebRtc_Word16 sigOut[1000], sigIn[1000];
WebRtc_UWord16 bitStream[500]; /* double to 32 kbps for 60 ms */
WebRtc_Word16 chc, ok;
int noOfCalls, cdlen;
WebRtc_Word16 noOfLostFrames;
int err, errtype;
BottleNeckModel BN_data;
int totalbits =0;
int totalsmpls =0;
/*End Parameters*/
if ((argc==6)||(argc==7) ){
strcpy(codec,argv[5]);
if(argc==7){
if (!_stricmp("isac",codec)){
bitrt = atoi(argv[6]);
if ( (bitrt<10000)&&(bitrt>32000)){
printf("Error: Supported bit rate in the range 10000-32000 bps!\n");
exit(-1);
}
}else{
printf("Error: Codec not recognized. Check spelling!\n");
exit(-1);
}
} else {
printf("Error: Codec not recognized. Check spelling!\n");
exit(-1);
}
} else {
printf("Error: Wrong number of input parameter!\n\n");
exit(-1);
}
frameLen = atoi(argv[4]);
strcpy(chcFile,argv[3]);
strcpy(outFile,argv[2]);
strcpy(inFile,argv[1]);
/* Open file streams */
if( (pInFile = fopen(inFile,"rb")) == NULL ) {
printf( "Error: Did not find input file!\n" );
exit(-1);
}
strcat(outFile,"_");
strcat(outFile, argv[4]);
strcat(outFile,"_");
strcat(outFile, codec);
if (argc==7){
strcat(outFile,"_");
strcat(outFile, argv[6]);
}
if (_stricmp("none", chcFile)){
strcat(outFile,"_");
strcat(outFile, "plc");
}
strcat(outFile, ".otp");
if (_stricmp("none", chcFile)){
if( (pChcFile = fopen(chcFile,"rb")) == NULL ) {
printf( "Error: Did not find channel file!\n" );
exit(-1);
}
}
/******************************************************************/
if (!_stricmp("isac", codec)){ /* ISAC */
if ((frameLen!=480)&&(frameLen!=960)) {
printf("Error: ISAC only supports 480 and 960 samples per frame (not %d)\n", frameLen);
exit(-1);
}
if( (pOutFile = fopen(outFile,"wb")) == NULL ) {
printf( "Could not open output file!\n" );
exit(-1);
}
ok=WebRtcIsacfix_Create(&ISACfix_inst);
if (ok!=0) {
printf("Couldn't allocate memory for iSAC fix instance\n");
exit(-1);
}
BN_data.arrival_time = 0;
BN_data.sample_count = 0;
BN_data.rtp_number = 0;
WebRtcIsacfix_EncoderInit(ISACfix_inst,1);
WebRtcIsacfix_DecoderInit(ISACfix_inst);
err = WebRtcIsacfix_Control(ISACfix_inst, bitrt, (frameLen>>4));
if (err < 0) {
/* exit if returned with error */
errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
printf("\n\n Error in initialization: %d.\n\n", errtype);
exit(EXIT_FAILURE);
}
/* loop over frame */
while (fread(sigIn,sizeof(WebRtc_Word16),frameLen,pInFile) == frameLen) {
noOfCalls=0;
cdlen=0;
while (cdlen<=0) {
cdlen=WebRtcIsacfix_Encode(ISACfix_inst,&sigIn[noOfCalls*160],(WebRtc_Word16*)bitStream);
if(cdlen==-1){
errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
printf("\n\nError in encoder: %d.\n\n", errtype);
exit(-1);
}
noOfCalls++;
}
if(_stricmp("none", chcFile)){
if (fread(&chc,sizeof(WebRtc_Word16),1,pChcFile)!=1) /* packet may be lost */
break;
} else {
chc = 1; /* packets never lost */
}
/* simulate packet handling through NetEq and the modem */
get_arrival_time(frameLen, cdlen, bitrt, &BN_data);
if (chc){ /* decode */
err = WebRtcIsacfix_UpdateBwEstimate1(ISACfix_inst,
bitStream,
cdlen,
BN_data.rtp_number,
BN_data.arrival_time);
if (err < 0) {
/* exit if returned with error */
errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
printf("\n\nError in decoder: %d.\n\n", errtype);
exit(EXIT_FAILURE);
}
size = WebRtcIsacfix_Decode(ISACfix_inst, bitStream, cdlen, sigOut, &spType);
if(size<=0){
/* exit if returned with error */
errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
printf("\n\nError in decoder: %d.\n\n", errtype);
exit(-1);
}
} else { /* PLC */
if (frameLen == 480){
noOfLostFrames = 1;
} else{
noOfLostFrames = 2;
}
size = WebRtcIsacfix_DecodePlc(ISACfix_inst, sigOut, noOfLostFrames );
if(size<=0){
errtype=WebRtcIsacfix_GetErrorCode(ISACfix_inst);
printf("\n\nError in decoder: %d.\n\n", errtype);
exit(-1);
}
}
/* Write decoded speech to file */
fwrite(sigOut,sizeof(short),size,pOutFile);
totalbits += 8 * cdlen;
totalsmpls += size;
}
/******************************************************************/
}
// printf("\n\ntotal bits = %d bits", totalbits);
printf("\nmeasured average bitrate = %0.3f kbits/s", (double)totalbits * 16 / totalsmpls);
printf("\n");
fclose(pInFile);
fclose(pOutFile);
if (_stricmp("none", chcFile)){
fclose(pChcFile);
}
if (!_stricmp("isac", codec)){
WebRtcIsacfix_Free(ISACfix_inst);
}
return 0;
}