Update SILK code using the CELT range coder
[opus.git] / test / Encoder.c
1 /***********************************************************************\r
2 Copyright (c) 2006-2010, Skype Limited. All rights reserved. \r
3 Redistribution and use in source and binary forms, with or without \r
4 modification, (subject to the limitations in the disclaimer below) \r
5 are permitted provided that the following conditions are met:\r
6 - Redistributions of source code must retain the above copyright notice,\r
7 this list of conditions and the following disclaimer.\r
8 - Redistributions in binary form must reproduce the above copyright \r
9 notice, this list of conditions and the following disclaimer in the \r
10 documentation and/or other materials provided with the distribution.\r
11 - Neither the name of Skype Limited, nor the names of specific \r
12 contributors, may be used to endorse or promote products derived from \r
13 this software without specific prior written permission.\r
14 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED \r
15 BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
16 CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r
17 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
18 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
19 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26 ***********************************************************************/\r
27 \r
28 \r
29 /*****************************/\r
30 /* Silk encoder test program */\r
31 /*****************************/\r
32 \r
33 #ifdef _WIN32\r
34 #define _CRT_SECURE_NO_DEPRECATE    1\r
35 #endif\r
36 \r
37 #include <stdio.h>\r
38 #include <stdlib.h>\r
39 #include <string.h>\r
40 #include <math.h>\r
41 #include "SKP_Silk_SDK_API.h"\r
42 #include "SKP_Silk_SigProc_FIX.h"\r
43 #include "SKP_debug.h"\r
44 \r
45 /* Define codec specific settings */\r
46 #define MAX_BYTES_PER_FRAME     250 // Equals peak bitrate of 100 kbps \r
47 #define MAX_INPUT_FRAMES        5\r
48 #define MAX_LBRR_DELAY          2\r
49 #define MAX_FRAME_LENGTH        480\r
50 #define MAX_FRAME_LENGTH_MS     20\r
51 #define MAX_API_FS_KHZ          48\r
52 \r
53 #ifdef SKP_MACRO_COUNT\r
54     varDefine /* Define and reset global counters */\r
55 #endif\r
56 \r
57 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
58 /* Function to convert a little endian int16 to a */\r
59 /* big endian int16 or vica verca                 */\r
60 void swap_endian(\r
61     SKP_int16       vec[],              /*  I/O array of */\r
62     SKP_int         len                 /*  I   length      */\r
63 )\r
64 {\r
65     SKP_int i;\r
66     SKP_int16 tmp;\r
67     SKP_uint8 *p1, *p2;\r
68 \r
69     for( i = 0; i < len; i++ ){\r
70         tmp = vec[ i ];\r
71         p1 = (SKP_uint8 *)&vec[ i ]; p2 = (SKP_uint8 *)&tmp;\r
72         p1[ 0 ] = p2[ 1 ]; p1[ 1 ] = p2[ 0 ];\r
73     }\r
74 }\r
75 #endif\r
76 \r
77 static void print_usage( char* argv[] ) {\r
78     printf( "\nusage: %s in.pcm out.bit [settings]\n", argv[ 0 ] );\r
79     printf( "\nin.pcm               : Speech input to encoder" );\r
80     printf( "\nout.bit              : Bitstream output from encoder" );\r
81     printf( "\n   settings:" );\r
82     printf( "\n-Fs_API <Hz>         : API sampling rate in Hz, default: 24000" );\r
83     printf( "\n-Fs_maxInternal <Hz> : Maximum internal sampling rate in Hz, default: 24000" ); \r
84     printf( "\n-packetlength <ms>   : Packet interval in ms, default: 20" );\r
85     printf( "\n-rate <bps>          : Target bitrate; default: 25000" );\r
86     printf( "\n-loss <perc>         : Uplink loss estimate, in percent (0-100); default: 0" );\r
87     printf( "\n-inbandFEC <flag>    : Enable inband FEC usage (0/1); default: 0" );\r
88     printf( "\n-complexity <comp>   : Set complexity, 0: low, 1: medium, 2: high; default: 2" );\r
89     printf( "\n-DTX <flag>          : Enable DTX (0/1); default: 0" );\r
90     printf( "\n-quiet               : Print only some basic values" );\r
91     printf( "\n");\r
92 }\r
93 \r
94 int main( int argc, char* argv[] )\r
95 {\r
96     unsigned long tottime, starttime;\r
97     double    filetime;\r
98     size_t    counter;\r
99     SKP_int32 k, args, totPackets, totActPackets, ret;\r
100     SKP_int16 nBytes;\r
101     double    sumBytes, sumActBytes, avg_rate, act_rate, nrg;\r
102     SKP_uint8 payload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES ];\r
103     SKP_int16 in[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ * MAX_INPUT_FRAMES ];\r
104     char      speechInFileName[ 150 ], bitOutFileName[ 150 ];\r
105     FILE      *bitOutFile, *speechInFile;\r
106     SKP_int32 encSizeBytes;\r
107     void      *psEnc;\r
108 #ifdef SKP_MACRO_COUNT\r
109     SKP_int64  Ops, maxOps = 0, totOps = 0;\r
110 #endif\r
111 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
112     SKP_int16 nBytes_LE;\r
113 #endif\r
114 \r
115     /* default settings */\r
116     SKP_int32 API_fs_Hz = 24000;\r
117     SKP_int32 max_internal_fs_Hz = 0;\r
118     SKP_int32 targetRate_bps = 25000;\r
119     SKP_int32 packetSize_ms = 20;\r
120     SKP_int32 frameSizeReadFromFile_ms = 10;\r
121     SKP_int32 packetLoss_perc = 0, complexity_mode = 2, smplsSinceLastPacket;\r
122     SKP_int32 INBandFEC_enabled = 0, DTX_enabled = 0, quiet = 0;\r
123     SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder\r
124         \r
125     if( argc < 3 ) {\r
126         print_usage( argv );\r
127         exit( 0 );\r
128     } \r
129     \r
130     /* get arguments */\r
131     args = 1;\r
132     strcpy( speechInFileName, argv[ args ] );\r
133     args++;\r
134     strcpy( bitOutFileName,   argv[ args ] );\r
135     args++;\r
136     while( args < argc ) {\r
137         if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_API" ) == 0 ) {\r
138             sscanf( argv[ args + 1 ], "%d", &API_fs_Hz );\r
139             args += 2;\r
140         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_maxInternal" ) == 0 ) {\r
141             sscanf( argv[ args + 1 ], "%d", &max_internal_fs_Hz );\r
142             args += 2;\r
143         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-packetlength" ) == 0 ) {\r
144             sscanf( argv[ args + 1 ], "%d", &packetSize_ms );\r
145             args += 2;\r
146         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-rate" ) == 0 ) {\r
147             sscanf( argv[ args + 1 ], "%d", &targetRate_bps );\r
148             args += 2;\r
149         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {\r
150             sscanf( argv[ args + 1 ], "%d", &packetLoss_perc );\r
151             args += 2;\r
152         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {\r
153             sscanf( argv[ args + 1 ], "%d", &complexity_mode );\r
154             args += 2;\r
155         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandFEC" ) == 0 ) {\r
156             sscanf( argv[ args + 1 ], "%d", &INBandFEC_enabled );\r
157             args += 2;\r
158         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-DTX") == 0 ) {\r
159             sscanf( argv[ args + 1 ], "%d", &DTX_enabled );\r
160             args += 2;\r
161         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-quiet" ) == 0 ) {\r
162             quiet = 1;\r
163             args++;\r
164         } else {\r
165             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );\r
166             print_usage( argv );\r
167             exit( 0 );\r
168         }\r
169     }\r
170 \r
171     /* If no max internal set set to API fs */\r
172     if( max_internal_fs_Hz == 0 ) {\r
173         max_internal_fs_Hz = API_fs_Hz;\r
174     }\r
175 \r
176     /* Print options */\r
177     if( !quiet ) {\r
178         printf("******************* Silk Encoder v %s ****************\n", SKP_Silk_SDK_get_version());\r
179         printf("******************* Compiled for %d bit cpu ********* \n", (int)sizeof(void*) * 8 );\r
180         printf( "Input:                          %s\n",     speechInFileName );\r
181         printf( "Output:                         %s\n",     bitOutFileName );\r
182         printf( "API sampling rate:              %d Hz\n",  API_fs_Hz );\r
183         printf( "Maximum internal sampling rate: %d Hz\n",  max_internal_fs_Hz );\r
184         printf( "Packet interval:                %d ms\n",  packetSize_ms );\r
185         printf( "Inband FEC used:                %d\n",     INBandFEC_enabled );\r
186         printf( "DTX used:                       %d\n",     DTX_enabled );\r
187         printf( "Complexity:                     %d\n",     complexity_mode );\r
188         printf( "Target bitrate:                 %d bps\n", targetRate_bps );\r
189     }\r
190 \r
191     /* Open files */\r
192     speechInFile = fopen( speechInFileName, "rb" );\r
193     if( speechInFile == NULL ) {\r
194         printf( "Error: could not open input file %s\n", speechInFileName );\r
195         exit( 0 );\r
196     }\r
197     bitOutFile = fopen( bitOutFileName, "wb" );\r
198     if( bitOutFile == NULL ) {\r
199         printf( "Error: could not open output file %s\n", bitOutFileName );\r
200         exit( 0 );\r
201     }\r
202 \r
203     /* Create Encoder */\r
204     ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );\r
205     if( ret ) {\r
206         printf( "\nSKP_Silk_create_encoder returned %d", ret );\r
207     }\r
208 \r
209     psEnc = malloc( encSizeBytes );\r
210 \r
211     /* Reset Encoder */\r
212     ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );\r
213     if( ret ) {\r
214         printf( "\nSKP_Silk_reset_encoder returned %d", ret );\r
215     }\r
216     \r
217     /* Set Encoder parameters */\r
218     encControl.API_sampleRate        = API_fs_Hz;\r
219     encControl.maxInternalSampleRate = max_internal_fs_Hz;\r
220     encControl.packetSize            = ( packetSize_ms * API_fs_Hz ) / 1000;\r
221     encControl.packetLossPercentage  = packetLoss_perc;\r
222     encControl.useInBandFEC          = INBandFEC_enabled;\r
223     encControl.useDTX                = DTX_enabled;\r
224     encControl.complexity            = complexity_mode;\r
225     encControl.bitRate               = ( targetRate_bps > 0 ? targetRate_bps : 0 );\r
226 \r
227     if( API_fs_Hz > MAX_API_FS_KHZ * 1000 || API_fs_Hz < 0 ) {\r
228         printf( "\nError: API sampling rate = %d out of range, valid range 8000 - 48000 \n \n", API_fs_Hz );\r
229         exit( 0 );\r
230     }\r
231 \r
232     tottime              = 0;\r
233     totPackets           = 0;\r
234     totActPackets        = 0;\r
235     smplsSinceLastPacket = 0;\r
236     sumBytes             = 0.0;\r
237     sumActBytes          = 0.0;\r
238     \r
239     while( 1 ) {\r
240         /* Read input from file */\r
241         counter = fread( in, sizeof( SKP_int16 ), ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000, speechInFile );\r
242 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
243         swap_endian( in, counter );\r
244 #endif\r
245         if( (SKP_int)counter < ( ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000 ) ) {\r
246             break;\r
247         }\r
248 \r
249         /* max payload size */\r
250         nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES;\r
251 \r
252         starttime = GetHighResolutionTime();\r
253         /* Silk Encoder */\r
254         ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)counter, payload, &nBytes );\r
255         if( ret ) {\r
256             printf( "\nSKP_Silk_Encode returned %d", ret );\r
257             break;\r
258         }\r
259         tottime += GetHighResolutionTime() - starttime;\r
260 \r
261 #ifdef SKP_MACRO_COUNT\r
262         Ops = SKP_SaveResetCount();\r
263         if( Ops > maxOps ){ maxOps = Ops; }\r
264         totOps += Ops;\r
265 #endif\r
266 \r
267         /* Get packet size */\r
268         packetSize_ms = ( SKP_int )( ( 1000 * ( SKP_int32 )encControl.packetSize ) / encControl.API_sampleRate );\r
269 \r
270         smplsSinceLastPacket += ( SKP_int )counter;\r
271         \r
272         if( ( ( 1000 * smplsSinceLastPacket ) / API_fs_Hz ) == packetSize_ms ) {\r
273             /* Sends a dummy zero size packet in case of DTX period  */\r
274             /* to make it work with the decoder test program.        */\r
275             /* In practice should be handled by RTP sequence numbers */\r
276             totPackets++;\r
277             sumBytes += nBytes;\r
278             nrg = 0.0;\r
279             for( k = 0; k < ( SKP_int )counter; k++ ) {\r
280                 nrg += in[ k ] * (double)in[ k ];\r
281             }\r
282             if( ( nrg / ( SKP_int )counter ) > 1e3 ) {\r
283                 sumActBytes += nBytes;\r
284                 totActPackets++;\r
285             }\r
286 \r
287             /* Write payload size */\r
288 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
289             nBytes_LE = nBytes;\r
290             swap_endian( &nBytes_LE, 1 );\r
291             fwrite( &nBytes_LE, sizeof( SKP_int16 ), 1, bitOutFile );\r
292 #else\r
293             fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );\r
294 #endif\r
295 \r
296             /* Write payload */\r
297             fwrite( payload, sizeof( SKP_uint8 ), nBytes, bitOutFile );\r
298         \r
299             if( !quiet ) {\r
300                 fprintf( stderr, "\rPackets encoded:              %d", totPackets );\r
301             }\r
302             smplsSinceLastPacket = 0;\r
303         }\r
304     }\r
305 \r
306     /* Write dummy because it can not end with 0 bytes */\r
307     nBytes = -1;\r
308 \r
309     /* Write payload size */\r
310     fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );\r
311 \r
312     /* Free Encoder */\r
313     free( psEnc );\r
314 \r
315     fclose( speechInFile );\r
316     fclose( bitOutFile   );\r
317 \r
318     filetime  = totPackets * 1e-3 * packetSize_ms;\r
319     avg_rate  = 8.0 / packetSize_ms * sumBytes       / totPackets;\r
320     act_rate  = 8.0 / packetSize_ms * sumActBytes    / totActPackets;\r
321     if( !quiet ) {\r
322         printf( "\nFile length:                 %.3f s", filetime );\r
323         printf( "\nTime for encoding:           %.3f s (%.3f%% of realtime)", 1e-6 * tottime, 1e-4 * tottime / filetime );\r
324         printf( "\nAverage bitrate:             %.3f kbps", avg_rate  );\r
325         printf( "\nActive bitrate:              %.3f kbps", act_rate  );\r
326 #ifdef SKP_MACRO_COUNT\r
327         printf( "\n \nWMOPS calculation");\r
328         printf( "\nMean:                        %.3f WMOPS", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3));\r
329         printf( "\nMax:                         %.3f WMOPS", (float)maxOps / ((float)packetSize_ms * 1e3));\r
330 #endif\r
331         printf( "\n\n" );\r
332     } else {\r
333         /* print time and % of realtime */\r
334         printf("%.3f %.3f %d ", 1e-6 * tottime, 1e-4 * tottime / filetime, totPackets );\r
335 \r
336         /* print average and active bitrates */\r
337         printf( "%.3f %.3f ", avg_rate, act_rate );\r
338 #ifdef SKP_MACRO_COUNT\r
339         /* print average and max WMOPS */\r
340         printf( "%.3f %.3f \n", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3), \r
341             (float)maxOps / ((float)packetSize_ms * 1e3));\r
342 #else\r
343         printf( "%.3f %.3f \n", 0, 0);\r
344 #endif\r
345     }\r
346 \r
347     /* Save timing file if TIC/TOC used */\r
348     SKP_TimerSave("encoder_timings.txt");\r
349 \r
350     return 0;\r
351 }\r