PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

synth_simple_drum.cpp 5.8KB

3 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* Audio Library for Teensy 3.X
  2. * Copyright (c) 2016, Byron Jacquot, SparkFun Electronics
  3. *
  4. * Development of this audio library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <Arduino.h>
  27. #include "synth_simple_drum.h"
  28. extern "C" {
  29. extern const int16_t AudioWaveformSine[257];
  30. }
  31. void AudioSynthSimpleDrum::noteOn(void)
  32. {
  33. __disable_irq();
  34. wav_phasor = 0;
  35. wav_phasor2 = 0;
  36. env_lin_current = 0x7fff0000;
  37. __enable_irq();
  38. }
  39. void AudioSynthSimpleDrum::secondMix(float level)
  40. {
  41. // As level goes from 0.0 to 1.0,
  42. // second goes from 0 to 1/2 scale
  43. // first goes from full scale to half scale.
  44. if(level < 0)
  45. {
  46. level = 0;
  47. }
  48. else if(level > 1.0)
  49. {
  50. level = 1.0;
  51. }
  52. __disable_irq();
  53. wav_amplitude2 = level * 0x3fff;
  54. wav_amplitude1 = 0x7fff - wav_amplitude2;
  55. __enable_irq();
  56. }
  57. void AudioSynthSimpleDrum::pitchMod(float depth)
  58. {
  59. int32_t intdepth, calc;
  60. // Validate parameter
  61. if(depth < 0)
  62. {
  63. depth = 0;
  64. }
  65. else if(depth > 1.0)
  66. {
  67. depth = 1.0;
  68. }
  69. // Depth is float, 0.0..1.0
  70. // turn 0.0 to 1.0 into
  71. // 0x0 to 0x3fff;
  72. intdepth = depth * 0x7fff;
  73. // Lets turn it into 2.14, in range between -0.75 and 2.9999, woth 0 at 0.5
  74. // It becomes the scalar for the modulation component of the phasor increment.
  75. if(intdepth < 0x4000)
  76. {
  77. // 0 to 0.5 becomes
  78. // -0x3000 (0xffffCfff) to 0 ()
  79. calc = ((0x4000 - intdepth) * 0x3000 )>> 14;
  80. calc = -calc;
  81. }
  82. else
  83. {
  84. // 0.5 to 1.0 becomes
  85. // 0x00 to 0xbfa0
  86. calc = ((intdepth - 0x4000) * 0xc000)>> 14;
  87. }
  88. // Call result 2.14 format (max of ~3.99...approx 4)
  89. // See note in update().
  90. wav_pitch_mod = calc;
  91. }
  92. void AudioSynthSimpleDrum::update(void)
  93. {
  94. #if defined(KINETISK) || defined(__IMXRT1062__)
  95. audio_block_t *block_wav;
  96. int16_t *p_wave, *end;
  97. int32_t sin_l, sin_r, interp, mod, mod2, delta;
  98. int32_t interp2;
  99. int32_t index, scale;
  100. bool do_second;
  101. int32_t env_sqr_current; // the square of the linear value - inexpensive quasi exponential decay.
  102. block_wav = allocate();
  103. if (!block_wav) return;
  104. p_wave = (block_wav->data);
  105. end = p_wave + AUDIO_BLOCK_SAMPLES;
  106. // 50 is arbitrary threshold...
  107. // low values of second are inaudible, and we can save CPU cycles
  108. // by not calculating second when it's really quiet.
  109. do_second = (wav_amplitude2 > 50);
  110. while(p_wave < end)
  111. {
  112. // Do envelope first
  113. if(env_lin_current < 0x0000ffff)
  114. {
  115. // If envelope has expired, then stuff zeros into output buffer.
  116. *p_wave = 0;
  117. p_wave++;
  118. }
  119. else
  120. {
  121. env_lin_current -= env_decrement;
  122. env_sqr_current = multiply_16tx16t(env_lin_current, env_lin_current) ;
  123. // do wave second;
  124. wav_phasor += wav_increment;
  125. // modulation changes how we use the increment
  126. // the increment will be scaled by the modulation amount.
  127. //
  128. // Pitch mod is in range [-0.75 .. 3.99999] in 2.14 format
  129. // Current envelope value gets scaled by mod depth.
  130. // Then phasor increment gets scaled by that.
  131. mod = signed_multiply_32x16b((env_sqr_current), (wav_pitch_mod>>1)) >> 13;
  132. mod2 = signed_multiply_32x16b(wav_increment<<3, mod>>1);
  133. wav_phasor += (mod2);
  134. wav_phasor &= 0x7fffffff;
  135. if(do_second)
  136. {
  137. // A perfect fifth uses increment of 1.5 times regular increment
  138. wav_phasor2 += wav_increment;
  139. wav_phasor2 += (wav_increment >> 1);
  140. wav_phasor2 += mod2;
  141. wav_phasor2 += (mod2 >> 1);
  142. wav_phasor2 &= 0x7fffffff;
  143. }
  144. // Phase to Sine lookup * interp:
  145. index = wav_phasor >> 23; // take top valid 8 bits
  146. sin_l = AudioWaveformSine[index];
  147. sin_r = AudioWaveformSine[index+1];
  148. // The fraction of the phasor in time we are between L and R
  149. // is the same as the fraction of the ampliture of that interval we should add
  150. // to L.
  151. delta = sin_r-sin_l;
  152. scale = (wav_phasor >> 7) & 0xfFFF;
  153. delta = (delta * scale)>> 16;
  154. interp = sin_l + delta;
  155. if(do_second)
  156. {
  157. index = wav_phasor2 >> 23; // take top valid 8 bits
  158. sin_l = AudioWaveformSine[index];
  159. sin_r = AudioWaveformSine[index+1];
  160. delta = sin_r-sin_l;
  161. scale = (wav_phasor2 >> 7) & 0xFFFF;
  162. delta = (delta * scale)>> 16;
  163. interp2 = sin_l + delta;
  164. // Then scale and add the two waves
  165. interp2 = (interp2 * wav_amplitude2 ) >> 15;
  166. interp = (interp * wav_amplitude1) >> 15;
  167. interp = interp + interp2;
  168. }
  169. *p_wave = signed_multiply_32x16b(env_sqr_current, interp ) >> 15 ;
  170. p_wave++;
  171. }
  172. }
  173. transmit(block_wav, 0);
  174. release(block_wav);
  175. #endif
  176. }