content/media/webaudio/WebAudioUtils.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/webaudio/WebAudioUtils.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,231 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef WebAudioUtils_h_
    1.11 +#define WebAudioUtils_h_
    1.12 +
    1.13 +#include <cmath>
    1.14 +#include <limits>
    1.15 +#include "mozilla/TypeTraits.h"
    1.16 +#include "mozilla/FloatingPoint.h"
    1.17 +#include "MediaSegment.h"
    1.18 +
    1.19 +// Forward declaration
    1.20 +typedef struct SpeexResamplerState_ SpeexResamplerState;
    1.21 +
    1.22 +namespace mozilla {
    1.23 +
    1.24 +class AudioNodeStream;
    1.25 +
    1.26 +namespace dom {
    1.27 +
    1.28 +class AudioParamTimeline;
    1.29 +
    1.30 +namespace WebAudioUtils {
    1.31 +  // 32 is the minimum required by the spec for createBuffer() and
    1.32 +  // createScriptProcessor() and matches what is used by Blink.  The limit
    1.33 +  // protects against large memory allocations.
    1.34 +  const uint32_t MaxChannelCount = 32;
    1.35 +  // AudioContext::CreateBuffer() "must support sample-rates in at least the
    1.36 +  // range 22050 to 96000."
    1.37 +  const uint32_t MinSampleRate = 8000;
    1.38 +  const uint32_t MaxSampleRate = 192000;
    1.39 +
    1.40 +  inline bool FuzzyEqual(float v1, float v2)
    1.41 +  {
    1.42 +    using namespace std;
    1.43 +    return fabsf(v1 - v2) < 1e-7f;
    1.44 +  }
    1.45 +  inline bool FuzzyEqual(double v1, double v2)
    1.46 +  {
    1.47 +    using namespace std;
    1.48 +    return fabs(v1 - v2) < 1e-7;
    1.49 +  }
    1.50 +
    1.51 +  /**
    1.52 +   * Computes an exponential smoothing rate for a time based variable
    1.53 +   * over aDuration seconds.
    1.54 +   */
    1.55 +  inline double ComputeSmoothingRate(double aDuration, double aSampleRate)
    1.56 +  {
    1.57 +    return 1.0 - std::exp(-1.0 / (aDuration * aSampleRate));
    1.58 +  }
    1.59 +
    1.60 +  /**
    1.61 +   * Converts AudioParamTimeline floating point time values to tick values
    1.62 +   * with respect to a source and a destination AudioNodeStream.
    1.63 +   *
    1.64 +   * This needs to be called for each AudioParamTimeline that gets sent to an
    1.65 +   * AudioNodeEngine on the engine side where the AudioParamTimeline is
    1.66 +   * received.  This means that such engines need to be aware of their source
    1.67 +   * and destination streams as well.
    1.68 +   */
    1.69 +  void ConvertAudioParamToTicks(AudioParamTimeline& aParam,
    1.70 +                                AudioNodeStream* aSource,
    1.71 +                                AudioNodeStream* aDest);
    1.72 +
    1.73 +  /**
    1.74 +   * Converts a linear value to decibels.  Returns aMinDecibels if the linear
    1.75 +   * value is 0.
    1.76 +   */
    1.77 +  inline float ConvertLinearToDecibels(float aLinearValue, float aMinDecibels)
    1.78 +  {
    1.79 +    return aLinearValue ? 20.0f * std::log10(aLinearValue) : aMinDecibels;
    1.80 +  }
    1.81 +
    1.82 +  /**
    1.83 +   * Converts a decibel value to a linear value.
    1.84 +   */
    1.85 +  inline float ConvertDecibelsToLinear(float aDecibels)
    1.86 +  {
    1.87 +    return std::pow(10.0f, 0.05f * aDecibels);
    1.88 +  }
    1.89 +
    1.90 +  /**
    1.91 +   * Converts a decibel to a linear value.
    1.92 +   */
    1.93 +  inline float ConvertDecibelToLinear(float aDecibel)
    1.94 +  {
    1.95 +    return std::pow(10.0f, 0.05f * aDecibel);
    1.96 +  }
    1.97 +
    1.98 +  inline void FixNaN(double& aDouble)
    1.99 +  {
   1.100 +    if (IsNaN(aDouble) || IsInfinite(aDouble)) {
   1.101 +      aDouble = 0.0;
   1.102 +    }
   1.103 +  }
   1.104 +
   1.105 +  inline double DiscreteTimeConstantForSampleRate(double timeConstant, double sampleRate)
   1.106 +  {
   1.107 +    return 1.0 - std::exp(-1.0 / (sampleRate * timeConstant));
   1.108 +  }
   1.109 +
   1.110 +  inline bool IsTimeValid(double aTime)
   1.111 +  {
   1.112 +    return aTime >= 0 &&  aTime <= (MEDIA_TIME_MAX >> MEDIA_TIME_FRAC_BITS);
   1.113 +  }
   1.114 +
   1.115 +  /**
   1.116 +   * Converts a floating point value to an integral type in a safe and
   1.117 +   * platform agnostic way.  The following program demonstrates the kinds
   1.118 +   * of ways things can go wrong depending on the CPU architecture you're
   1.119 +   * compiling for:
   1.120 +   *
   1.121 +   * #include <stdio.h>
   1.122 +   * volatile float r;
   1.123 +   * int main()
   1.124 +   * {
   1.125 +   *   unsigned int q;
   1.126 +   *   r = 1e100;
   1.127 +   *   q = r;
   1.128 +   *   printf("%f %d\n", r, q);
   1.129 +   *   r = -1e100;
   1.130 +   *   q = r;
   1.131 +   *   printf("%f %d\n", r, q);
   1.132 +   *   r = 1e15;
   1.133 +   *   q = r;
   1.134 +   *   printf("%f %x\n", r, q);
   1.135 +   *   r = 0/0.;
   1.136 +   *   q = r;
   1.137 +   *   printf("%f %d\n", r, q);
   1.138 +   * }
   1.139 +   *
   1.140 +   * This program, when compiled for unsigned int, generates the following
   1.141 +   * results depending on the architecture:
   1.142 +   *
   1.143 +   * x86 and x86-64
   1.144 +   * ---
   1.145 +   *  inf 0
   1.146 +   *  -inf 0
   1.147 +   *  999999995904.000000 -727384064 d4a50000
   1.148 +   *  nan 0
   1.149 +   *
   1.150 +   * ARM
   1.151 +   * ---
   1.152 +   *  inf -1
   1.153 +   *  -inf 0
   1.154 +   *  999999995904.000000 -1
   1.155 +   *  nan 0
   1.156 +   *
   1.157 +   * When compiled for int, this program generates the following results:
   1.158 +   *
   1.159 +   * x86 and x86-64
   1.160 +   * ---
   1.161 +   *  inf -2147483648
   1.162 +   *  -inf -2147483648
   1.163 +   *  999999995904.000000 -2147483648
   1.164 +   *  nan -2147483648
   1.165 +   *
   1.166 +   * ARM
   1.167 +   * ---
   1.168 +   *  inf 2147483647
   1.169 +   *  -inf -2147483648
   1.170 +   *  999999995904.000000 2147483647
   1.171 +   *  nan 0
   1.172 +   *
   1.173 +   * Note that the caller is responsible to make sure that the value
   1.174 +   * passed to this function is not a NaN.  This function will abort if
   1.175 +   * it sees a NaN.
   1.176 +   */
   1.177 +  template <typename IntType, typename FloatType>
   1.178 +  IntType TruncateFloatToInt(FloatType f)
   1.179 +  {
   1.180 +    using namespace std;
   1.181 +
   1.182 +    static_assert(mozilla::IsIntegral<IntType>::value == true,
   1.183 +                  "IntType must be an integral type");
   1.184 +    static_assert(mozilla::IsFloatingPoint<FloatType>::value == true,
   1.185 +                  "FloatType must be a floating point type");
   1.186 +
   1.187 +    if (f != f) {
   1.188 +      // It is the responsibility of the caller to deal with NaN values.
   1.189 +      // If we ever get to this point, we have a serious bug to fix.
   1.190 +      NS_RUNTIMEABORT("We should never see a NaN here");
   1.191 +    }
   1.192 +
   1.193 +    if (f > FloatType(numeric_limits<IntType>::max())) {
   1.194 +      // If the floating point value is outside of the range of maximum
   1.195 +      // integral value for this type, just clamp to the maximum value.
   1.196 +      return numeric_limits<IntType>::max();
   1.197 +    }
   1.198 +
   1.199 +    if (f < FloatType(numeric_limits<IntType>::min())) {
   1.200 +      // If the floating point value is outside of the range of minimum
   1.201 +      // integral value for this type, just clamp to the minimum value.
   1.202 +      return numeric_limits<IntType>::min();
   1.203 +    }
   1.204 +
   1.205 +    // Otherwise, this conversion must be well defined.
   1.206 +    return IntType(f);
   1.207 +  }
   1.208 +
   1.209 +  void Shutdown();
   1.210 +
   1.211 +  int
   1.212 +  SpeexResamplerProcess(SpeexResamplerState* aResampler,
   1.213 +                        uint32_t aChannel,
   1.214 +                        const float* aIn, uint32_t* aInLen,
   1.215 +                        float* aOut, uint32_t* aOutLen);
   1.216 +
   1.217 +  int
   1.218 +  SpeexResamplerProcess(SpeexResamplerState* aResampler,
   1.219 +                        uint32_t aChannel,
   1.220 +                        const int16_t* aIn, uint32_t* aInLen,
   1.221 +                        float* aOut, uint32_t* aOutLen);
   1.222 +
   1.223 +  int
   1.224 +  SpeexResamplerProcess(SpeexResamplerState* aResampler,
   1.225 +                        uint32_t aChannel,
   1.226 +                        const int16_t* aIn, uint32_t* aInLen,
   1.227 +                        int16_t* aOut, uint32_t* aOutLen);
   1.228 +  }
   1.229 +
   1.230 +}
   1.231 +}
   1.232 +
   1.233 +#endif
   1.234 +

mercurial