michael@0: /*********************************************************************** michael@0: Copyright (c) 2006-2011, Skype Limited. All rights reserved. michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions michael@0: are met: michael@0: - Redistributions of source code must retain the above copyright notice, michael@0: this list of conditions and the following disclaimer. michael@0: - Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: - Neither the name of Internet Society, IETF or IETF Trust, nor the michael@0: names of specific contributors, may be used to endorse or promote michael@0: products derived from this software without specific prior written michael@0: permission. michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" michael@0: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE michael@0: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE michael@0: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE michael@0: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR michael@0: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF michael@0: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS michael@0: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN michael@0: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE michael@0: POSSIBILITY OF SUCH DAMAGE. michael@0: ***********************************************************************/ michael@0: michael@0: #ifndef SILK_DEBUG_H michael@0: #define SILK_DEBUG_H michael@0: michael@0: #include "typedef.h" michael@0: #include /* file writing */ michael@0: #include /* strcpy, strcmp */ michael@0: michael@0: #ifdef __cplusplus michael@0: extern "C" michael@0: { michael@0: #endif michael@0: michael@0: unsigned long GetHighResolutionTime(void); /* O time in usec*/ michael@0: michael@0: /* make SILK_DEBUG dependent on compiler's _DEBUG */ michael@0: #if defined _WIN32 michael@0: #ifdef _DEBUG michael@0: #define SILK_DEBUG 1 michael@0: #else michael@0: #define SILK_DEBUG 0 michael@0: #endif michael@0: michael@0: /* overrule the above */ michael@0: #if 0 michael@0: /* #define NO_ASSERTS*/ michael@0: #undef SILK_DEBUG michael@0: #define SILK_DEBUG 1 michael@0: #endif michael@0: #else michael@0: #define SILK_DEBUG 0 michael@0: #endif michael@0: michael@0: /* Flag for using timers */ michael@0: #define SILK_TIC_TOC 0 michael@0: michael@0: michael@0: #if SILK_TIC_TOC michael@0: michael@0: #if (defined(_WIN32) || defined(_WINCE)) michael@0: #include /* timer */ michael@0: #else /* Linux or Mac*/ michael@0: #include michael@0: #endif michael@0: michael@0: /*********************************/ michael@0: /* timer functions for profiling */ michael@0: /*********************************/ michael@0: /* example: */ michael@0: /* */ michael@0: /* TIC(LPC) */ michael@0: /* do_LPC(in_vec, order, acoef); // do LPC analysis */ michael@0: /* TOC(LPC) */ michael@0: /* */ michael@0: /* and call the following just before exiting (from main) */ michael@0: /* */ michael@0: /* silk_TimerSave("silk_TimingData.txt"); */ michael@0: /* */ michael@0: /* results are now in silk_TimingData.txt */ michael@0: michael@0: void silk_TimerSave(char *file_name); michael@0: michael@0: /* max number of timers (in different locations) */ michael@0: #define silk_NUM_TIMERS_MAX 50 michael@0: /* max length of name tags in TIC(..), TOC(..) */ michael@0: #define silk_NUM_TIMERS_MAX_TAG_LEN 30 michael@0: michael@0: extern int silk_Timer_nTimers; michael@0: extern int silk_Timer_depth_ctr; michael@0: extern char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN]; michael@0: #ifdef _WIN32 michael@0: extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX]; michael@0: #else michael@0: extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX]; michael@0: #endif michael@0: extern unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX]; michael@0: extern opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX]; michael@0: extern opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX]; michael@0: extern opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX]; michael@0: extern opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX]; michael@0: michael@0: /* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */ michael@0: #ifdef _WIN32 michael@0: #define TIC(TAG_NAME) { \ michael@0: static int init = 0; \ michael@0: static int ID = -1; \ michael@0: if( init == 0 ) \ michael@0: { \ michael@0: int k; \ michael@0: init = 1; \ michael@0: for( k = 0; k < silk_Timer_nTimers; k++ ) { \ michael@0: if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ michael@0: ID = k; \ michael@0: break; \ michael@0: } \ michael@0: } \ michael@0: if (ID == -1) { \ michael@0: ID = silk_Timer_nTimers; \ michael@0: silk_Timer_nTimers++; \ michael@0: silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ michael@0: strcpy(silk_Timer_tags[ID], #TAG_NAME); \ michael@0: silk_Timer_cnt[ID] = 0; \ michael@0: silk_Timer_sum[ID] = 0; \ michael@0: silk_Timer_min[ID] = 0xFFFFFFFF; \ michael@0: silk_Timer_max[ID] = 0; \ michael@0: } \ michael@0: } \ michael@0: silk_Timer_depth_ctr++; \ michael@0: QueryPerformanceCounter(&silk_Timer_start[ID]); \ michael@0: } michael@0: #else michael@0: #define TIC(TAG_NAME) { \ michael@0: static int init = 0; \ michael@0: static int ID = -1; \ michael@0: if( init == 0 ) \ michael@0: { \ michael@0: int k; \ michael@0: init = 1; \ michael@0: for( k = 0; k < silk_Timer_nTimers; k++ ) { \ michael@0: if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ michael@0: ID = k; \ michael@0: break; \ michael@0: } \ michael@0: } \ michael@0: if (ID == -1) { \ michael@0: ID = silk_Timer_nTimers; \ michael@0: silk_Timer_nTimers++; \ michael@0: silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ michael@0: strcpy(silk_Timer_tags[ID], #TAG_NAME); \ michael@0: silk_Timer_cnt[ID] = 0; \ michael@0: silk_Timer_sum[ID] = 0; \ michael@0: silk_Timer_min[ID] = 0xFFFFFFFF; \ michael@0: silk_Timer_max[ID] = 0; \ michael@0: } \ michael@0: } \ michael@0: silk_Timer_depth_ctr++; \ michael@0: silk_Timer_start[ID] = GetHighResolutionTime(); \ michael@0: } michael@0: #endif michael@0: michael@0: #ifdef _WIN32 michael@0: #define TOC(TAG_NAME) { \ michael@0: LARGE_INTEGER lpPerformanceCount; \ michael@0: static int init = 0; \ michael@0: static int ID = 0; \ michael@0: if( init == 0 ) \ michael@0: { \ michael@0: int k; \ michael@0: init = 1; \ michael@0: for( k = 0; k < silk_Timer_nTimers; k++ ) { \ michael@0: if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ michael@0: ID = k; \ michael@0: break; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: QueryPerformanceCounter(&lpPerformanceCount); \ michael@0: lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \ michael@0: if((lpPerformanceCount.QuadPart < 100000000) && \ michael@0: (lpPerformanceCount.QuadPart >= 0)) { \ michael@0: silk_Timer_cnt[ID]++; \ michael@0: silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \ michael@0: if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \ michael@0: silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \ michael@0: if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \ michael@0: silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \ michael@0: } \ michael@0: silk_Timer_depth_ctr--; \ michael@0: } michael@0: #else michael@0: #define TOC(TAG_NAME) { \ michael@0: unsigned long endTime; \ michael@0: static int init = 0; \ michael@0: static int ID = 0; \ michael@0: if( init == 0 ) \ michael@0: { \ michael@0: int k; \ michael@0: init = 1; \ michael@0: for( k = 0; k < silk_Timer_nTimers; k++ ) { \ michael@0: if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ michael@0: ID = k; \ michael@0: break; \ michael@0: } \ michael@0: } \ michael@0: } \ michael@0: endTime = GetHighResolutionTime(); \ michael@0: endTime -= silk_Timer_start[ID]; \ michael@0: if((endTime < 100000000) && \ michael@0: (endTime >= 0)) { \ michael@0: silk_Timer_cnt[ID]++; \ michael@0: silk_Timer_sum[ID] += endTime; \ michael@0: if( endTime > silk_Timer_max[ID] ) \ michael@0: silk_Timer_max[ID] = endTime; \ michael@0: if( endTime < silk_Timer_min[ID] ) \ michael@0: silk_Timer_min[ID] = endTime; \ michael@0: } \ michael@0: silk_Timer_depth_ctr--; \ michael@0: } michael@0: #endif michael@0: michael@0: #else /* SILK_TIC_TOC */ michael@0: michael@0: /* define macros as empty strings */ michael@0: #define TIC(TAG_NAME) michael@0: #define TOC(TAG_NAME) michael@0: #define silk_TimerSave(FILE_NAME) michael@0: michael@0: #endif /* SILK_TIC_TOC */ michael@0: michael@0: michael@0: #if SILK_DEBUG michael@0: /************************************/ michael@0: /* write data to file for debugging */ michael@0: /************************************/ michael@0: /* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */ michael@0: michael@0: #define silk_NUM_STORES_MAX 100 michael@0: extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ]; michael@0: extern int silk_debug_store_count; michael@0: michael@0: /* Faster way of storing the data */ michael@0: #define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ michael@0: static opus_int init = 0, cnt = 0; \ michael@0: static FILE **fp; \ michael@0: if (init == 0) { \ michael@0: init = 1; \ michael@0: cnt = silk_debug_store_count++; \ michael@0: silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \ michael@0: } \ michael@0: fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \ michael@0: } michael@0: michael@0: /* Call this at the end of main() */ michael@0: #define SILK_DEBUG_STORE_CLOSE_FILES { \ michael@0: opus_int i; \ michael@0: for( i = 0; i < silk_debug_store_count; i++ ) { \ michael@0: fclose( silk_debug_store_fp[ i ] ); \ michael@0: } \ michael@0: } michael@0: michael@0: #else /* SILK_DEBUG */ michael@0: michael@0: /* define macros as empty strings */ michael@0: #define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) michael@0: #define SILK_DEBUG_STORE_CLOSE_FILES michael@0: michael@0: #endif /* SILK_DEBUG */ michael@0: michael@0: #ifdef __cplusplus michael@0: } michael@0: #endif michael@0: michael@0: #endif /* SILK_DEBUG_H */