Update SILK code using the CELT range coder
[opus.git] / test / Encoder.c
index 0e4dd1c..6a0deda 100644 (file)
@@ -25,6 +25,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
 ***********************************************************************/\r
 \r
+\r
 /*****************************/\r
 /* Silk encoder test program */\r
 /*****************************/\r
@@ -38,49 +39,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <string.h>\r
 #include <math.h>\r
 #include "SKP_Silk_SDK_API.h"\r
+#include "SKP_Silk_SigProc_FIX.h"\r
+#include "SKP_debug.h"\r
 \r
 /* Define codec specific settings */\r
 #define MAX_BYTES_PER_FRAME     250 // Equals peak bitrate of 100 kbps \r
 #define MAX_INPUT_FRAMES        5\r
 #define MAX_LBRR_DELAY          2\r
 #define MAX_FRAME_LENGTH        480\r
+#define MAX_FRAME_LENGTH_MS     20\r
+#define MAX_API_FS_KHZ          48\r
+\r
+#ifdef SKP_MACRO_COUNT\r
+    varDefine /* Define and reset global counters */\r
+#endif\r
+\r
+#ifdef _SYSTEM_IS_BIG_ENDIAN\r
+/* Function to convert a little endian int16 to a */\r
+/* big endian int16 or vica verca                 */\r
+void swap_endian(\r
+    SKP_int16       vec[],              /*  I/O array of */\r
+    SKP_int         len                 /*  I   length      */\r
+)\r
+{\r
+    SKP_int i;\r
+    SKP_int16 tmp;\r
+    SKP_uint8 *p1, *p2;\r
+\r
+    for( i = 0; i < len; i++ ){\r
+        tmp = vec[ i ];\r
+        p1 = (SKP_uint8 *)&vec[ i ]; p2 = (SKP_uint8 *)&tmp;\r
+        p1[ 0 ] = p2[ 1 ]; p1[ 1 ] = p2[ 0 ];\r
+    }\r
+}\r
+#endif\r
 \r
 static void print_usage( char* argv[] ) {\r
     printf( "\nusage: %s in.pcm out.bit [settings]\n", argv[ 0 ] );\r
-    printf( "\nin.pcm              : Speech input to encoder" );\r
-    printf( "\nout.bit             : Bitstream output from encoder" );\r
+    printf( "\nin.pcm               : Speech input to encoder" );\r
+    printf( "\nout.bit              : Bitstream output from encoder" );\r
     printf( "\n   settings:" );\r
-    printf( "\n-fs <kHz>           : Sampling rate in kHz, default: 24" );\r
-    printf( "\n-packetlength <ms>  : Packet interval in ms, default: 20" );\r
-    printf( "\n-rate <bps>         : Target bitrate; default: 25000" );\r
-    printf( "\n-loss <perc>        : Uplink loss estimate, in percent (0-100); default: 0" );\r
-    printf( "\n-inbandFEC <flag>   : Enable inband FEC usage (0/1); default: 0" );\r
-    printf( "\n-complexity <comp>  : Set complexity, 0: low, 1: medium, 2: high; default: 2" );\r
-    printf( "\n-DTX <flag>         : Enable DTX (0/1); default: 0" );\r
-    printf( "\n-quiet              : Print only some basic values" );\r
+    printf( "\n-Fs_API <Hz>         : API sampling rate in Hz, default: 24000" );\r
+    printf( "\n-Fs_maxInternal <Hz> : Maximum internal sampling rate in Hz, default: 24000" ); \r
+    printf( "\n-packetlength <ms>   : Packet interval in ms, default: 20" );\r
+    printf( "\n-rate <bps>          : Target bitrate; default: 25000" );\r
+    printf( "\n-loss <perc>         : Uplink loss estimate, in percent (0-100); default: 0" );\r
+    printf( "\n-inbandFEC <flag>    : Enable inband FEC usage (0/1); default: 0" );\r
+    printf( "\n-complexity <comp>   : Set complexity, 0: low, 1: medium, 2: high; default: 2" );\r
+    printf( "\n-DTX <flag>          : Enable DTX (0/1); default: 0" );\r
+    printf( "\n-quiet               : Print only some basic values" );\r
     printf( "\n");\r
 }\r
 \r
 int main( int argc, char* argv[] )\r
 {\r
+    unsigned long tottime, starttime;\r
+    double    filetime;\r
     size_t    counter;\r
-    SKP_int   k, args, totPackets, totActPackets, ret;\r
+    SKP_int32 k, args, totPackets, totActPackets, ret;\r
     SKP_int16 nBytes;\r
-    double    sumBytes, sumWBytes, sumActBytes, avg_rate, act_rate, wght_rate, nrg;\r
+    double    sumBytes, sumActBytes, avg_rate, act_rate, nrg;\r
     SKP_uint8 payload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES ];\r
