audio_util.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Copyright (c) 2013 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. #ifndef COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
  11. #define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
  12. #include <stdint.h>
  13. #include <algorithm>
  14. #include <cmath>
  15. #include <cstring>
  16. #include <limits>
  17. #include "rtc_base/checks.h"
  18. namespace webrtc {
  19. typedef std::numeric_limits<int16_t> limits_int16;
  20. // The conversion functions use the following naming convention:
  21. // S16: int16_t [-32768, 32767]
  22. // Float: float [-1.0, 1.0]
  23. // FloatS16: float [-32768.0, 32768.0]
  24. // Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
  25. // The ratio conversion functions use this naming convention:
  26. // Ratio: float (0, +inf)
  27. // Db: float (-inf, +inf)
  28. static inline float S16ToFloat(int16_t v) {
  29. constexpr float kScaling = 1.f / 32768.f;
  30. return v * kScaling;
  31. }
  32. static inline int16_t FloatS16ToS16(float v) {
  33. v = std::min(v, 32767.f);
  34. v = std::max(v, -32768.f);
  35. return static_cast<int16_t>(v + std::copysign(0.5f, v));
  36. }
  37. static inline int16_t FloatToS16(float v) {
  38. v *= 32768.f;
  39. v = std::min(v, 32767.f);
  40. v = std::max(v, -32768.f);
  41. return static_cast<int16_t>(v + std::copysign(0.5f, v));
  42. }
  43. static inline float FloatToFloatS16(float v) {
  44. v = std::min(v, 1.f);
  45. v = std::max(v, -1.f);
  46. return v * 32768.f;
  47. }
  48. static inline float FloatS16ToFloat(float v) {
  49. v = std::min(v, 32768.f);
  50. v = std::max(v, -32768.f);
  51. constexpr float kScaling = 1.f / 32768.f;
  52. return v * kScaling;
  53. }
  54. void FloatToS16(const float* src, size_t size, int16_t* dest);
  55. void S16ToFloat(const int16_t* src, size_t size, float* dest);
  56. void S16ToFloatS16(const int16_t* src, size_t size, float* dest);
  57. void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
  58. void FloatToFloatS16(const float* src, size_t size, float* dest);
  59. void FloatS16ToFloat(const float* src, size_t size, float* dest);
  60. inline float DbToRatio(float v) {
  61. return std::pow(10.0f, v / 20.0f);
  62. }
  63. inline float DbfsToFloatS16(float v) {
  64. static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
  65. return DbToRatio(v) * kMaximumAbsFloatS16;
  66. }
  67. inline float FloatS16ToDbfs(float v) {
  68. RTC_DCHECK_GE(v, 0);
  69. // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
  70. static constexpr float kMinDbfs = -90.30899869919436f;
  71. if (v <= 1.0f) {
  72. return kMinDbfs;
  73. }
  74. // Equal to 20 * log10(v / (-limits_int16::min()))
  75. return 20.0f * std::log10(v) + kMinDbfs;
  76. }
  77. // Copy audio from |src| channels to |dest| channels unless |src| and |dest|
  78. // point to the same address. |src| and |dest| must have the same number of
  79. // channels, and there must be sufficient space allocated in |dest|.
  80. template <typename T>
  81. void CopyAudioIfNeeded(const T* const* src,
  82. int num_frames,
  83. int num_channels,
  84. T* const* dest) {
  85. for (int i = 0; i < num_channels; ++i) {
  86. if (src[i] != dest[i]) {
  87. std::copy(src[i], src[i] + num_frames, dest[i]);
  88. }
  89. }
  90. }
  91. // Deinterleave audio from |interleaved| to the channel buffers pointed to
  92. // by |deinterleaved|. There must be sufficient space allocated in the
  93. // |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
  94. // per buffer).
  95. template <typename T>
  96. void Deinterleave(const T* interleaved,
  97. size_t samples_per_channel,
  98. size_t num_channels,
  99. T* const* deinterleaved) {
  100. for (size_t i = 0; i < num_channels; ++i) {
  101. T* channel = deinterleaved[i];
  102. size_t interleaved_idx = i;
  103. for (size_t j = 0; j < samples_per_channel; ++j) {
  104. channel[j] = interleaved[interleaved_idx];
  105. interleaved_idx += num_channels;
  106. }
  107. }
  108. }
  109. // Interleave audio from the channel buffers pointed to by |deinterleaved| to
  110. // |interleaved|. There must be sufficient space allocated in |interleaved|
  111. // (|samples_per_channel| * |num_channels|).
  112. template <typename T>
  113. void Interleave(const T* const* deinterleaved,
  114. size_t samples_per_channel,
  115. size_t num_channels,
  116. T* interleaved) {
  117. for (size_t i = 0; i < num_channels; ++i) {
  118. const T* channel = deinterleaved[i];
  119. size_t interleaved_idx = i;
  120. for (size_t j = 0; j < samples_per_channel; ++j) {
  121. interleaved[interleaved_idx] = channel[j];
  122. interleaved_idx += num_channels;
  123. }
  124. }
  125. }
  126. // Copies audio from a single channel buffer pointed to by |mono| to each
  127. // channel of |interleaved|. There must be sufficient space allocated in
  128. // |interleaved| (|samples_per_channel| * |num_channels|).
  129. template <typename T>
  130. void UpmixMonoToInterleaved(const T* mono,
  131. int num_frames,
  132. int num_channels,
  133. T* interleaved) {
  134. int interleaved_idx = 0;
  135. for (int i = 0; i < num_frames; ++i) {
  136. for (int j = 0; j < num_channels; ++j) {
  137. interleaved[interleaved_idx++] = mono[i];
  138. }
  139. }
  140. }
  141. template <typename T, typename Intermediate>
  142. void DownmixToMono(const T* const* input_channels,
  143. size_t num_frames,
  144. int num_channels,
  145. T* out) {
  146. for (size_t i = 0; i < num_frames; ++i) {
  147. Intermediate value = input_channels[0][i];
  148. for (int j = 1; j < num_channels; ++j) {
  149. value += input_channels[j][i];
  150. }
  151. out[i] = value / num_channels;
  152. }
  153. }
  154. // Downmixes an interleaved multichannel signal to a single channel by averaging
  155. // all channels.
  156. template <typename T, typename Intermediate>
  157. void DownmixInterleavedToMonoImpl(const T* interleaved,
  158. size_t num_frames,
  159. int num_channels,
  160. T* deinterleaved) {
  161. RTC_DCHECK_GT(num_channels, 0);
  162. RTC_DCHECK_GT(num_frames, 0);
  163. const T* const end = interleaved + num_frames * num_channels;
  164. while (interleaved < end) {
  165. const T* const frame_end = interleaved + num_channels;
  166. Intermediate value = *interleaved++;
  167. while (interleaved < frame_end) {
  168. value += *interleaved++;
  169. }
  170. *deinterleaved++ = value / num_channels;
  171. }
  172. }
  173. template <typename T>
  174. void DownmixInterleavedToMono(const T* interleaved,
  175. size_t num_frames,
  176. int num_channels,
  177. T* deinterleaved);
  178. template <>
  179. void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
  180. size_t num_frames,
  181. int num_channels,
  182. int16_t* deinterleaved);
  183. } // namespace webrtc
  184. #endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_