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.

230 lines
6.1KB

  1. /*
  2. * Copyright (c) 2018 John-Michael Reed
  3. * bleeplabs.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 all
  13. * 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 THE
  21. * SOFTWARE.
  22. */
  23. #include <Arduino.h>
  24. #include "effect_granular.h"
  25. void AudioEffectGranular::begin(int16_t *sample_bank_def, int16_t max_len_def)
  26. {
  27. max_sample_len = max_len_def;
  28. grain_mode = 0;
  29. read_head = 0;
  30. write_head = 0;
  31. prev_input = 0;
  32. playpack_rate = 512;
  33. accumulator = 0;
  34. allow_len_change = true;
  35. sample_loaded = false;
  36. sample_bank = sample_bank_def;
  37. }
  38. void AudioEffectGranular::beginFreeze_int(int grain_samples)
  39. {
  40. __disable_irq();
  41. grain_mode = 1;
  42. if (grain_samples < max_sample_len) {
  43. freeze_len = grain_samples;
  44. } else {
  45. freeze_len = grain_samples;
  46. }
  47. sample_loaded = false;
  48. write_en = false;
  49. sample_req = true;
  50. __enable_irq();
  51. Serial.print("in = ");
  52. Serial.print(grain_samples);
  53. Serial.print(", freeze len = ");
  54. Serial.println(freeze_len);
  55. }
  56. void AudioEffectGranular::beginPitchShift_int(int grain_samples)
  57. {
  58. __disable_irq();
  59. grain_mode = 2;
  60. if (allow_len_change) {
  61. if (grain_samples < 100) grain_samples = 100;
  62. int maximum = (max_sample_len - 1) / 3;
  63. if (grain_samples > maximum) grain_samples = maximum;
  64. glitch_len = grain_samples;
  65. }
  66. sample_loaded = false;
  67. write_en = false;
  68. sample_req = true;
  69. __enable_irq();
  70. }
  71. void AudioEffectGranular::stop()
  72. {
  73. grain_mode = 0;
  74. allow_len_change = true;
  75. }
  76. void AudioEffectGranular::rate(int16_t playpack_rate_def)
  77. {
  78. playpack_rate = playpack_rate_def;
  79. }
  80. void AudioEffectGranular::update(void)
  81. {
  82. audio_block_t *block;
  83. if (sample_bank == NULL) {
  84. block = receiveReadOnly(0);
  85. if (block) release(block);
  86. return;
  87. }
  88. block = receiveWritable(0);
  89. if (!block) return;
  90. if (grain_mode == 0) {
  91. // passthrough, no granular effect
  92. prev_input = block->data[AUDIO_BLOCK_SAMPLES-1];
  93. }
  94. else if (grain_mode == 1) {
  95. //when activated the last
  96. for (int j = 0; j < AUDIO_BLOCK_SAMPLES; j++) {
  97. if (sample_req) {
  98. // only begin capture on zero cross
  99. int16_t current_input = block->data[j];
  100. if ((current_input < 0 && prev_input >= 0) ||
  101. (current_input >= 0 && prev_input < 0)) {
  102. write_en = true;
  103. write_head = 0;
  104. read_head = 0;
  105. sample_req = false;
  106. Serial.println("begin freeze capture");
  107. } else {
  108. prev_input = current_input;
  109. }
  110. }
  111. if (write_en) {
  112. sample_bank[write_head++] = block->data[j];
  113. if (write_head >= freeze_len) {
  114. sample_loaded = true;
  115. }
  116. if (write_head >= max_sample_len) {
  117. write_en = false;
  118. Serial.println("end freeze capture");
  119. }
  120. }
  121. if (sample_loaded) {
  122. if (playpack_rate >= 0) {
  123. accumulator += playpack_rate;
  124. read_head = accumulator >> 9;
  125. }
  126. if (read_head >= freeze_len) {
  127. accumulator = 0;
  128. read_head = 0;
  129. }
  130. block->data[j] = sample_bank[read_head];
  131. }
  132. }
  133. }
  134. else if (grain_mode == 2) {
  135. //GLITCH SHIFT
  136. //basic granular synth thingy
  137. // the shorter the sample the max_sample_len the more tonal it is.
  138. // Longer it has more definition. It's a bit roboty either way which
  139. // is obv great and good enough for noise music.
  140. for (int k = 0; k < AUDIO_BLOCK_SAMPLES; k++) {
  141. // only start recording when the audio is crossing zero to minimize pops
  142. if (sample_req) {
  143. int16_t current_input = block->data[k];
  144. if ((current_input < 0 && prev_input >= 0) ||
  145. (current_input >= 0 && prev_input < 0)) {
  146. write_en = true;
  147. } else {
  148. prev_input = current_input;
  149. }
  150. }
  151. if (write_en) {
  152. sample_req = false;
  153. allow_len_change = true; // Reduces noise by not allowing the
  154. // length to change after the sample has been
  155. // recored. Kind of not too much though
  156. if (write_head >= glitch_len) {
  157. write_head = 0;
  158. sample_loaded = true;
  159. write_en = false;
  160. allow_len_change = false;
  161. }
  162. sample_bank[write_head] = block->data[k];
  163. write_head++;
  164. }
  165. if (sample_loaded) {
  166. //move it to the middle third of the bank.
  167. //3 "seperate" banks are used
  168. float fade_len = 20.00;
  169. int16_t m2 = fade_len;
  170. for (int m = 0; m < 2; m++) {
  171. // I'm off by one somewhere? why is there a tick at the
  172. // beginning of this only when it's combined with the
  173. // fade out???? ooor am i osbserving that incorrectly
  174. // either wait it works enough
  175. sample_bank[m + glitch_len] = 0;
  176. }
  177. for (int m = 2; m < glitch_len-m2; m++) {
  178. sample_bank[m + glitch_len] = sample_bank[m];
  179. }
  180. for (int m = glitch_len-m2; m < glitch_len; m++) {
  181. // fade out the end. You can just make fadet=0
  182. // but it's a little too daleky
  183. float fadet = sample_bank[m] * (m2 / fade_len);
  184. sample_bank[m + glitch_len] = (int16_t)fadet;
  185. m2--;
  186. }
  187. sample_loaded = false;
  188. prev_input = block->data[k];
  189. sample_req = true;
  190. }
  191. accumulator += playpack_rate;
  192. read_head = (accumulator >> 9);
  193. if (read_head >= glitch_len) {
  194. read_head -= glitch_len;
  195. accumulator = 0;
  196. for (int m = 0; m < glitch_len; m++) {
  197. sample_bank[m + (glitch_len*2)] = sample_bank[m+glitch_len];
  198. // sample_bank[m + (glitch_len*2)] = (m%20)*1000;
  199. }
  200. }
  201. block->data[k] = sample_bank[read_head + (glitch_len*2)];
  202. }
  203. }
  204. transmit(block);
  205. release(block);
  206. }