-    SKP_int16 in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];\r
+    SKP_int16 in[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ * MAX_INPUT_FRAMES ];\r
     char      speechInFileName[ 150 ], bitOutFileName[ 150 ];\r
     FILE      *bitOutFile, *speechInFile;\r
     SKP_int32 encSizeBytes;\r
     void      *psEnc;\r
+#ifdef SKP_MACRO_COUNT\r
+    SKP_int64  Ops, maxOps = 0, totOps = 0;\r
+#endif\r
+#ifdef _SYSTEM_IS_BIG_ENDIAN\r
+    SKP_int16 nBytes_LE;\r
+#endif\r
 \r
     /* default settings */\r
-    SKP_int   fs_kHz = 24;\r
-    SKP_int   targetRate_bps = 25000;\r
-    SKP_int   packetSize_ms = 20;\r
-    SKP_int   frameSizeReadFromFile_ms = 20;\r
-    SKP_int   packetLoss_perc = 0, complexity_mode = 2, smplsSinceLastPacket;\r
-    SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;\r
+    SKP_int32 API_fs_Hz = 24000;\r
+    SKP_int32 max_internal_fs_Hz = 0;\r
+    SKP_int32 targetRate_bps = 25000;\r
+    SKP_int32 packetSize_ms = 20;\r
+    SKP_int32 frameSizeReadFromFile_ms = 10;\r
+    SKP_int32 packetLoss_perc = 0, complexity_mode = 2, smplsSinceLastPacket;\r
+    SKP_int32 INBandFEC_enabled = 0, DTX_enabled = 0, quiet = 0;\r
     SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder\r
         \r
     if( argc < 3 ) {\r
@@ -95,8 +134,11 @@ int main( int argc, char* argv[] )
     strcpy( bitOutFileName,   argv[ args ] );\r
     args++;\r
     while( args < argc ) {\r
-        if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-fs" ) == 0 ) {\r
-            sscanf( argv[ args + 1 ], "%d", &fs_kHz );\r
+        if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_API" ) == 0 ) {\r
+            sscanf( argv[ args + 1 ], "%d", &API_fs_Hz );\r
+            args += 2;\r
+        } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_maxInternal" ) == 0 ) {\r
+            sscanf( argv[ args + 1 ], "%d", &max_internal_fs_Hz );\r
             args += 2;\r
         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-packetlength" ) == 0 ) {\r
             sscanf( argv[ args + 1 ], "%d", &packetSize_ms );\r
@@ -111,7 +153,7 @@ int main( int argc, char* argv[] )
             sscanf( argv[ args + 1 ], "%d", &complexity_mode );\r
             args += 2;\r
         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandFEC" ) == 0 ) {\r
-            sscanf( argv[ args + 1 ], "%d", &INBandFec_enabled );\r
+            sscanf( argv[ args + 1 ], "%d", &INBandFEC_enabled );\r
             args += 2;\r
         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-DTX") == 0 ) {\r
             sscanf( argv[ args + 1 ], "%d", &DTX_enabled );\r
@@ -126,18 +168,24 @@ int main( int argc, char* argv[] )
         }\r
     }\r
 \r
+    /* If no max internal set set to API fs */\r
+    if( max_internal_fs_Hz == 0 ) {\r
+        max_internal_fs_Hz = API_fs_Hz;\r
+    }\r
+\r
     /* Print options */\r
     if( !quiet ) {\r
         printf("******************* Silk Encoder v %s ****************\n", SKP_Silk_SDK_get_version());\r
         printf("******************* Compiled for %d bit cpu ********* \n", (int)sizeof(void*) * 8 );\r
-        printf( "Input:                       %s\n",        speechInFileName );\r
-        printf( "Output:                      %s\n",        bitOutFileName );\r
-        printf( "Sampling rate:               %d kHz\n",    fs_kHz);\r
-        printf( "Packet interval:             %d ms\n",     packetSize_ms);\r
-        printf( "Inband FEC used:             %d\n",        INBandFec_enabled);\r
-        printf( "DTX used:                    %d\n",        DTX_enabled);\r
-        printf( "Complexity:                  %d\n",        complexity_mode);\r
-        printf( "Target bitrate:              %d bps\n",    targetRate_bps);\r
+        printf( "Input:                          %s\n",     speechInFileName );\r
+        printf( "Output:                         %s\n",     bitOutFileName );\r
+        printf( "API sampling rate:              %d Hz\n",  API_fs_Hz );\r
+        printf( "Maximum internal sampling rate: %d Hz\n",  max_internal_fs_Hz );\r
+        printf( "Packet interval:                %d ms\n",  packetSize_ms );\r
+        printf( "Inband FEC used:                %d\n",     INBandFEC_enabled );\r
+        printf( "DTX used:                       %d\n",     DTX_enabled );\r
+        printf( "Complexity:                     %d\n",     complexity_mode );\r
+        printf( "Target bitrate:                 %d bps\n", targetRate_bps );\r
     }\r
 \r
     /* Open files */\r
