Home | History | Annotate | Download | only in signal_processing
      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/signal_processing_library.h"
     18 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
     19 
     20 /* Declare function pointers. */
     21 MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
     22 MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
     23 MaxValueW16 WebRtcSpl_MaxValueW16;
     24 MaxValueW32 WebRtcSpl_MaxValueW32;
     25 MinValueW16 WebRtcSpl_MinValueW16;
     26 MinValueW32 WebRtcSpl_MinValueW32;
     27 CrossCorrelation WebRtcSpl_CrossCorrelation;
     28 DownsampleFast WebRtcSpl_DownsampleFast;
     29 ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
     30 
     31 #if (defined(WEBRTC_DETECT_NEON) || !defined(WEBRTC_HAS_NEON)) && \
     32     !defined(MIPS32_LE)
     33 /* Initialize function pointers to the generic C version. */
     34 static void InitPointersToC() {
     35   WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C;
     36   WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
     37   WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C;
     38   WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C;
     39   WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C;
     40   WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C;
     41   WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC;
     42   WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC;
     43   WebRtcSpl_ScaleAndAddVectorsWithRound =
     44       WebRtcSpl_ScaleAndAddVectorsWithRoundC;
     45 }
     46 #endif
     47 
     48 #if defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON)
     49 /* Initialize function pointers to the Neon version. */
     50 static void InitPointersToNeon() {
     51   WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon;
     52   WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon;
     53   WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon;
     54   WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon;
     55   WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon;
     56   WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon;
     57   WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon;
     58   WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon;
     59   WebRtcSpl_ScaleAndAddVectorsWithRound =
     60       WebRtcSpl_ScaleAndAddVectorsWithRoundC;
     61 }
     62 #endif
     63 
     64 #if defined(MIPS32_LE)
     65 /* Initialize function pointers to the MIPS version. */
     66 static void InitPointersToMIPS() {
     67   WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips;
     68   WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips;
     69   WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips;
     70   WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips;
     71   WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips;
     72   WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips;
     73   WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips;
     74 #if defined(MIPS_DSP_R1_LE)
     75   WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips;
     76   WebRtcSpl_ScaleAndAddVectorsWithRound =
     77       WebRtcSpl_ScaleAndAddVectorsWithRound_mips;
     78 #else
     79   WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
     80   WebRtcSpl_ScaleAndAddVectorsWithRound =
     81       WebRtcSpl_ScaleAndAddVectorsWithRoundC;
     82 #endif
     83 }
     84 #endif
     85 
     86 static void InitFunctionPointers(void) {
     87 #if defined(WEBRTC_DETECT_NEON)
     88   if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
     89     InitPointersToNeon();
     90   } else {
     91     InitPointersToC();
     92   }
     93 #elif defined(WEBRTC_HAS_NEON)
     94   InitPointersToNeon();
     95 #elif defined(MIPS32_LE)
     96   InitPointersToMIPS();
     97 #else
     98   InitPointersToC();
     99 #endif  /* WEBRTC_DETECT_NEON */
    100 }
    101 
    102 #if defined(WEBRTC_POSIX)
    103 #include <pthread.h>
    104 
    105 static void once(void (*func)(void)) {
    106   static pthread_once_t lock = PTHREAD_ONCE_INIT;
    107   pthread_once(&lock, func);
    108 }
    109 
    110 #elif defined(_WIN32)
    111 #include <windows.h>
    112 
    113 static void once(void (*func)(void)) {
    114   /* Didn't use InitializeCriticalSection() since there's no race-free context
    115    * in which to execute it.
    116    *
    117    * TODO(kma): Change to different implementation (e.g.
    118    * InterlockedCompareExchangePointer) to avoid issues similar to
    119    * http://code.google.com/p/webm/issues/detail?id=467.
    120    */
    121   static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0};
    122   static int done = 0;
    123 
    124   EnterCriticalSection(&lock);
    125   if (!done) {
    126     func();
    127     done = 1;
    128   }
    129   LeaveCriticalSection(&lock);
    130 }
    131 
    132 /* There's no fallback version as an #else block here to ensure thread safety.
    133  * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build
    134  * system should pick it up.
    135  */
    136 #endif  /* WEBRTC_POSIX */
    137 
    138 void WebRtcSpl_Init() {
    139   once(InitFunctionPointers);
    140 }
    141