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