@@ -159,7 +207,7 @@ int main( int argc, char* argv[] )
     }\r
 \r
     psEnc = malloc( encSizeBytes );\r
-    \r
+\r
     /* Reset Encoder */\r
     ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );\r
     if( ret ) {\r
@@ -167,66 +215,83 @@ int main( int argc, char* argv[] )
     }\r
     \r
     /* Set Encoder parameters */\r
-    encControl.sampleRate           = fs_kHz * 1000;\r
-    encControl.packetSize           = packetSize_ms * fs_kHz;\r
-    encControl.packetLossPercentage = packetLoss_perc;\r
-    encControl.useInBandFEC         = INBandFec_enabled;\r
-    encControl.useDTX               = DTX_enabled;\r
-    encControl.complexity           = complexity_mode;\r
-    encControl.bitRate              = targetRate_bps;\r
-\r
-    if( fs_kHz > 24 || fs_kHz < 0 ) {\r
-        printf( "\nError: Sampling rate = %d out of range, valid range 8 - 24 \n \n", fs_kHz );\r
+    encControl.API_sampleRate        = API_fs_Hz;\r
+    encControl.maxInternalSampleRate = max_internal_fs_Hz;\r
+    encControl.packetSize            = ( packetSize_ms * API_fs_Hz ) / 1000;\r
+    encControl.packetLossPercentage  = packetLoss_perc;\r
+    encControl.useInBandFEC          = INBandFEC_enabled;\r
+    encControl.useDTX                = DTX_enabled;\r
+    encControl.complexity            = complexity_mode;\r
+    encControl.bitRate               = ( targetRate_bps > 0 ? targetRate_bps : 0 );\r
+\r
+    if( API_fs_Hz > MAX_API_FS_KHZ * 1000 || API_fs_Hz < 0 ) {\r
+        printf( "\nError: API sampling rate = %d out of range, valid range 8000 - 48000 \n \n", API_fs_Hz );\r
         exit( 0 );\r
     }\r
 \r
+    tottime              = 0;\r
     totPackets           = 0;\r
     totActPackets        = 0;\r
     smplsSinceLastPacket = 0;\r
     sumBytes             = 0.0;\r
     sumActBytes          = 0.0;\r
-    sumWBytes            = 0.0;\r
     \r
     while( 1 ) {\r
-        /* Read input to file */\r
-        counter = fread( in, sizeof( SKP_int16 ), frameSizeReadFromFile_ms * fs_kHz, speechInFile );\r
-        if( (SKP_int)counter < frameSizeReadFromFile_ms * fs_kHz ) {\r
+        /* Read input from file */\r
+        counter = fread( in, sizeof( SKP_int16 ), ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000, speechInFile );\r
+#ifdef _SYSTEM_IS_BIG_ENDIAN\r
+        swap_endian( in, counter );\r
+#endif\r
+        if( (SKP_int)counter < ( ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000 ) ) {\r
             break;\r
         }\r
 \r
         /* max payload size */\r
         nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES;\r
 \r
+        starttime = GetHighResolutionTime();\r
         /* Silk Encoder */\r
         ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)counter, payload, &nBytes );\r
         if( ret ) {\r
             printf( "\nSKP_Silk_Encode returned %d", ret );\r
             break;\r
         }\r
+        tottime += GetHighResolutionTime() - starttime;\r
+\r
+#ifdef SKP_MACRO_COUNT\r
+        Ops = SKP_SaveResetCount();\r
+        if( Ops > maxOps ){ maxOps = Ops; }\r
+        totOps += Ops;\r
+#endif\r
 \r
         /* Get packet size */\r
-        packetSize_ms = (SKP_int)( 1000 * encControl.packetSize ) / encControl.sampleRate;\r
+        packetSize_ms = ( SKP_int )( ( 1000 * ( SKP_int32 )encControl.packetSize ) / encControl.API_sampleRate );\r
 \r
-        smplsSinceLastPacket += (SKP_int)counter;\r
+        smplsSinceLastPacket += ( SKP_int )counter;\r
         \r
-        if( ( smplsSinceLastPacket / fs_kHz ) == packetSize_ms ) {\r
+        if( ( ( 1000 * smplsSinceLastPacket ) / API_fs_Hz ) == packetSize_ms ) {\r
             /* Sends a dummy zero size packet in case of DTX period  */\r
             /* to make it work with the decoder test program.        */\r
             /* In practice should be handled by RTP sequence numbers */\r
             totPackets++;\r
-            sumBytes  += nBytes;\r
-            sumWBytes += pow( (double)nBytes, 10.0 );\r
+            sumBytes += nBytes;\r
             nrg = 0.0;\r
-            for( k = 0; k < (SKP_int)counter; k++ ) {\r
+            for( k = 0; k < ( SKP_int )counter; k++ ) {\r
                 nrg += in[ k ] * (double)in[ k ];\r
             }\r
-            if( ( nrg / (SKP_int)counter ) > 1e3 ) {\r
+            if( ( nrg / ( SKP_int )counter ) > 1e3 ) {\r
                 sumActBytes += nBytes;\r
                 totActPackets++;\r
             }\r
 \r
             /* Write payload size */\r
+#ifdef _SYSTEM_IS_BIG_ENDIAN\r
+            nBytes_LE = nBytes;\r
+            swap_endian( &nBytes_LE, 1 );\r
+            fwrite( &nBytes_LE, sizeof( SKP_int16 ), 1, bitOutFile );\r
+#else\r
             fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );\r
+#endif\r
 \r
             /* Write payload */\r
             fwrite( payload, sizeof( SKP_uint8 ), nBytes, bitOutFile );\r
@@ -244,26 +309,43 @@ int main( int argc, char* argv[] )
     /* Write payload size */\r
     fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );\r
 \r
-    /* Query encoder */\r
-    packetSize_ms = (SKP_int)( 1000 * encControl.packetSize ) / encControl.sampleRate;\r
-\r
     /* Free Encoder */\r
     free( psEnc );\r
 \r
     fclose( speechInFile );\r
     fclose( bitOutFile   );\r
 \r
+    filetime  = totPackets * 1e-3 * packetSize_ms;\r
     avg_rate  = 8.0 / packetSize_ms * sumBytes       / totPackets;\r
     act_rate  = 8.0 / packetSize_ms * sumActBytes    / totActPackets;\r
-    wght_rate = 8.0 / packetSize_ms * pow( sumWBytes / totPackets, 0.1 );\r
     if( !quiet ) {\r
+        printf( "\nFile length:                 %.3f s", filetime );\r
+        printf( "\nTime for encoding:           %.3f s (%.3f%% of realtime)", 1e-6 * tottime, 1e-4 * tottime / filetime );\r
         printf( "\nAverage bitrate:             %.3f kbps", avg_rate  );\r
         printf( "\nActive bitrate:              %.3f kbps", act_rate  );\r
-        printf( "\nWeighted bitrate:            %.3f kbps", wght_rate );\r
+#ifdef SKP_MACRO_COUNT\r
+        printf( "\n \nWMOPS calculation");\r
+        printf( "\nMean:                        %.3f WMOPS", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3));\r
+        printf( "\nMax:                         %.3f WMOPS", (float)maxOps / ((float)packetSize_ms * 1e3));\r
+#endif\r
         printf( "\n\n" );\r
     } else {\r
-        /* print average and weighted bitrates */\r
-        printf( "%.3f %.3f %.3f \n", avg_rate, act_rate, wght_rate );\r
+        /* print time and % of realtime */\r
+        printf("%.3f %.3f %d ", 1e-6 * tottime, 1e-4 * tottime / filetime, totPackets );\r
+\r
+        /* print average and active bitrates */\r
+        printf( "%.3f %.3f ", avg_rate, act_rate );\r
+#ifdef SKP_MACRO_COUNT\r
+        /* print average and max WMOPS */\r
+        printf( "%.3f %.3f \n", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3), \r
+            (float)maxOps / ((float)packetSize_ms * 1e3));\r
+#else\r
+        printf( "%.3f %.3f \n", 0, 0);\r
+#endif\r
     }\r
+\r
+    /* Save timing file if TIC/TOC used */\r
+    SKP_TimerSave("encoder_timings.txt");\r
+\r
     return 0;\r
 }\r