freeswitch/libs/silk/test/Decoder.c

419 lines
14 KiB
C
Raw Normal View History

2014-08-08 15:24:42 +00:00
/***********************************************************************
2014-09-22 20:00:19 +00:00
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
2014-08-08 15:24:42 +00:00
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2014-09-22 20:00:19 +00:00
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
2014-08-08 15:24:42 +00:00
documentation and/or other materials provided with the distribution.
2014-09-22 20:00:19 +00:00
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
2014-08-08 15:24:42 +00:00
this software without specific prior written permission.
2014-09-22 20:00:19 +00:00
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2014-08-08 15:24:42 +00:00
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
2014-09-22 20:00:19 +00:00
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2014-08-08 15:24:42 +00:00
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2014-09-22 20:00:19 +00:00
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2014-08-08 15:24:42 +00:00
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*****************************/
/* Silk decoder test program */
/*****************************/
#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SKP_Silk_SDK_API.h"
#include "SKP_Silk_SigProc_FIX.h"
/* Define codec specific settings should be moved to h file */
#define MAX_BYTES_PER_FRAME 1024
#define MAX_INPUT_FRAMES 5
#define MAX_FRAME_LENGTH 480
#define FRAME_LENGTH_MS 20
#define MAX_API_FS_KHZ 48
#define MAX_LBRR_DELAY 2
#ifdef _SYSTEM_IS_BIG_ENDIAN
/* Function to convert a little endian int16 to a */
/* big endian int16 or vica verca */
void swap_endian(
SKP_int16 vec[],
SKP_int len
)
{
SKP_int i;
SKP_int16 tmp;
SKP_uint8 *p1, *p2;
for( i = 0; i < len; i++ ){
tmp = vec[ i ];
p1 = (SKP_uint8 *)&vec[ i ]; p2 = (SKP_uint8 *)&tmp;
p1[ 0 ] = p2[ 1 ]; p1[ 1 ] = p2[ 0 ];
}
}
#endif
/* Seed for the random number generator, which is used for simulating packet loss */
static SKP_int32 rand_seed = 1;
static void print_usage(char* argv[]) {
printf( "\nusage: %s in.bit out.pcm [settings]\n", argv[ 0 ] );
printf( "\nstream.bit : Bitstream input to decoder" );
printf( "\nout.pcm : Speech output from decoder" );
printf( "\n settings:" );
printf( "\n-Fs_API <Hz> : Sampling rate of output signal in Hz; default: 24000" );
printf( "\n-loss <perc> : Simulated packet loss percentage (0-100); default: 0" );
printf( "\n" );
}
int main( int argc, char* argv[] )
{
size_t counter;
SKP_int32 args, totPackets, i, k;
SKP_int16 ret, len, tot_len;
SKP_int16 nBytes;
SKP_uint8 payload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
SKP_uint8 *payloadEnd = NULL, *payloadToDec = NULL;
SKP_uint8 FECpayload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES ], *payloadPtr;
SKP_int16 nBytesFEC;
SKP_int16 nBytesPerPacket[ MAX_LBRR_DELAY + 1 ], totBytes;
SKP_int16 out[ ( ( FRAME_LENGTH_MS * MAX_API_FS_KHZ ) << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
char speechOutFileName[ 150 ], bitInFileName[ 150 ];
FILE *bitInFile, *speechOutFile;
SKP_int32 API_Fs_Hz = 0;
SKP_int32 decSizeBytes;
void *psDec;
float loss_prob;
SKP_int32 frames, lost, quiet;
SKP_SILK_SDK_DecControlStruct DecControl;
if( argc < 3 ) {
print_usage( argv );
exit( 0 );
2014-09-22 20:00:19 +00:00
}
2014-08-08 15:24:42 +00:00
/* default settings */
quiet = 0;
loss_prob = 0.0f;
/* get arguments */
args = 1;
strcpy( bitInFileName, argv[ args ] );
args++;
strcpy( speechOutFileName, argv[ args ] );
args++;
while( args < argc ) {
if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
sscanf( argv[ args + 1 ], "%f", &loss_prob );
args += 2;
} else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_API" ) == 0 ) {
sscanf( argv[ args + 1 ], "%d", &API_Fs_Hz );
args += 2;
} else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-quiet" ) == 0 ) {
quiet = 1;
args++;
} else {
printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
print_usage( argv );
exit( 0 );
}
}
if( !quiet ) {
printf("******************* Silk Decoder v %s ****************\n", SKP_Silk_SDK_get_version());
printf("******************* Compiled for %d bit cpu ********* \n", (int)sizeof(void*) * 8 );
printf( "Input: %s\n", bitInFileName );
printf( "Output: %s\n", speechOutFileName );
}
/* Open files */
bitInFile = fopen( bitInFileName, "rb" );
if( bitInFile == NULL ) {
printf( "Error: could not open input file %s\n", bitInFileName );
exit( 0 );
2014-09-22 20:00:19 +00:00
}
2014-08-08 15:24:42 +00:00
/* Check Silk header */
{
char header_buf[ 50 ];
counter = fread( header_buf, sizeof( char ), strlen( "#!SILK_V3" ), bitInFile );
header_buf[ strlen( "#!SILK_V3" ) ] = ( char )0; /* Terminate with a null character */
2014-09-22 20:00:19 +00:00
if( strcmp( header_buf, "#!SILK_V3" ) != 0 ) {
2014-08-08 15:24:42 +00:00
/* Non-equal strings */
printf( "Error: Wrong Header %s\n", header_buf );
exit( 0 );
}
}
speechOutFile = fopen( speechOutFileName, "wb" );
if( speechOutFile == NULL ) {
printf( "Error: could not open output file %s\n", speechOutFileName );
exit( 0 );
}
/* Set the samplingrate that is requested for the output */
if( API_Fs_Hz == 0 ) {
DecControl.API_sampleRate = 24000;
} else {
DecControl.API_sampleRate = API_Fs_Hz;
}
/* Initialize to one frame per packet, for proper concealment before first packet arrives */
DecControl.framesPerPacket = 1;
/* Create decoder */
ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
if( ret ) {
printf( "\nSKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
}
psDec = malloc( decSizeBytes );
/* Reset decoder */
ret = SKP_Silk_SDK_InitDecoder( psDec );
if( ret ) {
printf( "\nSKP_Silk_InitDecoder returned %d", ret );
}
totPackets = 0;
payloadEnd = payload;
/* Simulate the jitter buffer holding MAX_FEC_DELAY packets */
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
nBytesPerPacket[ i ] = nBytes;
payloadEnd += nBytes;
}
while( 1 ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
if( nBytes < 0 || counter < 1 ) {
break;
}
2014-09-22 20:00:19 +00:00
2014-08-08 15:24:42 +00:00
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
/* Simulate losses */
rand_seed = SKP_RAND( rand_seed );
if( ( ( ( float )( ( rand_seed >> 16 ) + ( 1 << 15 ) ) ) / 65535.0f >= ( loss_prob / 100.0f ) ) && ( counter > 0 ) ) {
nBytesPerPacket[ MAX_LBRR_DELAY ] = nBytes;
payloadEnd += nBytes;
} else {
nBytesPerPacket[ MAX_LBRR_DELAY ] = 0;
}
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], i + 1, FECpayload, &nBytesFEC );
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
if( lost == 0 ) {
/* No Loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
2014-09-22 20:00:19 +00:00
} while( DecControl.moreInternalDecoderFrames );
} else {
2014-08-08 15:24:42 +00:00
/* Loss: Decode enough frames to cover one packet duration */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
/* Generate 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
totPackets++;
/* Write output to file */
2014-09-22 20:00:19 +00:00
#ifdef _SYSTEM_IS_BIG_ENDIAN
2014-08-08 15:24:42 +00:00
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
if( !quiet ) {
fprintf( stderr, "\rPackets decoded: %d", totPackets );
}
}
/* Empty the recieve buffer */
for( k = 0; k < MAX_LBRR_DELAY; k++ ) {
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], i + 1, FECpayload, &nBytesFEC );
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
if( lost == 0 ) {
/* No loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
} while( DecControl.moreInternalDecoderFrames );
2014-09-22 20:00:19 +00:00
} else {
2014-08-08 15:24:42 +00:00
/* Loss: Decode enough frames to cover one packet duration */
/* Generate 20 ms */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
totPackets++;
/* Write output to file */
2014-09-22 20:00:19 +00:00
#ifdef _SYSTEM_IS_BIG_ENDIAN
2014-08-08 15:24:42 +00:00
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update Buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
if( !quiet ) {
fprintf( stderr, "\rPackets decoded: %d", totPackets );
}
}
if( !quiet ) {
printf( "\nDecoding Finished \n" );
}
/* Free decoder */
free( psDec );
/* Close files */
fclose( speechOutFile );
fclose( bitInFile );
return 0;
}