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.

395 lines
12KB

  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. // Resonestor.
  28. #ifndef CLOUDS_DSP_RESONESTOR_H_
  29. #define CLOUDS_DSP_RESONESTOR_H_
  30. #include "stmlib/stmlib.h"
  31. #include "stmlib/utils/random.h"
  32. #include "stmlib/dsp/units.h"
  33. #include "clouds/dsp/fx/fx_engine.h"
  34. #include "clouds/resources.h"
  35. using namespace stmlib;
  36. namespace clouds {
  37. const float chords[3][18] =
  38. {
  39. { 0.0f, 4.0f/128.0f, 16.0f/128.0f, 4.0f/128.0f, 4.0f/128.0f,
  40. 12.0f, 12.0f, 4.0f, 4.0f,
  41. 3.0f, 3.0f, 2.0f, 4.0f,
  42. 3.0f, 4.0f, 3.0f, 4.0f,
  43. 4.0f },
  44. { 0.0f, 8.0f/128.0f, 32.0f/128.0f, 7.0f, 12.0f,
  45. 24.0f, 7.0f, 7.0f, 7.0f,
  46. 7.0f, 7.0f, 7.0f, 7.0f,
  47. 7.0f, 7.0f, 7.0f, 7.0f,
  48. 7.0f },
  49. { 0.0f, 12.0f/128.0f, 48.0f/128.0f, 7.0f + 4.0f/128.0f, 12.0f + 4.0f/128.0f,
  50. 36.0f, 19.0f, 12.0f, 11.0f,
  51. 10.0f, 12.0f, 12.0f, 12.0f,
  52. 14.0f, 14.0f, 16.0f, 16.0f,
  53. 16.0f }
  54. };
  55. #define PLATEAU 2.0f
  56. inline float InterpolatePlateau(const float* table, float index, float size) {
  57. index *= size;
  58. MAKE_INTEGRAL_FRACTIONAL(index)
  59. float a = table[index_integral];
  60. float b = table[index_integral + 1];
  61. if (index_fractional < 1.0f/PLATEAU)
  62. return a + (b - a) * index_fractional * PLATEAU;
  63. else
  64. return b;
  65. }
  66. class Resonestor {
  67. public:
  68. Resonestor() { }
  69. ~Resonestor() { }
  70. void Init(float* buffer) {
  71. engine_.Init(buffer);
  72. for (int v=0; v<2; v++) {
  73. pitch_[v] = 0.0f;
  74. chord_[v] = 0.0f;
  75. feedback_[v] = 0.0f;
  76. narrow_[v] = 0.001f;
  77. damp_[v] = 1.0f;
  78. harmonicity_[v] = 1.0f;
  79. distortion_[v] = 0.0f;
  80. }
  81. spread_amount_ = 0.0f;
  82. stereo_ = 0.0f;
  83. burst_time_ = 0.0f;
  84. burst_damp_ = 1.0f;
  85. burst_comb_ = 1.0f;
  86. burst_duration_ = 0.0f;
  87. trigger_ = previous_trigger_ = 0.0f;
  88. freeze_ = previous_freeze_ = 0.0f;
  89. voice_ = false;
  90. for (int i=0; i<3; i++)
  91. spread_delay_[i] = Random::GetFloat() * 3999;
  92. burst_lp_.Init();
  93. rand_lp_.Init();
  94. rand_hp_.Init();
  95. rand_hp_.set_f<FREQUENCY_FAST>(1.0f / 32000.0f);
  96. for (int v=0; v<2; v++)
  97. for (int p=0; p<4; p++) {
  98. lp_[p][v].Init();
  99. bp_[p][v].Init();
  100. hp_[p][v] = 0.0f;
  101. comb_period_[p][v] = 0.0f;
  102. comb_feedback_[p][v] = 0.0f;
  103. }
  104. }
  105. #define MAX_COMB 1000
  106. #define BASE_PITCH 261.626f
  107. void Process(FloatFrame* in_out, size_t size) {
  108. typedef E::Reserve<MAX_COMB,
  109. E::Reserve<MAX_COMB,
  110. E::Reserve<MAX_COMB,
  111. E::Reserve<MAX_COMB,
  112. E::Reserve<200, /* bc */
  113. E::Reserve<4000, /* bd0 */
  114. E::Reserve<4000, /* bd1 */
  115. E::Reserve<MAX_COMB,
  116. E::Reserve<MAX_COMB,
  117. E::Reserve<MAX_COMB,
  118. E::Reserve<MAX_COMB > > > > > > > > > > > Memory;
  119. E::DelayLine<Memory, 0> c00;
  120. E::DelayLine<Memory, 1> c10;
  121. E::DelayLine<Memory, 2> c20;
  122. E::DelayLine<Memory, 3> c30;
  123. E::DelayLine<Memory, 4> bc;
  124. E::DelayLine<Memory, 5> bd0;
  125. E::DelayLine<Memory, 6> bd1;
  126. E::DelayLine<Memory, 7> c01;
  127. E::DelayLine<Memory, 8> c11;
  128. E::DelayLine<Memory, 9> c21;
  129. E::DelayLine<Memory, 10> c31;
  130. E::Context c;
  131. /* switch active voice */
  132. if (trigger_ && !previous_trigger_ && !freeze_) {
  133. voice_ = !voice_;
  134. }
  135. if (freeze_ && !previous_freeze_) {
  136. previous_freeze_ = freeze_;
  137. voice_ = !voice_;
  138. }
  139. /* set comb filters pitch */
  140. comb_period_[0][voice_] = 32000.0f / BASE_PITCH / SemitonesToRatio(pitch_[voice_]);
  141. CONSTRAIN(comb_period_[0][voice_], 0, MAX_COMB);
  142. for (int p=1; p<4; p++) {
  143. float pitch = InterpolatePlateau(chords[p-1], chord_[voice_], 16);
  144. comb_period_[p][voice_] = comb_period_[0][voice_] / SemitonesToRatio(pitch);
  145. CONSTRAIN(comb_period_[p][voice_], 0, MAX_COMB);
  146. }
  147. /* set LP/BP filters frequencies and feedback */
  148. for (int p=0; p<4; p++) {
  149. float freq = 1.0f / comb_period_[p][voice_];
  150. bp_[p][voice_].set_f_q<FREQUENCY_FAST>(freq, narrow_[voice_]);
  151. float lp_freq = (2.0f * freq + 1.0f) * damp_[voice_];
  152. CONSTRAIN(lp_freq, 0.0f, 1.0f);
  153. lp_[p][voice_].set_f_q<FREQUENCY_FAST>(lp_freq, 0.4f);
  154. comb_feedback_[p][voice_] = powf(feedback_[voice_], comb_period_[p][voice_] / 32000.0f);
  155. }
  156. /* initiate burst if trigger */
  157. if (trigger_ && !previous_trigger_) {
  158. previous_trigger_ = trigger_;
  159. burst_time_ = comb_period_[0][voice_];
  160. burst_time_ *= 2.0f * burst_duration_;
  161. for (int i=0; i<3; i++)
  162. spread_delay_[i] = Random::GetFloat() * (bd0.length - 1);
  163. }
  164. rand_lp_.set_f_q<FREQUENCY_FAST>(distortion_[voice_] * 0.4f, 1.0f);
  165. while (size--) {
  166. engine_.Start(&c);
  167. burst_time_--;
  168. float burst_gain = burst_time_ > 0.0f ? 1.0f : 0.0f;
  169. float random = Random::GetFloat() * 2.0f - 1.0f;
  170. /* burst noise generation */
  171. c.Read(random, burst_gain);
  172. // goes through comb and lp filters
  173. const float comb_fb = 0.6f - burst_comb_ * 0.4f;
  174. float comb_del = burst_comb_ * bc.length;
  175. if (comb_del <= 1.0f) comb_del = 1.0f;
  176. c.InterpolateHermite(bc, comb_del, comb_fb);
  177. c.Write(bc, 1.0f);
  178. float burst;
  179. c.Write(burst);
  180. c.Load(burst_lp_.Process<FILTER_MODE_LOW_PASS>(burst));
  181. c.Write(burst);
  182. c.Load(burst);
  183. c.Read(in_out->l, 1.0f);
  184. c.Write(bd0, 0.0f);
  185. c.Load(burst);
  186. c.Read(in_out->r, 1.0f);
  187. c.Write(bd1, 0.0f);
  188. float amplitude = distortion_[voice_];
  189. amplitude = 1.0f - amplitude;
  190. amplitude *= 0.3f;
  191. amplitude *= amplitude;
  192. random *= amplitude;
  193. random = rand_lp_.Process<FILTER_MODE_LOW_PASS>(random);
  194. random = rand_hp_.Process<FILTER_MODE_HIGH_PASS>(random);
  195. #define COMB(pre, part, voice, vol) \
  196. { \
  197. c.Load(0.0f); \
  198. c.Read(bd ## voice, pre * spread_amount_, vol); \
  199. float tap = comb_period_[part][voice] * (1.0f + random); \
  200. c.InterpolateHermite(c ## part ## voice, tap , \
  201. comb_feedback_[part][voice] * 0.7f); \
  202. c.InterpolateHermite(c ## part ## voice, \
  203. tap * harmonicity_[voice], \
  204. comb_feedback_[part][voice] * 0.3f); \
  205. float acc; \
  206. c.Write(acc); \
  207. acc = lp_[part][voice].Process<FILTER_MODE_LOW_PASS>(acc); \
  208. acc = bp_[part][voice].Process<FILTER_MODE_BAND_PASS_NORMALIZED>(acc); \
  209. c.Load(acc); \
  210. c.Hp(hp_[part][voice], 10.0f / 32000.0f); \
  211. c.Write(acc, 0.5f); \
  212. c.SoftLimit(); \
  213. c.Write(acc, 2.0f); \
  214. c.Write(c ## part ## voice, 0.0f); \
  215. } \
  216. /* first voice: */
  217. COMB(0, 0, 0, !voice_);
  218. COMB(spread_delay_[0], 1, 0, !voice_);
  219. COMB(spread_delay_[1], 2, 0, !voice_);
  220. COMB(spread_delay_[2], 3, 0, !voice_);
  221. /* second voice: */
  222. COMB(0, 0, 1, voice_);
  223. COMB(spread_delay_[0], 1, 1, voice_);
  224. COMB(spread_delay_[1], 2, 1, voice_);
  225. COMB(spread_delay_[2], 3, 1, voice_);
  226. /* left mix */
  227. c.Read(c00, (1.0f + 0.5f * narrow_[0]) *
  228. 0.25f * (1.0f - stereo_) * (1.0f - separation_));
  229. c.Read(c10, (1.0f + 0.5f * narrow_[0]) *
  230. (0.25f + 0.25f * stereo_) * (1.0f - separation_));
  231. c.Read(c20, (1.0f + 0.5f * narrow_[0]) *
  232. (0.25f * (1.0f - stereo_)) * (1.0f - separation_));
  233. c.Read(c30, (1.0f + 0.5f * narrow_[0]) *
  234. (0.25f + 0.25f * stereo_) * (1.0f - separation_));
  235. c.Read(c01, (1.0f + 0.5f * narrow_[1]) * (0.25f + 0.25f * stereo_));
  236. c.Read(c11, (1.0f + 0.5f * narrow_[1]) * 0.25f * (1.0f - stereo_));
  237. c.Read(c21, (1.0f + 0.5f * narrow_[1]) * (0.25f + 0.25 * stereo_));
  238. c.Read(c31, (1.0f + 0.5f * narrow_[1]) * 0.25f * (1.0f - stereo_));
  239. c.Write(in_out->l, 0.0f);
  240. /* right mix */
  241. c.Read(c00, (1.0f + 0.5f * narrow_[0]) * (0.25f + 0.25f * stereo_));
  242. c.Read(c10, (1.0f + 0.5f * narrow_[0]) * 0.25f * (1.0f - stereo_));
  243. c.Read(c20, (1.0f + 0.5f * narrow_[0]) * (0.25f + 0.25f * stereo_));
  244. c.Read(c30, (1.0f + 0.5f * narrow_[0]) * 0.25f * (1.0f - stereo_));
  245. c.Read(c01, (1.0f + 0.5f * narrow_[1]) *
  246. 0.25f * (1.0f - stereo_) * (1.0f - separation_));
  247. c.Read(c11, (1.0f + 0.5f * narrow_[1]) *
  248. (0.25f + 0.25f * stereo_) * (1.0f - separation_));
  249. c.Read(c21, (1.0f + 0.5f * narrow_[1]) *
  250. 0.25f * (1.0f - stereo_) * (1.0f - separation_));
  251. c.Read(c31, (1.0f + 0.5f * narrow_[1]) *
  252. (0.25f + 0.25f * stereo_) * (1.0f - separation_));
  253. c.Write(in_out->r, 0.0f);
  254. ++in_out;
  255. }
  256. }
  257. void set_pitch(float pitch) {
  258. pitch_[voice_] = pitch;
  259. }
  260. void set_chord(float chord) {
  261. chord_[voice_] = chord;
  262. }
  263. void set_feedback(float feedback) {
  264. feedback_[voice_] = feedback;
  265. }
  266. void set_narrow(float narrow) {
  267. narrow_[voice_] = narrow;
  268. }
  269. void set_damp(float damp) {
  270. damp_[voice_] = damp;
  271. }
  272. void set_distortion(float distortion) {
  273. distortion *= distortion * distortion;
  274. distortion_[voice_] = distortion;
  275. }
  276. void set_trigger(bool trigger) {
  277. previous_trigger_ = trigger_;
  278. trigger_ = trigger;
  279. }
  280. void set_burst_damp(float burst_damp) {
  281. burst_lp_.set_f_q<FREQUENCY_FAST>(burst_damp * burst_damp * 0.5f, 0.8f);
  282. }
  283. void set_burst_comb(float burst_comb) {
  284. burst_comb_ = burst_comb;
  285. }
  286. void set_burst_duration(float burst_duration) {
  287. burst_duration_ = burst_duration;
  288. }
  289. void set_spread_amount(float spread_amount) {
  290. spread_amount_ = spread_amount;
  291. }
  292. void set_stereo(float stereo) {
  293. stereo_ = stereo;
  294. }
  295. void set_separation(float separation) {
  296. separation_ = separation;
  297. }
  298. void set_freeze(float freeze) {
  299. previous_freeze_ = freeze_;
  300. freeze_ = freeze;
  301. }
  302. void set_harmonicity(float harmonicity) {
  303. harmonicity_[voice_] = harmonicity;
  304. }
  305. private:
  306. typedef FxEngine<16384, FORMAT_32_BIT> E;
  307. E engine_;
  308. /* parameters: */
  309. float feedback_[2];
  310. float pitch_[2];
  311. float chord_[2];
  312. float narrow_[2];
  313. float damp_[2];
  314. float harmonicity_[2];
  315. float distortion_[2];
  316. float spread_amount_;
  317. float stereo_;
  318. float separation_;
  319. float burst_time_;
  320. float burst_damp_;
  321. float burst_comb_;
  322. float burst_duration_;
  323. int16_t trigger_, previous_trigger_;
  324. int16_t freeze_, previous_freeze_;
  325. /* internal states: */
  326. float spread_delay_[3];
  327. float comb_period_[4][2];
  328. float comb_feedback_[4][2];
  329. float hp_[4][2];
  330. Svf lp_[4][2];
  331. Svf bp_[4][2];
  332. Svf burst_lp_;
  333. Svf rand_lp_;
  334. OnePole rand_hp_;
  335. int32_t voice_, __align1;
  336. DISALLOW_COPY_AND_ASSIGN(Resonestor);
  337. };
  338. } // namespace clouds
  339. #endif // CLOUDS_DSP_RESONESTOR_H_