AudioSampleFormat.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim:set ts=2 sw=2 sts=2 et cindent: */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #ifndef MOZILLA_AUDIOSAMPLEFORMAT_H_
  7. #define MOZILLA_AUDIOSAMPLEFORMAT_H_
  8. #include "nsAlgorithm.h"
  9. #include <algorithm>
  10. namespace mozilla {
  11. /**
  12. * Audio formats supported in MediaStreams and media elements.
  13. *
  14. * Only one of these is supported by AudioStream, and that is determined
  15. * at compile time (roughly, FLOAT32 on desktops, S16 on mobile). Media decoders
  16. * produce that format only; queued AudioData always uses that format.
  17. */
  18. enum AudioSampleFormat
  19. {
  20. // Native-endian signed 16-bit audio samples
  21. AUDIO_FORMAT_S16,
  22. // Signed 32-bit float samples
  23. AUDIO_FORMAT_FLOAT32,
  24. // Silence: format will be chosen later
  25. AUDIO_FORMAT_SILENCE,
  26. // The format used for output by AudioStream.
  27. #ifdef MOZ_SAMPLE_TYPE_S16
  28. AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_S16
  29. #else
  30. AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_FLOAT32
  31. #endif
  32. };
  33. enum {
  34. MAX_AUDIO_SAMPLE_SIZE = sizeof(float)
  35. };
  36. template <AudioSampleFormat Format> class AudioSampleTraits;
  37. template <> class AudioSampleTraits<AUDIO_FORMAT_FLOAT32> {
  38. public:
  39. typedef float Type;
  40. };
  41. template <> class AudioSampleTraits<AUDIO_FORMAT_S16> {
  42. public:
  43. typedef int16_t Type;
  44. };
  45. typedef AudioSampleTraits<AUDIO_OUTPUT_FORMAT>::Type AudioDataValue;
  46. template<typename T> class AudioSampleTypeToFormat;
  47. template <> class AudioSampleTypeToFormat<float> {
  48. public:
  49. static const AudioSampleFormat Format = AUDIO_FORMAT_FLOAT32;
  50. };
  51. template <> class AudioSampleTypeToFormat<short> {
  52. public:
  53. static const AudioSampleFormat Format = AUDIO_FORMAT_S16;
  54. };
  55. // Single-sample conversion
  56. /*
  57. * Use "2^N" conversion since it's simple, fast, "bit transparent", used by
  58. * many other libraries and apparently behaves reasonably.
  59. * http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html
  60. * http://blog.bjornroche.com/2009/12/linearity-and-dynamic-range-in-int.html
  61. */
  62. inline float
  63. AudioSampleToFloat(float aValue)
  64. {
  65. return aValue;
  66. }
  67. inline float
  68. AudioSampleToFloat(int16_t aValue)
  69. {
  70. return aValue/32768.0f;
  71. }
  72. inline float
  73. AudioSampleToFloat(int32_t aValue)
  74. {
  75. return aValue/(float)(1U<<31);
  76. }
  77. template <typename T> T FloatToAudioSample(float aValue);
  78. template <> inline float
  79. FloatToAudioSample<float>(float aValue)
  80. {
  81. return aValue;
  82. }
  83. template <> inline int16_t
  84. FloatToAudioSample<int16_t>(float aValue)
  85. {
  86. float v = aValue*32768.0f;
  87. float clamped = std::max(-32768.0f, std::min(32767.0f, v));
  88. return int16_t(clamped);
  89. }
  90. template <typename T> T UInt8bitToAudioSample(uint8_t aValue);
  91. template <> inline float
  92. UInt8bitToAudioSample<float>(uint8_t aValue)
  93. {
  94. return aValue * (static_cast<float>(2) / UINT8_MAX) - static_cast<float>(1);
  95. }
  96. template <> inline int16_t
  97. UInt8bitToAudioSample<int16_t>(uint8_t aValue)
  98. {
  99. return (int16_t(aValue) << 8) + aValue + INT16_MIN;
  100. }
  101. template <typename T> T IntegerToAudioSample(int16_t aValue);
  102. template <> inline float
  103. IntegerToAudioSample<float>(int16_t aValue)
  104. {
  105. return aValue / 32768.0f;
  106. }
  107. template <> inline int16_t
  108. IntegerToAudioSample<int16_t>(int16_t aValue)
  109. {
  110. return aValue;
  111. }
  112. template <typename T> T Int24bitToAudioSample(int32_t aValue);
  113. template <> inline float
  114. Int24bitToAudioSample<float>(int32_t aValue)
  115. {
  116. return aValue / static_cast<float>(1 << 23);
  117. }
  118. template <> inline int16_t
  119. Int24bitToAudioSample<int16_t>(int32_t aValue)
  120. {
  121. return aValue / 256;
  122. }
  123. template<typename SrcT, typename DstT>
  124. inline void
  125. ConvertAudioSample(SrcT aIn, DstT& aOut);
  126. template<>
  127. inline void
  128. ConvertAudioSample(int16_t aIn, int16_t & aOut)
  129. {
  130. aOut = aIn;
  131. }
  132. template<>
  133. inline void
  134. ConvertAudioSample(int16_t aIn, float& aOut)
  135. {
  136. aOut = AudioSampleToFloat(aIn);
  137. }
  138. template<>
  139. inline void
  140. ConvertAudioSample(float aIn, float& aOut)
  141. {
  142. aOut = aIn;
  143. }
  144. template<>
  145. inline void
  146. ConvertAudioSample(float aIn, int16_t& aOut)
  147. {
  148. aOut = FloatToAudioSample<int16_t>(aIn);
  149. }
  150. // Sample buffer conversion
  151. template <typename From, typename To> inline void
  152. ConvertAudioSamples(const From* aFrom, To* aTo, int aCount)
  153. {
  154. for (int i = 0; i < aCount; ++i) {
  155. aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i]));
  156. }
  157. }
  158. inline void
  159. ConvertAudioSamples(const int16_t* aFrom, int16_t* aTo, int aCount)
  160. {
  161. memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
  162. }
  163. inline void
  164. ConvertAudioSamples(const float* aFrom, float* aTo, int aCount)
  165. {
  166. memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
  167. }
  168. // Sample buffer conversion with scale
  169. template <typename From, typename To> inline void
  170. ConvertAudioSamplesWithScale(const From* aFrom, To* aTo, int aCount, float aScale)
  171. {
  172. if (aScale == 1.0f) {
  173. ConvertAudioSamples(aFrom, aTo, aCount);
  174. return;
  175. }
  176. for (int i = 0; i < aCount; ++i) {
  177. aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i])*aScale);
  178. }
  179. }
  180. inline void
  181. ConvertAudioSamplesWithScale(const int16_t* aFrom, int16_t* aTo, int aCount, float aScale)
  182. {
  183. if (aScale == 1.0f) {
  184. ConvertAudioSamples(aFrom, aTo, aCount);
  185. return;
  186. }
  187. if (0.0f <= aScale && aScale < 1.0f) {
  188. int32_t scale = int32_t((1 << 16) * aScale);
  189. for (int i = 0; i < aCount; ++i) {
  190. aTo[i] = int16_t((int32_t(aFrom[i]) * scale) >> 16);
  191. }
  192. return;
  193. }
  194. for (int i = 0; i < aCount; ++i) {
  195. aTo[i] = FloatToAudioSample<int16_t>(AudioSampleToFloat(aFrom[i])*aScale);
  196. }
  197. }
  198. // In place audio sample scaling.
  199. inline void
  200. ScaleAudioSamples(float* aBuffer, int aCount, float aScale)
  201. {
  202. for (int32_t i = 0; i < aCount; ++i) {
  203. aBuffer[i] *= aScale;
  204. }
  205. }
  206. inline void
  207. ScaleAudioSamples(short* aBuffer, int aCount, float aScale)
  208. {
  209. int32_t volume = int32_t((1 << 16) * aScale);
  210. for (int32_t i = 0; i < aCount; ++i) {
  211. aBuffer[i] = short((int32_t(aBuffer[i]) * volume) >> 16);
  212. }
  213. }
  214. inline const void*
  215. AddAudioSampleOffset(const void* aBase, AudioSampleFormat aFormat,
  216. int32_t aOffset)
  217. {
  218. static_assert(AUDIO_FORMAT_S16 == 0, "Bad constant");
  219. static_assert(AUDIO_FORMAT_FLOAT32 == 1, "Bad constant");
  220. NS_ASSERTION(aFormat == AUDIO_FORMAT_S16 || aFormat == AUDIO_FORMAT_FLOAT32,
  221. "Unknown format");
  222. return static_cast<const uint8_t*>(aBase) + (aFormat + 1)*2*aOffset;
  223. }
  224. } // namespace mozilla
  225. #endif /* MOZILLA_AUDIOSAMPLEFORMAT_H_ */