1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* The global function contained in this file initializes SPL function 12 * pointers, currently only for ARM platforms. 13 * 14 * Some code came from common/rtcd.c in the WebM project. 15 */ 16 17 #include "webrtc/common_audio/signal_processing/include/real_fft.h" 18 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 19 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" 20 21 /* Declare function pointers. */ 22 MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16; 23 MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32; 24 MaxValueW16 WebRtcSpl_MaxValueW16; 25 MaxValueW32 WebRtcSpl_MaxValueW32; 26 MinValueW16 WebRtcSpl_MinValueW16; 27 MinValueW32 WebRtcSpl_MinValueW32; 28 CrossCorrelation WebRtcSpl_CrossCorrelation; 29 DownsampleFast WebRtcSpl_DownsampleFast; 30 ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound; 31 CreateRealFFT WebRtcSpl_CreateRealFFT; 32 FreeRealFFT WebRtcSpl_FreeRealFFT; 33 RealForwardFFT WebRtcSpl_RealForwardFFT; 34 RealInverseFFT WebRtcSpl_RealInverseFFT; 35 36 #if (defined(WEBRTC_DETECT_ARM_NEON) || !defined(WEBRTC_ARCH_ARM_NEON)) && \ 37 !defined(MIPS32_LE) 38 /* Initialize function pointers to the generic C version. */ InitPointersToC()39static void InitPointersToC() { 40 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C; 41 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 42 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C; 43 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C; 44 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C; 45 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C; 46 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC; 47 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC; 48 WebRtcSpl_ScaleAndAddVectorsWithRound = 49 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 50 WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTC; 51 WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTC; 52 WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTC; 53 WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTC; 54 } 55 #endif 56 57 #if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON) 58 /* Initialize function pointers to the Neon version. */ InitPointersToNeon()59static void InitPointersToNeon() { 60 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon; 61 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon; 62 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon; 63 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon; 64 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon; 65 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon; 66 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon; 67 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon; 68 /* TODO(henrik.lundin): re-enable NEON when the crash from bug 3243 is 69 understood. */ 70 WebRtcSpl_ScaleAndAddVectorsWithRound = 71 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 72 WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTNeon; 73 WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTNeon; 74 WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTNeon; 75 WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTNeon; 76 } 77 #endif 78 79 #if defined(MIPS32_LE) 80 /* Initialize function pointers to the MIPS version. */ InitPointersToMIPS()81static void InitPointersToMIPS() { 82 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips; 83 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips; 84 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips; 85 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips; 86 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips; 87 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips; 88 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips; 89 WebRtcSpl_CreateRealFFT = WebRtcSpl_CreateRealFFTC; 90 WebRtcSpl_FreeRealFFT = WebRtcSpl_FreeRealFFTC; 91 WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTC; 92 WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTC; 93 #if defined(MIPS_DSP_R1_LE) 94 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips; 95 WebRtcSpl_ScaleAndAddVectorsWithRound = 96 WebRtcSpl_ScaleAndAddVectorsWithRound_mips; 97 #else 98 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 99 WebRtcSpl_ScaleAndAddVectorsWithRound = 100 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 101 #endif 102 } 103 #endif 104 InitFunctionPointers(void)105static void InitFunctionPointers(void) { 106 #if defined(WEBRTC_DETECT_ARM_NEON) 107 if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) { 108 InitPointersToNeon(); 109 } else { 110 InitPointersToC(); 111 } 112 #elif defined(WEBRTC_ARCH_ARM_NEON) 113 InitPointersToNeon(); 114 #elif defined(MIPS32_LE) 115 InitPointersToMIPS(); 116 #else 117 InitPointersToC(); 118 #endif /* WEBRTC_DETECT_ARM_NEON */ 119 } 120 121 #if defined(WEBRTC_POSIX) 122 #include <pthread.h> 123 once(void (* func)(void))124static void once(void (*func)(void)) { 125 static pthread_once_t lock = PTHREAD_ONCE_INIT; 126 pthread_once(&lock, func); 127 } 128 129 #elif defined(_WIN32) 130 #include <windows.h> 131 once(void (* func)(void))132static void once(void (*func)(void)) { 133 /* Didn't use InitializeCriticalSection() since there's no race-free context 134 * in which to execute it. 135 * 136 * TODO(kma): Change to different implementation (e.g. 137 * InterlockedCompareExchangePointer) to avoid issues similar to 138 * http://code.google.com/p/webm/issues/detail?id=467. 139 */ 140 static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0}; 141 static int done = 0; 142 143 EnterCriticalSection(&lock); 144 if (!done) { 145 func(); 146 done = 1; 147 } 148 LeaveCriticalSection(&lock); 149 } 150 151 /* There's no fallback version as an #else block here to ensure thread safety. 152 * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build 153 * system should pick it up. 154 */ 155 #endif /* WEBRTC_POSIX */ 156 WebRtcSpl_Init()157void WebRtcSpl_Init() { 158 once(InitFunctionPointers); 159 } 160