forked from Mirrors/freeswitch
749114b704
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@12095 d0543943-73ff-0310-b7d9-9358b9ac24b2
352 lines
11 KiB
C
352 lines
11 KiB
C
/*
|
|
* iLBC - a library for the iLBC codec
|
|
*
|
|
* ilbc_tests.c - Test the iLBC low bit rate speech codec.
|
|
*
|
|
* Adapted by Steve Underwood <steveu@coppice.org> from the reference
|
|
* iLBC code supplied in RFC3951.
|
|
*
|
|
* Copyright (C) The Internet Society (2004).
|
|
* All Rights Reserved.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* $Id: ilbc_tests.c,v 1.1.1.1 2008/02/15 12:15:55 steveu Exp $
|
|
*/
|
|
|
|
/*! \file */
|
|
|
|
/*! \page ilbc_tests_page iLBC codec tests
|
|
\section ilbc_tests_page_sec_1 What does it do?
|
|
|
|
\section ilbc_tests_page_sec_2 How is it used?
|
|
To perform a general audio quality test, ilbc_tests should be run. The file ../localtests/short_nb_voice.wav
|
|
will be compressed to iLBC data, decompressed, and the resulting audio stored in post_ilbc.wav.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
#include <time.h>
|
|
#include <audiofile.h>
|
|
|
|
#include "ilbc.h"
|
|
|
|
#define IN_FILE_NAME "../localtests/dam9.wav"
|
|
#define REF_FILE_NAME "../localtests/dam9_lpc55.wav"
|
|
#define COMPRESS_FILE_NAME "lpc10_out.lpc10"
|
|
#define DECOMPRESS_FILE_NAME "lpc10_in.lpc10"
|
|
#define OUT_FILE_NAME "post_lpc10.wav"
|
|
|
|
#define SAMPLE_RATE 8000
|
|
|
|
/*---------------------------------------------------------------*
|
|
* Main program to test iLBC encoding and decoding
|
|
*
|
|
* Usage:
|
|
* exefile_name.exe <infile> <bytefile> <outfile> <channel>
|
|
*
|
|
* <infile> : Input file, speech for encoder (16-bit PCM file)
|
|
* <bytefile> : Bit stream output from the encoder
|
|
* <outfile> : Output file, decoded speech (16-bit PCM file)
|
|
* <channel> : Bit error file, optional (16-bit)
|
|
* 1 - Packet received correctly
|
|
* 0 - Packet Lost
|
|
*--------------------------------------------------------------*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
AFfilehandle inhandle;
|
|
AFfilehandle refhandle;
|
|
AFfilehandle outhandle;
|
|
AFfilesetup filesetup;
|
|
int frames;
|
|
int outframes;
|
|
int compress_file;
|
|
int decompress_file;
|
|
float x;
|
|
|
|
float starttime;
|
|
float runtime;
|
|
float outtime;
|
|
FILE *ifileid;
|
|
FILE *efileid;
|
|
FILE *ofileid;
|
|
FILE *cfileid;
|
|
int16_t data[ILBC_BLOCK_LEN_MAX];
|
|
uint8_t encoded_data[ILBC_NO_OF_BYTES_MAX];
|
|
int16_t decoded_data[ILBC_BLOCK_LEN_MAX];
|
|
int len;
|
|
int16_t pli;
|
|
int16_t mode;
|
|
int blockcount = 0;
|
|
int packetlosscount = 0;
|
|
|
|
/* Create structs */
|
|
ilbc_encode_state_t Enc_Inst;
|
|
ilbc_decode_state_t Dec_Inst;
|
|
|
|
compress_file = -1;
|
|
decompress_file = -1;
|
|
inhandle = AF_NULL_FILEHANDLE;
|
|
refhandle = AF_NULL_FILEHANDLE;
|
|
outhandle = AF_NULL_FILEHANDLE;
|
|
#if 0
|
|
if (!decompress)
|
|
{
|
|
if ((inhandle = afOpenFile(in_file_name, "r", 0)) == AF_NULL_FILEHANDLE)
|
|
{
|
|
fprintf(stderr, " Cannot open wave file '%s'\n", in_file_name);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
|
|
{
|
|
fprintf(stderr, " Unexpected frame size in wave file '%s'\n", in_file_name);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
|
|
{
|
|
fprintf(stderr, " Unexpected sample rate in wave file '%s'\n", in_file_name);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0)
|
|
{
|
|
fprintf(stderr, " Unexpected number of channels in wave file '%s'\n", in_file_name);
|
|
exit(2);
|
|
}
|
|
if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
|
|
{
|
|
fprintf(stderr, " Failed to create file setup\n");
|
|
exit(2);
|
|
}
|
|
|
|
if ((refhandle = afOpenFile(REF_FILE_NAME, "r", 0)) == AF_NULL_FILEHANDLE)
|
|
{
|
|
fprintf(stderr, " Cannot open wave file '%s'\n", REF_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetFrameSize(refhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
|
|
{
|
|
fprintf(stderr, " Unexpected frame size in wave file '%s'\n", REF_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetRate(refhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
|
|
{
|
|
fprintf(stderr, " Unexpected sample rate in wave file '%s'\n", REF_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
if ((x = afGetChannels(refhandle, AF_DEFAULT_TRACK)) != 1.0)
|
|
{
|
|
fprintf(stderr, " Unexpected number of channels in wave file '%s'\n", REF_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((decompress_file = open(DECOMPRESS_FILE_NAME, O_RDONLY)) < 0)
|
|
{
|
|
fprintf(stderr, " Cannot open decompressed data file '%s'\n", DECOMPRESS_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
}
|
|
|
|
if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
|
|
{
|
|
fprintf(stderr, " Failed to create file setup\n");
|
|
exit(2);
|
|
}
|
|
afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
|
|
afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
|
|
afInitFileFormat(filesetup, AF_FILE_WAVE);
|
|
afInitChannels(filesetup, AF_DEFAULT_TRACK, 1);
|
|
|
|
if ((outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
|
|
{
|
|
fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME);
|
|
exit(2);
|
|
}
|
|
#endif
|
|
|
|
if ((argc != 5) && (argc != 6))
|
|
{
|
|
fprintf(stderr,
|
|
"\n*-----------------------------------------------*\n");
|
|
fprintf(stderr,
|
|
" %s <20,30> input encoded decoded (channel)\n\n",
|
|
argv[0]);
|
|
fprintf(stderr,
|
|
" mode : Frame size for the encoding/decoding\n");
|
|
fprintf(stderr,
|
|
" 20 - 20 ms\n");
|
|
fprintf(stderr,
|
|
" 30 - 30 ms\n");
|
|
fprintf(stderr,
|
|
" input : Speech for encoder (16-bit pcm file)\n");
|
|
fprintf(stderr,
|
|
" encoded : Encoded bit stream\n");
|
|
fprintf(stderr,
|
|
" decoded : Decoded speech (16-bit pcm file)\n");
|
|
fprintf(stderr,
|
|
" channel : Packet loss pattern, optional (16-bit)\n");
|
|
fprintf(stderr,
|
|
" 1 - Packet received correctly\n");
|
|
fprintf(stderr,
|
|
" 0 - Packet Lost\n");
|
|
fprintf(stderr,
|
|
"*-----------------------------------------------*\n\n");
|
|
exit(1);
|
|
}
|
|
mode = atoi(argv[1]);
|
|
if (mode != 20 && mode != 30)
|
|
{
|
|
fprintf(stderr,"Wrong mode %s, must be 20, or 30\n",
|
|
argv[1]);
|
|
exit(2);
|
|
}
|
|
if ((ifileid = fopen(argv[2],"rb")) == NULL)
|
|
{
|
|
fprintf(stderr,"Cannot open input file %s\n", argv[2]);
|
|
exit(2);
|
|
}
|
|
if ((efileid = fopen(argv[3],"wb")) == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot open encoded file %s\n",
|
|
argv[3]);
|
|
exit(1);
|
|
}
|
|
if ((ofileid = fopen(argv[4],"wb")) == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot open decoded file %s\n",
|
|
argv[4]);
|
|
exit(1);
|
|
}
|
|
if (argc == 6)
|
|
{
|
|
if( (cfileid=fopen(argv[5],"rb")) == NULL)
|
|
{
|
|
fprintf(stderr, "Cannot open channel file %s\n",
|
|
argv[5]);
|
|
exit(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cfileid=NULL;
|
|
}
|
|
|
|
/* print info */
|
|
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr,
|
|
"*---------------------------------------------------*\n");
|
|
fprintf(stderr,
|
|
"* *\n");
|
|
fprintf(stderr,
|
|
"* iLBC test program *\n");
|
|
fprintf(stderr,
|
|
"* *\n");
|
|
fprintf(stderr,
|
|
"* *\n");
|
|
fprintf(stderr,
|
|
"*---------------------------------------------------*\n");
|
|
fprintf(stderr, "\nMode : %2d ms\n", mode);
|
|
fprintf(stderr, "Input file : %s\n", argv[2]);
|
|
fprintf(stderr, "Encoded file : %s\n", argv[3]);
|
|
fprintf(stderr, "Output file : %s\n", argv[4]);
|
|
if (argc == 6)
|
|
fprintf(stderr,"Channel file : %s\n", argv[5]);
|
|
fprintf(stderr, "\n");
|
|
|
|
/* Initialization */
|
|
|
|
ilbc_encode_init(&Enc_Inst, mode);
|
|
ilbc_decode_init(&Dec_Inst, mode, 1);
|
|
|
|
/* Runtime statistics */
|
|
starttime = clock()/(float)CLOCKS_PER_SEC;
|
|
|
|
/* Loop over input blocks */
|
|
while (fread(data, sizeof(int16_t), Enc_Inst.blockl, ifileid) == Enc_Inst.blockl)
|
|
{
|
|
blockcount++;
|
|
|
|
/* Encoding */
|
|
fprintf(stderr, "--- Encoding block %i --- ",blockcount);
|
|
len = ilbc_encode(&Enc_Inst, encoded_data, data, Enc_Inst.blockl);
|
|
fprintf(stderr, "\r");
|
|
|
|
/* Write byte file */
|
|
fwrite(encoded_data, sizeof(uint8_t), len, efileid);
|
|
|
|
/* Get channel data if provided */
|
|
if (argc == 6)
|
|
{
|
|
if (fread(&pli, sizeof(int16_t), 1, cfileid))
|
|
{
|
|
if ((pli != 0) && (pli != 1))
|
|
{
|
|
fprintf(stderr, "Error in channel file\n");
|
|
exit(0);
|
|
}
|
|
if (pli == 0)
|
|
{
|
|
/* Packet loss -> remove info from frame */
|
|
memset(encoded_data, 0, len);
|
|
packetlosscount++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Error. Channel file too int16_t\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pli = 1;
|
|
}
|
|
|
|
/* Decoding */
|
|
fprintf(stderr, "--- Decoding block %i --- ", blockcount);
|
|
|
|
if (pli)
|
|
len = ilbc_decode(&Dec_Inst, decoded_data, encoded_data, len);
|
|
else
|
|
len = ilbc_fillin(&Dec_Inst, decoded_data, len);
|
|
fprintf(stderr, "\r");
|
|
|
|
/* Write output file */
|
|
fwrite(decoded_data, sizeof(int16_t), len, ofileid);
|
|
}
|
|
|
|
/* Runtime statistics */
|
|
runtime = (float) (clock()/(float) CLOCKS_PER_SEC - starttime);
|
|
outtime = (float) ((float) blockcount*(float) mode/1000.0f);
|
|
printf("\n\nLength of speech file: %.1f s\n", outtime);
|
|
printf("Packet loss : %.1f%%\n",
|
|
100.0f*(float) packetlosscount/(float) blockcount);
|
|
printf("Time to run iLBC :");
|
|
printf(" %.1f s (%.1f%% of realtime)\n\n", runtime, 100.0f*runtime/outtime);
|
|
|
|
/* close files */
|
|
fclose(ifileid);
|
|
fclose(efileid);
|
|
fclose(ofileid);
|
|
if (argc == 6)
|
|
fclose(cfileid);
|
|
return(0);
|
|
}
|