Update SILK code using the CELT range coder
[opus.git] / test / Decoder.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 decoder 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 "SKP_Silk_SDK_API.h"\r
41 #include "SKP_Silk_SigProc_FIX.h"\r
42 #include "SKP_debug.h"\r
43 \r
44 /* Define codec specific settings should be moved to h file */\r
45 #define MAX_BYTES_PER_FRAME     1024\r
46 #define MAX_INPUT_FRAMES        5\r
47 #define MAX_FRAME_LENGTH        480\r
48 #define MAX_FRAME_LENGTH_MS     20\r
49 #define MAX_API_FS_KHZ          48\r
50 #define MAX_LBRR_DELAY          2\r
51 \r
52 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
53 /* Function to convert a little endian int16 to a */\r
54 /* big endian int16 or vica verca                 */\r
55 void swap_endian(\r
56     SKP_int16       vec[],\r
57     SKP_int         len\r
58 )\r
59 {\r
60     SKP_int i;\r
61     SKP_int16 tmp;\r
62     SKP_uint8 *p1, *p2;\r
63 \r
64     for( i = 0; i < len; i++ ){\r
65         tmp = vec[ i ];\r
66         p1 = (SKP_uint8 *)&vec[ i ]; p2 = (SKP_uint8 *)&tmp;\r
67         p1[ 0 ] = p2[ 1 ]; p1[ 1 ] = p2[ 0 ];\r
68     }\r
69 }\r
70 #endif\r
71 \r
72 static void print_usage(char* argv[]) {\r
73     printf( "\nusage: %s in.bit out.pcm [settings]\n", argv[ 0 ] );\r
74     printf( "\nin.bit       : Bitstream input to decoder" );\r
75     printf( "\nout.pcm      : Speech output from decoder" );\r
76     printf( "\n   settings:" );\r
77     printf( "\n-Fs_API <Hz> : Sampling rate of output signal in Hz; default: 24000" );\r
78     printf( "\n-loss <perc> : Simulated packet loss percentage (0-100); default: 0" );\r
79     printf( "\n" );\r
80 }\r
81 \r
82 #ifdef SKP_MACRO_COUNT\r
83     varDefine /* Define and reset global counters */\r
84 #endif\r
85 \r
86 int main( int argc, char* argv[] )\r
87 {\r
88     unsigned long tottime, starttime;\r
89     double    filetime;\r
90     size_t    counter;\r
91     SKP_int32 args, totPackets, i, k;\r
92     SKP_int16 ret, len, tot_len;\r
93     SKP_int16 nBytes;\r
94     SKP_uint8 payload[    MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];\r
95     SKP_uint8 *payloadEnd = NULL, *payloadToDec = NULL;\r
96     SKP_uint8 FECpayload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES ], *payloadPtr;\r
97     SKP_int16 nBytesFEC;\r
98     SKP_int16 nBytesPerPacket[ MAX_LBRR_DELAY + 1 ], totBytes;\r
99     SKP_int16 out[ ( ( MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ) << 1 ) * MAX_INPUT_FRAMES ], *outPtr;\r
100     char      speechOutFileName[ 150 ], bitInFileName[ 150 ];\r
101     FILE      *bitInFile, *speechOutFile;\r
102     SKP_int32 API_Fs_Hz = 0, packetSize_ms=0;\r
103     SKP_int32 decSizeBytes;\r
104     void      *psDec;\r
105 #ifdef SKP_MACRO_COUNT\r
106     SKP_int64  Ops, maxOps = 0, totOps = 0;\r
107 #endif\r
108     float     loss_prob;\r
109     SKP_int32 frames, lost, quiet;\r
110     SKP_SILK_SDK_DecControlStruct DecControl;\r
111 \r
112     if( argc < 3 ) {\r
113         print_usage( argv );\r
114         exit( 0 );\r
115     } \r
116 \r
117     /* default settings */\r
118     quiet     = 0;\r
119     loss_prob = 0.0f;\r
120 \r
121     /* get arguments */\r
122     args = 1;\r
123     strcpy( bitInFileName, argv[ args ] );\r
124     args++;\r
125     strcpy( speechOutFileName, argv[ args ] );\r
126     args++;\r
127     while( args < argc ) {\r
128         if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {\r
129             sscanf( argv[ args + 1 ], "%f", &loss_prob );\r
130             args += 2;\r
131         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_API" ) == 0 ) {\r
132             sscanf( argv[ args + 1 ], "%d", &API_Fs_Hz );\r
133             args += 2;\r
134         } else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-quiet" ) == 0 ) {\r
135             quiet = 1;\r
136             args++;\r
137         } else {\r
138             printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );\r
139             print_usage( argv );\r
140             exit( 0 );\r
141         }\r
142     }\r
143 \r
144     if( !quiet ) {\r
145         printf("******************* Silk Decoder v %s ****************\n", SKP_Silk_SDK_get_version());\r
146         printf("******************* Compiled for %d bit cpu ********* \n", (int)sizeof(void*) * 8 );\r
147         printf( "Input:                       %s\n", bitInFileName );\r
148         printf( "Output:                      %s\n", speechOutFileName );\r
149     }\r
150 \r
151     /* Open files */\r
152     bitInFile = fopen( bitInFileName, "rb" );\r
153     if( bitInFile == NULL ) {\r
154         printf( "Error: could not open input file %s\n", bitInFileName );\r
155         exit( 0 );\r
156     } \r
157     speechOutFile = fopen( speechOutFileName, "wb" );\r
158     if( speechOutFile == NULL ) {\r
159         printf( "Error: could not open output file %s\n", speechOutFileName );\r
160         exit( 0 );\r
161     }\r
162 \r
163     /* Set the samplingrate that is requested for the output */\r
164     if( API_Fs_Hz == 0 ) {\r
165         DecControl.API_sampleRate = 24000;\r
166     } else {\r
167         DecControl.API_sampleRate = API_Fs_Hz;\r
168     }\r
169 \r
170     /* Create decoder */\r
171     ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );\r
172     if( ret ) {\r
173         printf( "\nSKP_Silk_SDK_Get_Decoder_Size returned %d", ret );\r
174     }\r
175     psDec = malloc( decSizeBytes );\r
176 \r
177     /* Reset decoder */\r
178     ret = SKP_Silk_SDK_InitDecoder( psDec );\r
179     if( ret ) {\r
180         printf( "\nSKP_Silk_InitDecoder returned %d", ret );\r
181     }\r
182 \r
183     tottime    = 0;\r
184     totPackets = 0;\r
185     payloadEnd = payload;\r
186 \r
187     /* Simulate the jitter buffer holding MAX_FEC_DELAY packets */\r
188     for( i = 0; i < MAX_LBRR_DELAY; i++ ) {\r
189         /* Read payload size */\r
190         counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );\r
191 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
192         swap_endian( &nBytes, 1 );\r
193 #endif\r
194         /* Read payload */\r
195         counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );\r
196 \r
197         if( ( SKP_int16 )counter < nBytes ) {\r
198             break;\r
199         }\r
200         nBytesPerPacket[ i ] = nBytes;\r
201         payloadEnd          += nBytes;\r
202     }\r
203 \r
204     while( 1 ) {\r
205         /* Read payload size */\r
206         counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );\r
207 #ifdef _SYSTEM_IS_BIG_ENDIAN\r
208         swap_endian( &nBytes, 1 );\r
209 #endif\r
210         if( nBytes < 0 || counter < 1 ) {\r
211             break;\r
212         }\r
213         \r
214         /* Read payload */\r
215         counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );\r
216         if( ( SKP_int16 )counter < nBytes ) {\r
217             break;\r
218         }\r
219 \r
220         /* Simulate losses */\r
221         if( ( (float)rand() / (float)RAND_MAX >= loss_prob / 100 ) && counter > 0 ) {\r
222             nBytesPerPacket[ MAX_LBRR_DELAY ] = nBytes;\r
223             payloadEnd                       += nBytes;\r
224         } else {\r
225             nBytesPerPacket[ MAX_LBRR_DELAY ] = 0;\r
226         }\r
227 \r
228         if( nBytesPerPacket[ 0 ] == 0 ) {\r
229             /* Indicate lost packet */\r
230             lost = 1;\r
231 \r
232             /* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */\r
233             payloadPtr = payload;\r
234             for( i = 0; i < MAX_LBRR_DELAY; i++ ) {\r
235                 if( nBytesPerPacket[ i + 1 ] > 0 ) {\r
236                     starttime = GetHighResolutionTime();\r
237                     SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], i + 1, FECpayload, &nBytesFEC );\r
238                     tottime += GetHighResolutionTime() - starttime;\r
239                     if( nBytesFEC > 0 ) {\r
240                         payloadToDec = FECpayload;\r
241                         nBytes = nBytesFEC;\r
242                         lost = 0;\r
243                         break;\r
244                     }\r
245                 }\r
246                 payloadPtr += nBytesPerPacket[ i + 1 ];\r
247             }\r
248         } else {\r
249             lost = 0;\r
250             nBytes = nBytesPerPacket[ 0 ];\r
251             payloadToDec = payload;\r
252         }\r
253 \r
254         /* Silk decoder */\r
255         outPtr = out;\r
256         tot_len = 0;\r
257 \r
258         if( lost == 0 ) {\r
259             /* No Loss: Decode all frames in the packet */\r
260             frames = 0;\r
261             do {\r
262                 /* Decode 20 ms */\r
263                 starttime = GetHighResolutionTime();\r
264                 ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );\r
265                 tottime += GetHighResolutionTime() - starttime;\r
266                 if( ret ) {\r
267                     printf( "\nSKP_Silk_SDK_Decode returned %d", ret );\r
268                 }\r
269 #ifdef SKP_MACRO_COUNT\r
270                 Ops = SKP_SaveResetCount();\r
271                 if( Ops > maxOps ){ maxOps = Ops; }\r
272                 totOps += Ops;\r
273 #endif\r
274                 frames++;\r
275                 outPtr  += len;\r
276                 tot_len += len;\r
277                 if( frames > MAX_INPUT_FRAMES ) {\r
278                     /* Hack for corrupt stream that could generate too many frames */\r
279                     outPtr  = out;\r
280                     tot_len = 0;\r
281                     frames  = 0;\r
282                 }\r
283                 /* Until last 20 ms frame of packet has been decoded */\r
284             } while( DecControl.moreInternalDecoderFrames ); \r
285         } else {    \r
286             /* Loss: Decode enough frames to cover one packet duration */\r
287             for( i = 0; i < DecControl.framesPerPacket; i++ ) {\r
288                 /* Generate 20 ms */\r
289                 starttime = GetHighResolutionTime();\r
290                 ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );\r
291                 tottime += GetHighResolutionTime() - starttime;\r
292                 if( ret ) {\r
293                     printf( "\nSKP_Silk_Decode returned %d", ret );\r
294                 }\r
295 #ifdef SKP_MACRO_COUNT\r
296                 Ops = SKP_SaveResetCount();\r
297                 if( Ops > maxOps ){ maxOps = Ops; }\r
298                 totOps += Ops;\r
299 #endif\r
300                 outPtr  += len;\r
301                 tot_len += len;\r
302             }\r
303         }\r
304         totPackets++;\r
305         packetSize_ms = tot_len / ( DecControl.API_sampleRate / 1000 );\r
306 \r
307         /* Write output to file */\r
308 #ifdef _SYSTEM_IS_BIG_ENDIAN   \r
309         swap_endian( out, tot_len );\r
310 #endif\r
311         fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );\r
312 \r
313         /* Update buffer */\r
314         totBytes = 0;\r
315         for( i = 0; i < MAX_LBRR_DELAY; i++ ) {\r
316             totBytes += nBytesPerPacket[ i + 1 ];\r
317         }\r
318         SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );\r
319         payloadEnd -= nBytesPerPacket[ 0 ];\r
320         SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );\r
321 \r
322         if( !quiet ) {\r
323             fprintf( stderr, "\rPackets decoded:             %d", totPackets );\r
324         }\r
325     }\r
326 \r
327     /* Empty the recieve buffer */\r
328     for( k = 0; k < MAX_LBRR_DELAY; k++ ) {\r
329         if( nBytesPerPacket[ 0 ] == 0 ) {\r
330             /* Indicate lost packet */\r
331             lost = 1;\r
332 \r
333             /* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */\r
334             payloadPtr = payload;\r
335             for( i = 0; i < MAX_LBRR_DELAY; i++ ) {\r
336                 if( nBytesPerPacket[ i + 1 ] > 0 ) {\r
337                     starttime = GetHighResolutionTime();\r
338                     SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], i + 1, FECpayload, &nBytesFEC );\r
339                     tottime += GetHighResolutionTime() - starttime;\r
340                     if( nBytesFEC > 0 ) {\r
341                         payloadToDec = FECpayload;\r
342                         nBytes = nBytesFEC;\r
343                         lost = 0;\r
344                         break;\r
345                     }\r
346                 }\r
347                 payloadPtr += nBytesPerPacket[ i + 1 ];\r
348             }\r
349         } else {\r
350             lost = 0;\r
351             nBytes = nBytesPerPacket[ 0 ];\r
352             payloadToDec = payload;\r
353         }\r
354 \r
355         /* Silk decoder */\r
356         outPtr  = out;\r
357         tot_len = 0;\r
358 \r
359         if( lost == 0 ) {\r
360             /* No loss: Decode all frames in the packet */\r
361             frames = 0;\r
362             do {\r
363                 /* Decode 20 ms */\r
364                 starttime = GetHighResolutionTime();\r
365                 ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );\r
366                 tottime += GetHighResolutionTime() - starttime;\r
367                 if( ret ) {\r
368                     printf( "\nSKP_Silk_SDK_Decode returned %d", ret );\r
369                 }\r
370 \r
371                 frames++;\r
372                 outPtr  += len;\r
373                 tot_len += len;\r
374                 if( frames > MAX_INPUT_FRAMES ) {\r
375                     /* Hack for corrupt stream that could generate too many frames */\r
376                     outPtr  = out;\r
377                     tot_len = 0;\r
378                     frames  = 0;\r
379                 }\r
380             /* Until last 20 ms frame of packet has been decoded */\r
381             } while( DecControl.moreInternalDecoderFrames );\r
382         } else {    \r
383             /* Loss: Decode enough frames to cover one packet duration */\r
384 \r
385             /* Generate 20 ms */\r
386             for( i = 0; i < DecControl.framesPerPacket; i++ ) {\r
387                 starttime = GetHighResolutionTime();\r
388                 ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );\r
389                 tottime += GetHighResolutionTime() - starttime;\r
390                 if( ret ) {\r
391                     printf( "\nSKP_Silk_Decode returned %d", ret );\r
392                 }\r
393                 outPtr  += len;\r
394                 tot_len += len;\r
395             }\r
396         }\r
397         totPackets++;\r
398 \r
399         /* Write output to file */\r
400 #ifdef _SYSTEM_IS_BIG_ENDIAN   \r
401         swap_endian( out, tot_len );\r
402 #endif\r
403         fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );\r
404 \r
405         /* Update Buffer */\r
406         totBytes = 0;\r
407         for( i = 0; i < MAX_LBRR_DELAY; i++ ) {\r
408             totBytes += nBytesPerPacket[ i + 1 ];\r
409         }\r
410         SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );\r
411         payloadEnd -= nBytesPerPacket[ 0 ];\r
412         SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );\r
413 \r
414         if( !quiet ) {\r
415             fprintf( stderr, "\rPackets decoded:              %d", totPackets );\r
416         }\r
417     }\r
418 \r
419     filetime = totPackets * 1e-3 * packetSize_ms;\r
420     if( !quiet ) {\r
421         printf("\nFile length:                 %.3f s", filetime);\r
422         printf("\nTime for decoding:           %.3f s (%.3f%% of realtime)", 1e-6 * tottime, 1e-4 * tottime / filetime);\r
423 \r
424 #ifdef SKP_MACRO_COUNT\r
425         printf("\n \nWMOPS calculation");\r
426         printf("\nMean:                        %.3f WMOPS", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3));\r
427         printf("\nMax:                         %.3f WMOPS", (float)maxOps / ((float)packetSize_ms * 1e3));\r
428 #endif\r
429         printf("\n\n");\r
430     } else {\r
431         /* print time and % of realtime */\r
432         printf( "%.3f %.3f %d ", 1e-6 * tottime, 1e-4 * tottime / filetime, totPackets );\r
433 #ifdef SKP_MACRO_COUNT\r
434         /* print average and max WMOPS */\r
435         printf( "%.3f %.3f \n", (float)totOps / ((float)packetSize_ms * (float)totPackets * 1e3), \r
436             (float)maxOps / ((float)packetSize_ms * 1e3));\r
437 #else\r
438         printf( "%.3f %.3f \n", 0, 0);\r
439 #endif\r
440     }\r
441 \r
442     /* Free decoder */\r
443     free( psDec );\r
444 \r
445     /* Close files */\r
446     fclose( speechOutFile );\r
447     fclose( bitInFile );\r
448 \r
449     /* Save timing file if TIC/TOC used */\r
450     SKP_TimerSave("decoder_timings.txt");\r
451 \r
452     return 0;\r
453 }\r