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.

209 line
5.7KB

  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 "synth_simple_drum.h"
  27. extern "C" {
  28. extern const int16_t AudioWaveformSine[257];
  29. }
  30. void AudioSynthSimpleDrum::noteOn(void)
  31. {
  32. __disable_irq();
  33. wav_phasor = 0;
  34. wav_phasor2 = 0;
  35. env_lin_current = 0x7fff0000;
  36. __enable_irq();
  37. }
  38. void AudioSynthSimpleDrum::secondMix(float level)
  39. {
  40. // As level goes from 0.0 to 1.0,
  41. // second goes from 0 to 1/2 scale
  42. // first goes from full scale to half scale.
  43. if(level < 0)
  44. {
  45. level = 0;
  46. }
  47. else if(level > 1.0)
  48. {
  49. level = 1.0;
  50. }
  51. __disable_irq();
  52. wav_amplitude2 = level * 0x3fff;
  53. wav_amplitude1 = 0x7fff - wav_amplitude2;
  54. __enable_irq();
  55. }
  56. void AudioSynthSimpleDrum::pitchMod(float depth)
  57. {
  58. int32_t intdepth, calc;
  59. // Validate parameter
  60. if(depth < 0)
  61. {
  62. depth = 0;
  63. }
  64. else if(depth > 1.0)
  65. {
  66. depth = 1.0;
  67. }
  68. // Depth is float, 0.0..1.0
  69. // turn 0.0 to 1.0 into
  70. // 0x0 to 0x3fff;
  71. intdepth = depth * 0x7fff;
  72. // Lets turn it into 2.14, in range between -0.75 and 2.9999, woth 0 at 0.5
  73. // It becomes the scalar for the modulation component of the phasor increment.
  74. if(intdepth < 0x4000)
  75. {
  76. // 0 to 0.5 becomes
  77. // -0x3000 (0xffffCfff) to 0 ()
  78. calc = ((0x4000 - intdepth) * 0x3000 )>> 14;
  79. calc = -calc;
  80. }
  81. else
  82. {
  83. // 0.5 to 1.0 becomes
  84. // 0x00 to 0xbfa0
  85. calc = ((intdepth - 0x4000) * 0xc000)>> 14;
  86. }
  87. // Call result 2.14 format (max of ~3.99...approx 4)
  88. // See note in update().
  89. wav_pitch_mod = calc;
  90. }
  91. void AudioSynthSimpleDrum::update(void)
  92. {
  93. audio_block_t *block_wav;
  94. int16_t *p_wave, *end;
  95. int32_t sin_l, sin_r, interp, mod, mod2, delta;
  96. int32_t interp2;
  97. int32_t index, scale;
  98. bool do_second;
  99. int32_t env_sqr_current; // the square of the linear value - inexpensive quasi exponential decay.
  100. block_wav = allocate();
  101. if (!block_wav) return;
  102. p_wave = (block_wav->data);
  103. end = p_wave + AUDIO_BLOCK_SAMPLES;
  104. // 50 is arbitrary threshold...
  105. // low values of second are inaudible, and we can save CPU cycles
  106. // by not calculating second when it's really quiet.
  107. do_second = (wav_amplitude2 > 50);
  108. while(p_wave < end)
  109. {
  110. // Do envelope first
  111. if(env_lin_current < 0x0000ffff)
  112. {
  113. // If envelope has expired, then stuff zeros into output buffer.
  114. *p_wave = 0;
  115. p_wave++;
  116. }
  117. else
  118. {
  119. env_lin_current -= env_decrement;
  120. env_sqr_current = multiply_16tx16t(env_lin_current, env_lin_current) ;
  121. // do wave second;
  122. wav_phasor += wav_increment;
  123. // modulation changes how we use the increment
  124. // the increment will be scaled by the modulation amount.
  125. //
  126. // Pitch mod is in range [-0.75 .. 3.99999] in 2.14 format
  127. // Current envelope value gets scaled by mod depth.
  128. // Then phasor increment gets scaled by that.
  129. mod = signed_multiply_32x16b((env_sqr_current), (wav_pitch_mod>>1)) >> 13;
  130. mod2 = signed_multiply_32x16b(wav_increment<<3, mod>>1);
  131. wav_phasor += (mod2);
  132. wav_phasor &= 0x7fffffff;
  133. if(do_second)
  134. {
  135. // A perfect fifth uses increment of 1.5 times regular increment
  136. wav_phasor2 += wav_increment;
  137. wav_phasor2 += (wav_increment >> 1);
  138. wav_phasor2 += mod2;
  139. wav_phasor2 += (mod2 >> 1);
  140. wav_phasor2 &= 0x7fffffff;
  141. }
  142. // Phase to Sine lookup * interp:
  143. index = wav_phasor >> 23; // take top valid 8 bits
  144. sin_l = AudioWaveformSine[index];
  145. sin_r = AudioWaveformSine[index+1];
  146. // The fraction of the phasor in time we are between L and R
  147. // is the same as the fraction of the ampliture of that interval we should add
  148. // to L.
  149. delta = sin_r-sin_l;
  150. scale = (wav_phasor >> 7) & 0xfFFF;
  151. delta = (delta * scale)>> 16;
  152. interp = sin_l + delta;
  153. if(do_second)
  154. {
  155. index = wav_phasor2 >> 23; // take top valid 8 bits
  156. sin_l = AudioWaveformSine[index];
  157. sin_r = AudioWaveformSine[index+1];
  158. delta = sin_r-sin_l;
  159. scale = (wav_phasor2 >> 7) & 0xFFFF;
  160. delta = (delta * scale)>> 16;
  161. interp2 = sin_l + delta;
  162. // Then scale and add the two waves
  163. interp2 = (interp2 * wav_amplitude2 ) >> 15;
  164. interp = (interp * wav_amplitude1) >> 15;
  165. interp = interp + interp2;
  166. }
  167. *p_wave = signed_multiply_32x16b(env_sqr_current, interp ) >> 15 ;
  168. p_wave++;
  169. }
  170. }
  171. transmit(block_wav, 0);
  172. release(block_wav);
  173. }