1/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions
5are met:
6- Redistributions of source code must retain the above copyright notice,
7this list of conditions and the following disclaimer.
8- Redistributions in binary form must reproduce the above copyright
9notice, this list of conditions and the following disclaimer in the
10documentation and/or other materials provided with the distribution.
11- Neither the name of Internet Society, IETF or IETF Trust, nor the
12names of specific contributors, may be used to endorse or promote
13products derived from this software without specific prior written
14permission.
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25POSSIBILITY OF SUCH DAMAGE.
26***********************************************************************/
27
28#ifndef SILK_DEBUG_H
29#define SILK_DEBUG_H
30
31#include "typedef.h"
32#include <stdio.h>      /* file writing */
33#include <string.h>     /* strcpy, strcmp */
34
35#ifdef  __cplusplus
36extern "C"
37{
38#endif
39
40unsigned long GetHighResolutionTime(void); /* O  time in usec*/
41
42/* make SILK_DEBUG dependent on compiler's _DEBUG */
43#if defined _WIN32
44    #ifdef _DEBUG
45        #define SILK_DEBUG  1
46    #else
47        #define SILK_DEBUG  0
48    #endif
49
50    /* overrule the above */
51    #if 0
52    /*  #define NO_ASSERTS*/
53    #undef  SILK_DEBUG
54    #define SILK_DEBUG  1
55    #endif
56#else
57    #define SILK_DEBUG  0
58#endif
59
60/* Flag for using timers */
61#define SILK_TIC_TOC    0
62
63
64#if SILK_TIC_TOC
65
66#if (defined(_WIN32) || defined(_WINCE))
67#include <windows.h>    /* timer */
68#else   /* Linux or Mac*/
69#include <sys/time.h>
70#endif
71
72/*********************************/
73/* timer functions for profiling */
74/*********************************/
75/* example:                                                         */
76/*                                                                  */
77/* TIC(LPC)                                                         */
78/* do_LPC(in_vec, order, acoef);    // do LPC analysis              */
79/* TOC(LPC)                                                         */
80/*                                                                  */
81/* and call the following just before exiting (from main)           */
82/*                                                                  */
83/* silk_TimerSave("silk_TimingData.txt");                           */
84/*                                                                  */
85/* results are now in silk_TimingData.txt                           */
86
87void silk_TimerSave(char *file_name);
88
89/* max number of timers (in different locations) */
90#define silk_NUM_TIMERS_MAX                  50
91/* max length of name tags in TIC(..), TOC(..) */
92#define silk_NUM_TIMERS_MAX_TAG_LEN          30
93
94extern int           silk_Timer_nTimers;
95extern int           silk_Timer_depth_ctr;
96extern char          silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
97#ifdef _WIN32
98extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
99#else
100extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
101#endif
102extern unsigned int  silk_Timer_cnt[silk_NUM_TIMERS_MAX];
103extern opus_int64    silk_Timer_sum[silk_NUM_TIMERS_MAX];
104extern opus_int64    silk_Timer_max[silk_NUM_TIMERS_MAX];
105extern opus_int64    silk_Timer_min[silk_NUM_TIMERS_MAX];
106extern opus_int64    silk_Timer_depth[silk_NUM_TIMERS_MAX];
107
108/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */
109#ifdef _WIN32
110#define TIC(TAG_NAME) {                                     \
111    static int init = 0;                                    \
112    static int ID = -1;                                     \
113    if( init == 0 )                                         \
114    {                                                       \
115        int k;                                              \
116        init = 1;                                           \
117        for( k = 0; k < silk_Timer_nTimers; k++ ) {         \
118            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
119                ID = k;                                     \
120                break;                                      \
121            }                                               \
122        }                                                   \
123        if (ID == -1) {                                     \
124            ID = silk_Timer_nTimers;                        \
125            silk_Timer_nTimers++;                           \
126            silk_Timer_depth[ID] = silk_Timer_depth_ctr;    \
127            strcpy(silk_Timer_tags[ID], #TAG_NAME);         \
128            silk_Timer_cnt[ID] = 0;                         \
129            silk_Timer_sum[ID] = 0;                         \
130            silk_Timer_min[ID] = 0xFFFFFFFF;                \
131            silk_Timer_max[ID] = 0;                         \
132        }                                                   \
133    }                                                       \
134    silk_Timer_depth_ctr++;                                 \
135    QueryPerformanceCounter(&silk_Timer_start[ID]);         \
136}
137#else
138#define TIC(TAG_NAME) {                                     \
139    static int init = 0;                                    \
140    static int ID = -1;                                     \
141    if( init == 0 )                                         \
142    {                                                       \
143        int k;                                              \
144        init = 1;                                           \
145        for( k = 0; k < silk_Timer_nTimers; k++ ) {         \
146        if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {  \
147                ID = k;                                     \
148                break;                                      \
149            }                                               \
150        }                                                   \
151        if (ID == -1) {                                     \
152            ID = silk_Timer_nTimers;                        \
153            silk_Timer_nTimers++;                           \
154            silk_Timer_depth[ID] = silk_Timer_depth_ctr;    \
155            strcpy(silk_Timer_tags[ID], #TAG_NAME);         \
156            silk_Timer_cnt[ID] = 0;                         \
157            silk_Timer_sum[ID] = 0;                         \
158            silk_Timer_min[ID] = 0xFFFFFFFF;                \
159            silk_Timer_max[ID] = 0;                         \
160        }                                                   \
161    }                                                       \
162    silk_Timer_depth_ctr++;                                 \
163    silk_Timer_start[ID] = GetHighResolutionTime();         \
164}
165#endif
166
167#ifdef _WIN32
168#define TOC(TAG_NAME) {                                             \
169    LARGE_INTEGER lpPerformanceCount;                               \
170    static int init = 0;                                            \
171    static int ID = 0;                                              \
172    if( init == 0 )                                                 \
173    {                                                               \
174        int k;                                                      \
175        init = 1;                                                   \
176        for( k = 0; k < silk_Timer_nTimers; k++ ) {                 \
177            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {      \
178                ID = k;                                             \
179                break;                                              \
180            }                                                       \
181        }                                                           \
182    }                                                               \
183    QueryPerformanceCounter(&lpPerformanceCount);                   \
184    lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart;   \
185    if((lpPerformanceCount.QuadPart < 100000000) &&                 \
186        (lpPerformanceCount.QuadPart >= 0)) {                       \
187        silk_Timer_cnt[ID]++;                                       \
188        silk_Timer_sum[ID] += lpPerformanceCount.QuadPart;          \
189        if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] )      \
190            silk_Timer_max[ID] = lpPerformanceCount.QuadPart;       \
191        if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] )      \
192            silk_Timer_min[ID] = lpPerformanceCount.QuadPart;       \
193    }                                                               \
194    silk_Timer_depth_ctr--;                                         \
195}
196#else
197#define TOC(TAG_NAME) {                                             \
198    unsigned long endTime;                                          \
199    static int init = 0;                                            \
200    static int ID = 0;                                              \
201    if( init == 0 )                                                 \
202    {                                                               \
203        int k;                                                      \
204        init = 1;                                                   \
205        for( k = 0; k < silk_Timer_nTimers; k++ ) {                 \
206            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {      \
207                ID = k;                                             \
208                break;                                              \
209            }                                                       \
210        }                                                           \
211    }                                                               \
212    endTime = GetHighResolutionTime();                              \
213    endTime -= silk_Timer_start[ID];                                \
214    if((endTime < 100000000) &&                                     \
215        (endTime >= 0)) {                                           \
216        silk_Timer_cnt[ID]++;                                       \
217        silk_Timer_sum[ID] += endTime;                              \
218        if( endTime > silk_Timer_max[ID] )                          \
219            silk_Timer_max[ID] = endTime;                           \
220        if( endTime < silk_Timer_min[ID] )                          \
221            silk_Timer_min[ID] = endTime;                           \
222    }                                                               \
223        silk_Timer_depth_ctr--;                                     \
224}
225#endif
226
227#else /* SILK_TIC_TOC */
228
229/* define macros as empty strings */
230#define TIC(TAG_NAME)
231#define TOC(TAG_NAME)
232#define silk_TimerSave(FILE_NAME)
233
234#endif /* SILK_TIC_TOC */
235
236
237#if SILK_DEBUG
238/************************************/
239/* write data to file for debugging */
240/************************************/
241/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */
242
243#define silk_NUM_STORES_MAX                                  100
244extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
245extern int silk_debug_store_count;
246
247/* Faster way of storing the data */
248#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) {          \
249    static opus_int init = 0, cnt = 0;                              \
250    static FILE **fp;                                               \
251    if (init == 0) {                                                \
252        init = 1;                                                   \
253        cnt = silk_debug_store_count++;                             \
254        silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb");       \
255    }                                                               \
256    fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]);   \
257}
258
259/* Call this at the end of main() */
260#define SILK_DEBUG_STORE_CLOSE_FILES {                              \
261    opus_int i;                                                     \
262    for( i = 0; i < silk_debug_store_count; i++ ) {                 \
263        fclose( silk_debug_store_fp[ i ] );                         \
264    }                                                               \
265}
266
267#else /* SILK_DEBUG */
268
269/* define macros as empty strings */
270#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
271#define SILK_DEBUG_STORE_CLOSE_FILES
272
273#endif /* SILK_DEBUG */
274
275#ifdef  __cplusplus
276}
277#endif
278
279#endif /* SILK_DEBUG_H */
280