You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
8.7KB

  1. // Copyright 2014 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Circular buffer storing audio samples.
  28. #ifndef CLOUDS_DSP_AUDIO_BUFFER_H_
  29. #define CLOUDS_DSP_AUDIO_BUFFER_H_
  30. #include <algorithm>
  31. #include "stmlib/stmlib.h"
  32. #include "stmlib/dsp/dsp.h"
  33. #include "stmlib/utils/dsp.h"
  34. #include "clouds/dsp/mu_law.h"
  35. const int32_t kCrossFadeSize = 256;
  36. const int32_t kInterpolationTail = 8;
  37. namespace clouds {
  38. enum Resolution {
  39. RESOLUTION_16_BIT,
  40. RESOLUTION_8_BIT,
  41. RESOLUTION_8_BIT_DITHERED,
  42. RESOLUTION_8_BIT_MU_LAW,
  43. };
  44. enum InterpolationMethod {
  45. INTERPOLATION_ZOH,
  46. INTERPOLATION_LINEAR,
  47. INTERPOLATION_HERMITE
  48. };
  49. template<Resolution resolution>
  50. class AudioBuffer {
  51. public:
  52. AudioBuffer() { }
  53. ~AudioBuffer() { }
  54. void Init(
  55. void* buffer,
  56. int32_t size,
  57. int16_t* tail_buffer) {
  58. s16_ = static_cast<int16_t*>(buffer);
  59. s8_ = static_cast<int8_t*>(buffer);
  60. size_ = size - kInterpolationTail;
  61. write_head_ = 0;
  62. quantization_error_ = 0.0f;
  63. crossfade_counter_ = 0;
  64. if (resolution == RESOLUTION_16_BIT) {
  65. std::fill(&s16_[0], &s16_[size], 0);
  66. } else {
  67. std::fill(
  68. &s8_[0],
  69. &s8_[size],
  70. resolution == RESOLUTION_8_BIT_MU_LAW ? 127 : 0);
  71. }
  72. tail_ = tail_buffer;
  73. }
  74. inline void Resync(int32_t head) {
  75. write_head_ = head;
  76. crossfade_counter_ = 0;
  77. }
  78. inline void Write(float in) {
  79. if (resolution == RESOLUTION_16_BIT) {
  80. s16_[write_head_] = stmlib::Clip16(
  81. static_cast<int32_t>(in * 32768.0f));
  82. } else if (resolution == RESOLUTION_8_BIT_DITHERED) {
  83. float sample = in * 127.0f;
  84. sample += quantization_error_;
  85. int32_t quantized = static_cast<int32_t>(sample);
  86. if (quantized < -127) quantized = -127;
  87. else if (quantized > 127) quantized = 127;
  88. quantization_error_ = sample - static_cast<float>(in);
  89. s8_[write_head_] = quantized;
  90. } else if (resolution == RESOLUTION_8_BIT_MU_LAW) {
  91. int16_t sample = stmlib::Clip16(static_cast<int32_t>(in * 32768.0f));
  92. s8_[write_head_] = Lin2MuLaw(sample);
  93. } else {
  94. s8_[write_head_] = static_cast<int8_t>(
  95. stmlib::Clip16(in * 32768.0f) >> 8);
  96. }
  97. if (resolution == RESOLUTION_16_BIT) {
  98. if (write_head_ < kInterpolationTail) {
  99. s16_[write_head_ + size_] = s16_[write_head_];
  100. }
  101. } else {
  102. if (write_head_ < kInterpolationTail) {
  103. s8_[write_head_ + size_] = s8_[write_head_];
  104. }
  105. }
  106. ++write_head_;
  107. if (write_head_ >= size_) {
  108. write_head_ = 0;
  109. }
  110. }
  111. inline void WriteFade(
  112. const float* in,
  113. int32_t size,
  114. int32_t stride,
  115. bool write) {
  116. if (!write) {
  117. // Continue recording samples to have something to crossfade with
  118. // when recording resumes.
  119. if (crossfade_counter_ < kCrossFadeSize) {
  120. while (size--) {
  121. if (crossfade_counter_ < kCrossFadeSize) {
  122. tail_[crossfade_counter_++] = stmlib::Clip16(
  123. static_cast<int32_t>(*in * 32767.0f));
  124. in += stride;
  125. }
  126. }
  127. }
  128. } else if (write && !crossfade_counter_ &&
  129. resolution == RESOLUTION_16_BIT &&
  130. write_head_ >= kInterpolationTail && write_head_ < (size_ - size)) {
  131. // Fast write routine for the most common case.
  132. while (size--) {
  133. s16_[write_head_] = stmlib::Clip16(
  134. static_cast<int32_t>(*in * 32767.0f));
  135. ++write_head_;
  136. in += stride;
  137. }
  138. } else {
  139. while (size--) {
  140. float sample = *in;
  141. if (crossfade_counter_) {
  142. --crossfade_counter_;
  143. float tail_sample = tail_[kCrossFadeSize - crossfade_counter_];
  144. float gain = crossfade_counter_ * (1.0f / float(kCrossFadeSize));
  145. sample += (tail_sample / 32768.0f - sample) * gain;
  146. }
  147. Write(sample);
  148. in += stride;
  149. }
  150. }
  151. }
  152. inline void Write(const float* in, int32_t size, int32_t stride) {
  153. if (resolution == RESOLUTION_16_BIT
  154. && write_head_ >= kInterpolationTail && write_head_ < (size_ - size)) {
  155. // Fast write routine for the most common case.
  156. while (size--) {
  157. s16_[write_head_] = stmlib::Clip16(
  158. static_cast<int32_t>(*in * 32768.0f));
  159. ++write_head_;
  160. in += stride;
  161. }
  162. } else {
  163. while (size--) {
  164. Write(*in);
  165. in += stride;
  166. }
  167. }
  168. }
  169. template<InterpolationMethod method>
  170. inline float Read(int32_t integral, uint16_t fractional) const {
  171. if (method == INTERPOLATION_ZOH) {
  172. return ReadZOH(integral, fractional);
  173. } else if (method == INTERPOLATION_LINEAR) {
  174. return ReadLinear(integral, fractional);
  175. } else if (method == INTERPOLATION_HERMITE) {
  176. return ReadHermite(integral, fractional);
  177. }
  178. }
  179. inline float ReadZOH(int32_t integral, uint16_t fractional) const {
  180. if (integral >= size_) {
  181. integral -= size_;
  182. }
  183. float x0, scale;
  184. if (resolution == RESOLUTION_16_BIT) {
  185. x0 = s16_[integral];
  186. scale = 1.0f / 32768.0f;
  187. } else if (resolution == RESOLUTION_8_BIT_MU_LAW) {
  188. x0 = MuLaw2Lin(s8_[integral]);
  189. scale = 1.0f / 32768.0f;
  190. } else {
  191. x0 = s8_[integral];
  192. scale = 1.0f / 128.0f;
  193. }
  194. return x0 * scale;
  195. }
  196. inline float ReadLinear(int32_t integral, uint16_t fractional) const {
  197. if (integral >= size_) {
  198. integral -= size_;
  199. }
  200. // assert(integral >= 0 && integral < size_);
  201. float x0, x1, scale;
  202. float t = static_cast<float>(fractional) / 65536.0f;
  203. if (resolution == RESOLUTION_16_BIT) {
  204. x0 = s16_[integral];
  205. x1 = s16_[integral + 1];
  206. scale = 1.0f / 32768.0f;
  207. } else if (resolution == RESOLUTION_8_BIT_MU_LAW) {
  208. x0 = MuLaw2Lin(s8_[integral]);
  209. x1 = MuLaw2Lin(s8_[integral + 1]);
  210. scale = 1.0f / 32768.0f;
  211. } else {
  212. x0 = s8_[integral];
  213. x1 = s8_[integral + 1];
  214. scale = 1.0f / 128.0f;
  215. }
  216. return (x0 + (x1 - x0) * t) * scale;
  217. }
  218. inline float ReadHermite(int32_t integral, uint16_t fractional) const {
  219. if (integral >= size_) {
  220. integral -= size_;
  221. }
  222. // assert(integral >= 0 && integral < size_);
  223. float xm1, x0, x1, x2, scale;
  224. float t = static_cast<float>(fractional) / 65536.0f;
  225. if (resolution == RESOLUTION_16_BIT) {
  226. xm1 = s16_[integral];
  227. x0 = s16_[integral + 1];
  228. x1 = s16_[integral + 2];
  229. x2 = s16_[integral + 3];
  230. scale = 1.0f / 32768.0f;
  231. } else if (resolution == RESOLUTION_8_BIT_MU_LAW) {
  232. xm1 = MuLaw2Lin(s8_[integral]);
  233. x0 = MuLaw2Lin(s8_[integral + 1]);
  234. x1 = MuLaw2Lin(s8_[integral + 2]);
  235. x2 = MuLaw2Lin(s8_[integral + 3]);
  236. scale = 1.0f / 32768.0f;
  237. } else {
  238. xm1 = s8_[integral];
  239. x0 = s8_[integral + 1];
  240. x1 = s8_[integral + 2];
  241. x2 = s8_[integral + 3];
  242. scale = 1.0f / 128.0f;
  243. }
  244. // Laurent de Soras's Hermite interpolator.
  245. const float c = (x1 - xm1) * 0.5f;
  246. const float v = x0 - x1;
  247. const float w = c + v;
  248. const float a = w + v + (x2 - x0) * 0.5f;
  249. const float b_neg = w + a;
  250. return ((((a * t) - b_neg) * t + c) * t + x0) * scale;
  251. }
  252. inline int32_t size() const { return size_; }
  253. inline int32_t head() const { return write_head_; }
  254. private:
  255. int16_t* s16_;
  256. int8_t* s8_;
  257. float quantization_error_;
  258. int16_t tail_ptr_;
  259. int32_t size_;
  260. int32_t write_head_;
  261. int16_t* tail_;
  262. int32_t crossfade_counter_;
  263. DISALLOW_COPY_AND_ASSIGN(AudioBuffer);
  264. };
  265. } // namespace clouds
  266. #endif // CLOUDS_DSP_AUDIO_BUFFER_H_