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.

238 lines
7.6KB

  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. // Naive playback of audio stored in a buffer.
  28. #ifndef CLOUDS_DSP_LOOPING_SAMPLE_PLAYER_H_
  29. #define CLOUDS_DSP_LOOPING_SAMPLE_PLAYER_H_
  30. #include "stmlib/stmlib.h"
  31. #include <algorithm>
  32. #include "stmlib/dsp/units.h"
  33. #include "clouds/dsp/audio_buffer.h"
  34. #include "clouds/dsp/frame.h"
  35. #include "clouds/dsp/parameters.h"
  36. #include "clouds/resources.h"
  37. namespace clouds {
  38. const float kCrossfadeDuration = 64.0f;
  39. const int kMultDivSteps = 16;
  40. const float kMultDivs[kMultDivSteps] = {
  41. 1.0f/16.0f, 3.0f/32.0f, 1.0f/8.0f, 3.0f/16.0f,
  42. 1.0f/4.0f, 3.0f/8.0f, 1.0f/2.0f, 3.0f/4.0f,
  43. 1.0f,
  44. 3.0f/2.0f, 2.0f/1.0f, 3.0f/1.0f, 4.0f/1.0f,
  45. 6.0f/1.0f, 8.0f/1.0f, 12.0f/1.0f
  46. };
  47. using namespace stmlib;
  48. class LoopingSamplePlayer {
  49. public:
  50. LoopingSamplePlayer() { }
  51. ~LoopingSamplePlayer() { }
  52. void Init(int32_t num_channels) {
  53. num_channels_ = num_channels;
  54. phase_ = 0.0f;
  55. current_delay_ = 0.0f;
  56. loop_point_ = 0.0f;
  57. loop_duration_ = 0.0f;
  58. tap_delay_ = 0;
  59. tap_delay_counter_ = 0;
  60. synchronized_ = false;
  61. tail_duration_ = 1.0f;
  62. }
  63. inline bool synchronized() const { return synchronized_; }
  64. template<Resolution resolution>
  65. void Play(
  66. const AudioBuffer<resolution>* buffer,
  67. const Parameters& parameters,
  68. float* out, size_t size) {
  69. int32_t max_delay = buffer->size() - kCrossfadeDuration;
  70. tap_delay_counter_ += size;
  71. if (tap_delay_counter_ > max_delay) {
  72. tap_delay_ = 0;
  73. tap_delay_counter_ = 0;
  74. synchronized_ = false;
  75. }
  76. if (parameters.trigger) {
  77. if(tap_delay_counter_ > 128) {
  78. synchronized_ = true;
  79. tap_delay_ = tap_delay_counter_;
  80. loop_reset_ = phase_;
  81. phase_ = 0.0f;
  82. }
  83. tap_delay_counter_ = 0;
  84. }
  85. if (synchronized_)
  86. smoothed_tap_delay_ += 0.01f * (tap_delay_ - smoothed_tap_delay_);
  87. float target_delay = parameters.position * parameters.position * max_delay;
  88. if (synchronized_) {
  89. int index = roundf(parameters.position *
  90. static_cast<float>(kMultDivSteps));
  91. CONSTRAIN(index, 0, kMultDivSteps-1);
  92. do target_delay = kMultDivs[index--] * static_cast<float>(smoothed_tap_delay_);
  93. while (target_delay > max_delay && index >= 0);
  94. }
  95. const float swap_channels = parameters.stereo_spread;
  96. if (!parameters.freeze) {
  97. while (size--) {
  98. float error = (target_delay - current_delay_);
  99. float delay = current_delay_ + 0.0005f * error;
  100. current_delay_ = delay;
  101. int32_t delay_int = (buffer->head() - 4 - size + buffer->size()) << 12;
  102. delay_int -= static_cast<int32_t>(delay * 4096.0f);
  103. float l = buffer[0].ReadHermite((delay_int >> 12), delay_int << 4);
  104. if (num_channels_ == 1) {
  105. *out++ = l;
  106. *out++ = l;
  107. } else if (num_channels_ == 2) {
  108. float r = buffer[1].ReadHermite((delay_int >> 12), delay_int << 4);
  109. *out++ = l + (r - l) * swap_channels;
  110. *out++ = r + (l - r) * swap_channels;
  111. }
  112. }
  113. phase_ = 0.0f;
  114. } else {
  115. float loop_point = parameters.position * max_delay * 15.0f / 16.0f;
  116. loop_point += kCrossfadeDuration;
  117. float d = parameters.size;
  118. float loop_duration = (0.01f + 0.99f * d * d) * max_delay;
  119. if (synchronized_) {
  120. int index = roundf(d * static_cast<float>(kMultDivSteps));
  121. CONSTRAIN(index, 0, kMultDivSteps-1);
  122. do loop_duration = kMultDivs[index--] * static_cast<float>(smoothed_tap_delay_);
  123. while (loop_duration > max_delay && index >= 0);
  124. }
  125. if (loop_point + loop_duration >= max_delay) {
  126. loop_point = max_delay - loop_duration;
  127. }
  128. float phase_increment = synchronized_
  129. ? 1.0f
  130. : SemitonesToRatio(parameters.pitch);
  131. while (size--) {
  132. ONE_POLE(smoothed_tap_delay_, tap_delay_, 0.00001f);
  133. if (phase_ >= loop_duration_ || phase_ == 0.0f) {
  134. if (phase_ >= loop_duration_) {
  135. loop_reset_ = loop_duration_;
  136. }
  137. if (loop_reset_ >= loop_duration_) {
  138. loop_reset_ = loop_duration_;
  139. }
  140. tail_start_ = loop_duration_ - loop_reset_ + loop_point_;
  141. phase_ = 0.0f;
  142. tail_duration_ = std::min(
  143. kCrossfadeDuration,
  144. kCrossfadeDuration * phase_increment);
  145. loop_point_ = loop_point;
  146. loop_duration_ = loop_duration;
  147. }
  148. phase_ += phase_increment;
  149. float gain = 1.0f;
  150. if (tail_duration_ != 0.0f) {
  151. gain = phase_ / tail_duration_;
  152. CONSTRAIN(gain, 0.0f, 1.0f);
  153. }
  154. int32_t delay_int = (buffer->head() - 4 + buffer->size()) << 12;
  155. float ph = parameters.granular.reverse ?
  156. loop_duration_ - phase_ :
  157. phase_;
  158. int32_t position = delay_int - static_cast<int32_t>(
  159. (loop_duration_ - ph + loop_point_) * 4096.0f);
  160. float l = buffer[0].ReadHermite((position >> 12), position << 4);
  161. if (num_channels_ == 1) {
  162. out[0] = l * gain;
  163. out[1] = l * gain;
  164. } else if (num_channels_ == 2) {
  165. float r = buffer[1].ReadHermite((position >> 12), position << 4);
  166. out[0] = (l + (r - l) * swap_channels) * gain;
  167. out[1] = (r + (l - r) * swap_channels) * gain;
  168. }
  169. if (gain != 1.0f) {
  170. gain = 1.0f - gain;
  171. int32_t position = delay_int - static_cast<int32_t>(
  172. (-phase_ + tail_start_) * 4096.0f);
  173. float l = buffer[0].ReadHermite((position >> 12), position << 4);
  174. if (num_channels_ == 1) {
  175. out[0] += l * gain;
  176. out[1] += l * gain;
  177. } else if (num_channels_ == 2) {
  178. float r = buffer[1].ReadHermite((position >> 12), position << 4);
  179. out[0] += (l + (r - l) * swap_channels) * gain;
  180. out[1] += (r + (l - r) * swap_channels) * gain;
  181. }
  182. }
  183. out += 2;
  184. }
  185. }
  186. }
  187. private:
  188. float phase_;
  189. float current_delay_;
  190. float loop_point_;
  191. float loop_duration_;
  192. float tail_start_;
  193. float tail_duration_;
  194. float loop_reset_;
  195. bool synchronized_;
  196. int32_t num_channels_;
  197. int32_t elapsed_;
  198. int32_t tap_delay_;
  199. int32_t smoothed_tap_delay_;
  200. int32_t tap_delay_counter_;
  201. DISALLOW_COPY_AND_ASSIGN(LoopingSamplePlayer);
  202. };
  203. } // namespace clouds
  204. #endif // CLOUDS_DSP_LOOPING_SAMPLE_PLAYER_H_