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