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.

362 lines
11KB

  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. // Transformations applied to a single STFT slice.
  28. #include "clouds/dsp/pvoc/frame_transformation.h"
  29. #include <algorithm>
  30. #include "stmlib/dsp/atan.h"
  31. #include "stmlib/dsp/units.h"
  32. #include "stmlib/utils/random.h"
  33. #include "clouds/dsp/frame.h"
  34. #include "clouds/dsp/parameters.h"
  35. namespace clouds {
  36. using namespace std;
  37. using namespace stmlib;
  38. void FrameTransformation::Init(
  39. float* buffer,
  40. int32_t fft_size,
  41. int32_t num_textures) {
  42. fft_size_ = fft_size;
  43. size_ = (fft_size >> 1) - kHighFrequencyTruncation;
  44. for (int32_t i = 0; i < num_textures; ++i) {
  45. textures_[i] = &buffer[i * size_];
  46. }
  47. phases_ = static_cast<uint16_t*>((void*)(textures_[num_textures - 1]));
  48. num_textures_ = num_textures - 1; // Last texture is used for storing phases.
  49. phases_delta_ = phases_ + size_;
  50. glitch_algorithm_ = 0;
  51. Reset();
  52. }
  53. void FrameTransformation::Reset() {
  54. for (int32_t i = 0; i < num_textures_; ++i) {
  55. fill(&textures_[i][0], &textures_[i][size_], 0.0f);
  56. }
  57. }
  58. void FrameTransformation::Process(
  59. const Parameters& parameters,
  60. float* fft_out,
  61. float* ifft_in) {
  62. fft_out[0] = 0.0f;
  63. fft_out[fft_size_ >> 1] = 0.0f;
  64. bool freeze = parameters.freeze;
  65. bool glitch = parameters.gate;
  66. float pitch_ratio = SemitonesToRatio(parameters.pitch);
  67. if (!freeze) {
  68. RectangularToPolar(fft_out);
  69. StoreMagnitudes(
  70. fft_out,
  71. parameters.position,
  72. parameters.spectral.refresh_rate);
  73. }
  74. float* temp = &fft_out[0];
  75. ReplayMagnitudes(ifft_in, parameters.position);
  76. WarpMagnitudes(ifft_in, temp, parameters.spectral.warp);
  77. ShiftMagnitudes(temp, ifft_in, pitch_ratio);
  78. if (glitch) {
  79. AddGlitch(ifft_in);
  80. }
  81. QuantizeMagnitudes(ifft_in, parameters.spectral.quantization);
  82. SetPhases(ifft_in, parameters.spectral.phase_randomization, pitch_ratio);
  83. PolarToRectangular(ifft_in);
  84. if (!glitch) {
  85. // Decide on which glitch algorithm will be used next time... if glitch
  86. // is enabled on the next frame!
  87. glitch_algorithm_ = stmlib::Random::GetSample() & 3;
  88. }
  89. ifft_in[0] = 0.0f;
  90. ifft_in[fft_size_ >> 1] = 0.0f;
  91. }
  92. void FrameTransformation::RectangularToPolar(float* fft_data) {
  93. float* real = &fft_data[0];
  94. float* imag = &fft_data[fft_size_ >> 1];
  95. float* magnitude = &fft_data[0];
  96. for (int32_t i = 1; i < size_; ++i) {
  97. uint16_t angle = fast_atan2r(imag[i], real[i], &magnitude[i]);
  98. phases_delta_[i] = angle - phases_[i];
  99. phases_[i] = angle;
  100. }
  101. }
  102. void FrameTransformation::SetPhases(
  103. float* destination,
  104. float phase_randomization,
  105. float pitch_ratio) {
  106. uint32_t* synthesis_phase = (uint32_t*) &destination[fft_size_ >> 1];
  107. for (int32_t i = 0; i < size_; ++i) {
  108. synthesis_phase[i] = phases_[i];
  109. phases_[i] += static_cast<uint16_t>(
  110. static_cast<float>(phases_delta_[i]) * pitch_ratio);
  111. }
  112. float r = phase_randomization;
  113. r = (r - 0.05f) * 1.06f;
  114. CONSTRAIN(r, 0.0f, 1.0f);
  115. r *= r;
  116. int32_t amount = static_cast<int32_t>(r * 32768.0f);
  117. for (int32_t i = 0; i < size_; ++i) {
  118. synthesis_phase[i] += \
  119. static_cast<int32_t>(stmlib::Random::GetSample()) * amount >> 14;
  120. }
  121. }
  122. void FrameTransformation::PolarToRectangular(float* fft_data) {
  123. float* real = &fft_data[0];
  124. float* imag = &fft_data[fft_size_ >> 1];
  125. float* magnitude = &fft_data[0];
  126. uint32_t* angle = (uint32_t*) &fft_data[fft_size_ >> 1];
  127. for (int32_t i = 1; i < size_; ++i) {
  128. fast_p2r(magnitude[i], angle[i], &real[i], &imag[i]);
  129. }
  130. for (int32_t i = size_; i < fft_size_ >> 1; ++i) {
  131. real[i] = imag[i] = 0.0f;
  132. }
  133. }
  134. void FrameTransformation::AddGlitch(float* xf_polar) {
  135. float* x = xf_polar;
  136. switch (glitch_algorithm_) {
  137. case 0:
  138. // Spectral hold and blow.
  139. {
  140. // Create trails
  141. float held = 0.0;
  142. for (int32_t i = 0; i < size_; ++i) {
  143. if ((stmlib::Random::GetSample() & 15) == 0) {
  144. held = x[i];
  145. }
  146. x[i] = held;
  147. held = held * 1.01f;
  148. }
  149. }
  150. break;
  151. case 1:
  152. // Spectral shift up with aliasing.
  153. {
  154. float factor = 1.0f + (stmlib::Random::GetSample() & 7) / 4.0f;
  155. float source = 0.0f;
  156. for (int32_t i = 0; i < size_; ++i) {
  157. source += factor;
  158. if (source >= size_) {
  159. source = 0.0f;
  160. }
  161. x[i] = x[static_cast<int32_t>(source)];
  162. }
  163. }
  164. break;
  165. case 2:
  166. // Kill largest harmonic and boost second largest.
  167. *std::max_element(&x[0], &x[size_]) = 0.0f;
  168. *std::max_element(&x[0], &x[size_]) *= 8.0f;
  169. break;
  170. case 3:
  171. {
  172. // Nasty high-pass
  173. for (int32_t i = 0; i < size_; ++i) {
  174. uint32_t random = stmlib::Random::GetSample() & 15;
  175. if (random == 0) {
  176. x[i] *= static_cast<float>(i) / 16.0f;
  177. }
  178. }
  179. }
  180. break;
  181. default:
  182. break;
  183. }
  184. }
  185. void FrameTransformation::QuantizeMagnitudes(float* xf_polar, float amount) {
  186. if (amount <= 0.48f) {
  187. amount = amount * 2.0f;
  188. float scale_down = 0.5f * SemitonesToRatio(
  189. -108.0f * (1.0f - amount * amount)) / float(fft_size_);
  190. float scale_up = 1.0f / scale_down;
  191. for (int32_t i = 0.0f; i < size_; ++i) {
  192. xf_polar[i] = scale_up * static_cast<float>(
  193. static_cast<int32_t>(scale_down * xf_polar[i]));
  194. }
  195. } else if (amount >= 0.52f) {
  196. amount = (amount - 0.52f) * 2.0f;
  197. float norm = *std::max_element(&xf_polar[0], &xf_polar[size_]);
  198. float inv_norm = 1.0f / (norm + 0.0001f);
  199. for (int32_t i = 1.0f; i < size_; ++i) {
  200. float x = xf_polar[i] * inv_norm;
  201. float warped = 4.0f * x * (1.0f - x) * (1.0f - x) * (1.0f - x);
  202. xf_polar[i] = (x + (warped - x) * amount) * norm;
  203. }
  204. }
  205. }
  206. const float kWarpPolynomials[6][4] = {
  207. { 10.5882f, -14.8824f, 5.29412f, 0.0f },
  208. { -7.3333f, +9.0, -1.79167f, 0.125f },
  209. { 0.0f, 0.0f, 1.0f, 0.0f },
  210. { 0.0f, 0.5f, 0.5f, 0.0f },
  211. { -7.3333f, +9.5f, -2.416667f, 0.25f },
  212. { -7.3333f, +9.5f, -2.416667f, 0.25f },
  213. };
  214. void FrameTransformation::WarpMagnitudes(
  215. float* source,
  216. float* xf_polar,
  217. float amount) {
  218. float bin_width = 1.0f / static_cast<float>(size_);
  219. float f = 0.0;
  220. float coefficients[4];
  221. amount *= 4.0f;
  222. MAKE_INTEGRAL_FRACTIONAL(amount);
  223. for (int32_t i = 0; i < 4; ++i) {
  224. coefficients[i] = Crossfade(
  225. kWarpPolynomials[amount_integral][i],
  226. kWarpPolynomials[amount_integral + 1][i],
  227. amount_fractional);
  228. }
  229. float a = coefficients[0];
  230. float b = coefficients[1];
  231. float c = coefficients[2];
  232. float d = coefficients[3];
  233. for (int32_t i = 1.0f; i < size_; ++i) {
  234. f += bin_width;
  235. float wf = (d + f * (c + f * (b + a * f))) * size_;
  236. xf_polar[i] = Interpolate(source, wf, 1.0f);
  237. }
  238. }
  239. void FrameTransformation::ShiftMagnitudes(
  240. float* source,
  241. float* xf_polar,
  242. float pitch_ratio) {
  243. float* destination = &xf_polar[0];
  244. float* temp = &xf_polar[size_];
  245. if (pitch_ratio == 1.0f) {
  246. copy(&source[0], &source[size_], &temp[0]);
  247. } else if (pitch_ratio > 1.0f) {
  248. float index = 1.0f;
  249. float increment = 1.0f / pitch_ratio;
  250. for (int32_t i = 1; i < size_; ++i) {
  251. temp[i] = Interpolate(source, index, 1.0f);
  252. index += increment;
  253. }
  254. } else {
  255. fill(&temp[0], &temp[size_], 0.0f);
  256. float index = 1.0f;
  257. float increment = pitch_ratio;
  258. for (int32_t i = 1; i < size_; ++i) {
  259. MAKE_INTEGRAL_FRACTIONAL(index)
  260. temp[index_integral] += (1.0f - index_fractional) * source[i];
  261. temp[index_integral + 1] += index_fractional * source[i];
  262. index += increment;
  263. }
  264. }
  265. copy(&temp[0], &temp[size_], &destination[0]);
  266. }
  267. void FrameTransformation::StoreMagnitudes(
  268. float* xf_polar,
  269. float position,
  270. float feedback) {
  271. // Write into magnitude buffers.
  272. float index_float = position * float(num_textures_ - 1);
  273. int32_t index_int = static_cast<int32_t>(index_float);
  274. float index_fractional = index_float - index_int;
  275. float gain_a = 1.0f - index_fractional;
  276. float gain_b = index_fractional;
  277. float* a = textures_[index_int];
  278. float* b = textures_[index_int + (position == 1.0f ? 0 : 1)];
  279. if (feedback >= 0.5f) {
  280. feedback = 2.0f * (feedback - 0.5f);
  281. if (feedback < 0.5f) {
  282. gain_a *= 1.0f - feedback;
  283. gain_b *= 1.0f - feedback;
  284. for (int32_t i = 0; i < size_; ++i) {
  285. float x = *xf_polar++;
  286. a[i] = Crossfade(a[i], x, gain_a);
  287. b[i] = Crossfade(b[i], x, gain_b);
  288. }
  289. } else {
  290. float t = (feedback - 0.5f) * 0.7f + 0.5f;
  291. float gain_new = t - 0.5f;
  292. gain_new = gain_new * gain_new * 2.0f + 0.5f;
  293. float gain_new_a = gain_a * gain_new;
  294. float gain_new_b = gain_b * gain_new;
  295. float gain_old_a = 1.0f - gain_a * (1.0f - t);
  296. float gain_old_b = 1.0f - gain_b * (1.0f - t);
  297. for (int32_t i = 0; i < size_; ++i) {
  298. float x = *xf_polar++;
  299. a[i] = a[i] * gain_old_a + x * gain_new_a;
  300. b[i] = b[i] * gain_old_b + x * gain_new_b;
  301. }
  302. }
  303. } else {
  304. feedback *= 2.0f;
  305. feedback *= feedback;
  306. uint16_t threshold = feedback * 65535.0f;
  307. for (int32_t i = 0; i < size_; ++i) {
  308. float x = *xf_polar++;
  309. float gain = static_cast<uint16_t>(Random::GetSample()) <= threshold
  310. ? 1.0f : 0.0f;
  311. a[i] = Crossfade(a[i], x, gain_a * gain);
  312. b[i] = Crossfade(b[i], x, gain_b * gain);
  313. }
  314. }
  315. }
  316. void FrameTransformation::ReplayMagnitudes(float* xf_polar, float position) {
  317. float index_float = position * float(num_textures_ - 1);
  318. int32_t index_int = static_cast<int32_t>(index_float);
  319. float index_fractional = index_float - static_cast<float>(index_int);
  320. float* a = textures_[index_int];
  321. float* b = textures_[index_int + (position == 1.0f ? 0 : 1)];
  322. for (int32_t i = 0; i < size_; ++i) {
  323. xf_polar[i] = Crossfade(a[i], b[i], index_fractional);
  324. }
  325. }
  326. } // namespace clouds