content/media/AudioSampleFormat.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/media/AudioSampleFormat.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,183 @@
     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 +#ifndef MOZILLA_AUDIOSAMPLEFORMAT_H_
    1.10 +#define MOZILLA_AUDIOSAMPLEFORMAT_H_
    1.11 +
    1.12 +#include "nsAlgorithm.h"
    1.13 +#include <algorithm>
    1.14 +
    1.15 +namespace mozilla {
    1.16 +
    1.17 +/**
    1.18 + * Audio formats supported in MediaStreams and media elements.
    1.19 + *
    1.20 + * Only one of these is supported by AudioStream, and that is determined
    1.21 + * at compile time (roughly, FLOAT32 on desktops, S16 on mobile). Media decoders
    1.22 + * produce that format only; queued AudioData always uses that format.
    1.23 + */
    1.24 +enum AudioSampleFormat
    1.25 +{
    1.26 +  // Native-endian signed 16-bit audio samples
    1.27 +  AUDIO_FORMAT_S16,
    1.28 +  // Signed 32-bit float samples
    1.29 +  AUDIO_FORMAT_FLOAT32,
    1.30 +  // Silence: format will be chosen later
    1.31 +  AUDIO_FORMAT_SILENCE,
    1.32 +  // The format used for output by AudioStream.
    1.33 +#ifdef MOZ_SAMPLE_TYPE_S16
    1.34 +  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_S16
    1.35 +#else
    1.36 +  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_FLOAT32
    1.37 +#endif
    1.38 +};
    1.39 +
    1.40 +enum {
    1.41 +  MAX_AUDIO_SAMPLE_SIZE = sizeof(float)
    1.42 +};
    1.43 +
    1.44 +template <AudioSampleFormat Format> class AudioSampleTraits;
    1.45 +
    1.46 +template <> class AudioSampleTraits<AUDIO_FORMAT_FLOAT32> {
    1.47 +public:
    1.48 +  typedef float Type;
    1.49 +};
    1.50 +template <> class AudioSampleTraits<AUDIO_FORMAT_S16> {
    1.51 +public:
    1.52 +  typedef int16_t Type;
    1.53 +};
    1.54 +
    1.55 +typedef AudioSampleTraits<AUDIO_OUTPUT_FORMAT>::Type AudioDataValue;
    1.56 +
    1.57 +template<typename T> class AudioSampleTypeToFormat;
    1.58 +
    1.59 +template <> class AudioSampleTypeToFormat<float> {
    1.60 +public:
    1.61 +  static const AudioSampleFormat Format = AUDIO_FORMAT_FLOAT32;
    1.62 +};
    1.63 +
    1.64 +template <> class AudioSampleTypeToFormat<short> {
    1.65 +public:
    1.66 +  static const AudioSampleFormat Format = AUDIO_FORMAT_S16;
    1.67 +};
    1.68 +
    1.69 +// Single-sample conversion
    1.70 +/*
    1.71 + * Use "2^N" conversion since it's simple, fast, "bit transparent", used by
    1.72 + * many other libraries and apparently behaves reasonably.
    1.73 + * http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html
    1.74 + * http://blog.bjornroche.com/2009/12/linearity-and-dynamic-range-in-int.html
    1.75 + */
    1.76 +inline float
    1.77 +AudioSampleToFloat(float aValue)
    1.78 +{
    1.79 +  return aValue;
    1.80 +}
    1.81 +inline float
    1.82 +AudioSampleToFloat(int16_t aValue)
    1.83 +{
    1.84 +  return aValue/32768.0f;
    1.85 +}
    1.86 +
    1.87 +template <typename T> T FloatToAudioSample(float aValue);
    1.88 +
    1.89 +template <> inline float
    1.90 +FloatToAudioSample<float>(float aValue)
    1.91 +{
    1.92 +  return aValue;
    1.93 +}
    1.94 +template <> inline int16_t
    1.95 +FloatToAudioSample<int16_t>(float aValue)
    1.96 +{
    1.97 +  float v = aValue*32768.0f;
    1.98 +  float clamped = std::max(-32768.0f, std::min(32767.0f, v));
    1.99 +  return int16_t(clamped);
   1.100 +}
   1.101 +
   1.102 +// Sample buffer conversion
   1.103 +
   1.104 +template <typename From, typename To> inline void
   1.105 +ConvertAudioSamples(const From* aFrom, To* aTo, int aCount)
   1.106 +{
   1.107 +  for (int i = 0; i < aCount; ++i) {
   1.108 +    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i]));
   1.109 +  }
   1.110 +}
   1.111 +inline void
   1.112 +ConvertAudioSamples(const int16_t* aFrom, int16_t* aTo, int aCount)
   1.113 +{
   1.114 +  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
   1.115 +}
   1.116 +inline void
   1.117 +ConvertAudioSamples(const float* aFrom, float* aTo, int aCount)
   1.118 +{
   1.119 +  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
   1.120 +}
   1.121 +
   1.122 +// Sample buffer conversion with scale
   1.123 +
   1.124 +template <typename From, typename To> inline void
   1.125 +ConvertAudioSamplesWithScale(const From* aFrom, To* aTo, int aCount, float aScale)
   1.126 +{
   1.127 +  if (aScale == 1.0f) {
   1.128 +    ConvertAudioSamples(aFrom, aTo, aCount);
   1.129 +    return;
   1.130 +  }
   1.131 +  for (int i = 0; i < aCount; ++i) {
   1.132 +    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i])*aScale);
   1.133 +  }
   1.134 +}
   1.135 +inline void
   1.136 +ConvertAudioSamplesWithScale(const int16_t* aFrom, int16_t* aTo, int aCount, float aScale)
   1.137 +{
   1.138 +  if (aScale == 1.0f) {
   1.139 +    ConvertAudioSamples(aFrom, aTo, aCount);
   1.140 +    return;
   1.141 +  }
   1.142 +  if (0.0f <= aScale && aScale < 1.0f) {
   1.143 +    int32_t scale = int32_t((1 << 16) * aScale);
   1.144 +    for (int i = 0; i < aCount; ++i) {
   1.145 +      aTo[i] = int16_t((int32_t(aFrom[i]) * scale) >> 16);
   1.146 +    }
   1.147 +    return;
   1.148 +  }
   1.149 +  for (int i = 0; i < aCount; ++i) {
   1.150 +    aTo[i] = FloatToAudioSample<int16_t>(AudioSampleToFloat(aFrom[i])*aScale);
   1.151 +  }
   1.152 +}
   1.153 +
   1.154 +// In place audio sample scaling.
   1.155 +inline void
   1.156 +ScaleAudioSamples(float* aBuffer, int aCount, float aScale)
   1.157 +{
   1.158 +  for (int32_t i = 0; i < aCount; ++i) {
   1.159 +    aBuffer[i] *= aScale;
   1.160 +  }
   1.161 +}
   1.162 +
   1.163 +inline void
   1.164 +ScaleAudioSamples(short* aBuffer, int aCount, float aScale)
   1.165 +{
   1.166 +  int32_t volume = int32_t((1 << 16) * aScale);
   1.167 +  for (int32_t i = 0; i < aCount; ++i) {
   1.168 +    aBuffer[i] = short((int32_t(aBuffer[i]) * volume) >> 16);
   1.169 +  }
   1.170 +}
   1.171 +
   1.172 +inline const void*
   1.173 +AddAudioSampleOffset(const void* aBase, AudioSampleFormat aFormat,
   1.174 +                     int32_t aOffset)
   1.175 +{
   1.176 +  static_assert(AUDIO_FORMAT_S16 == 0, "Bad constant");
   1.177 +  static_assert(AUDIO_FORMAT_FLOAT32 == 1, "Bad constant");
   1.178 +  NS_ASSERTION(aFormat == AUDIO_FORMAT_S16 || aFormat == AUDIO_FORMAT_FLOAT32,
   1.179 +               "Unknown format");
   1.180 +
   1.181 +  return static_cast<const uint8_t*>(aBase) + (aFormat + 1)*2*aOffset;
   1.182 +}
   1.183 +
   1.184 +} // namespace mozilla
   1.185 +
   1.186 +#endif /* MOZILLA_AUDIOSAMPLEFORMAT_H_ */

mercurial