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.

318 lines
8.8KB

  1. #include "Audio.h"
  2. #include "arm_math.h"
  3. #include "utility/dspinst.h"
  4. #ifdef ORIGINAL_AUDIOSYNTHWAVEFORM
  5. /******************************************************************/
  6. // PAH - add ramp-up and ramp-down to the onset of the wave
  7. // the length is specified in samples
  8. void AudioSynthWaveform::set_ramp_length(uint16_t r_length)
  9. {
  10. if(r_length < 0) {
  11. ramp_length = 0;
  12. return;
  13. }
  14. // Don't set the ramp length longer than about 4 milliseconds
  15. if(r_length > 44*4) {
  16. ramp_length = 44*4;
  17. return;
  18. }
  19. ramp_length = r_length;
  20. }
  21. void AudioSynthWaveform::update(void)
  22. {
  23. audio_block_t *block;
  24. uint32_t i, ph, inc, index, scale;
  25. int32_t val1, val2, val3;
  26. //Serial.println("AudioSynthWaveform::update");
  27. if (((magnitude > 0) || ramp_down) && (block = allocate()) != NULL) {
  28. ph = phase;
  29. inc = phase_increment;
  30. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  31. index = ph >> 24;
  32. val1 = wavetable[index];
  33. val2 = wavetable[index+1];
  34. scale = (ph >> 8) & 0xFFFF;
  35. val2 *= scale;
  36. val1 *= 0xFFFF - scale;
  37. val3 = (val1 + val2) >> 16;
  38. // The value of ramp_up is always initialized to RAMP_LENGTH and then is
  39. // decremented each time through here until it reaches zero.
  40. // The value of ramp_up is used to generate a Q15 fraction which varies
  41. // from [0 - 1), and multiplies this by the current sample
  42. if(ramp_up) {
  43. // ramp up to the new magnitude
  44. // ramp_mag is the Q15 representation of the fraction
  45. // Since ramp_up can't be zero, this cannot generate +1
  46. ramp_mag = ((ramp_length-ramp_up)<<15)/ramp_length;
  47. ramp_up--;
  48. block->data[i] = (val3 * ((ramp_mag * magnitude)>>15)) >> 15;
  49. } else if(ramp_down) {
  50. // ramp down to zero from the last magnitude
  51. // The value of ramp_down is always initialized to RAMP_LENGTH and then is
  52. // decremented each time through here until it reaches zero.
  53. // The value of ramp_down is used to generate a Q15 fraction which varies
  54. // from (1 - 0], and multiplies this by the current sample
  55. // avoid RAMP_LENGTH/RAMP_LENGTH because Q15 format
  56. // cannot represent +1
  57. ramp_mag = ((ramp_down - 1)<<15)/ramp_length;
  58. ramp_down--;
  59. block->data[i] = (val3 * ((ramp_mag * last_magnitude)>>15)) >> 15;
  60. } else {
  61. block->data[i] = (val3 * magnitude) >> 15;
  62. }
  63. //Serial.print(block->data[i]);
  64. //Serial.print(", ");
  65. //if ((i % 12) == 11) Serial.println();
  66. ph += inc;
  67. }
  68. //Serial.println();
  69. phase = ph;
  70. transmit(block);
  71. release(block);
  72. } else {
  73. // is this numerical overflow ok?
  74. phase += phase_increment * AUDIO_BLOCK_SAMPLES;
  75. }
  76. }
  77. #else
  78. /******************************************************************/
  79. // PAH - add ramp-up and ramp-down to the onset of the wave
  80. // the length is specified in samples
  81. void AudioSynthWaveform::set_ramp_length(uint16_t r_length)
  82. {
  83. if(r_length < 0) {
  84. ramp_length = 0;
  85. return;
  86. }
  87. // Don't set the ramp length longer than about 4 milliseconds
  88. if(r_length > 44*4) {
  89. ramp_length = 44*4;
  90. return;
  91. }
  92. ramp_length = r_length;
  93. }
  94. boolean AudioSynthWaveform::begin(float t_amp,int t_hi,short type)
  95. {
  96. tone_type = type;
  97. // tone_amp = t_amp;
  98. amplitude(t_amp);
  99. tone_freq = t_hi;
  100. if(t_hi < 1)return false;
  101. if(t_hi >= AUDIO_SAMPLE_RATE_EXACT/2)return false;
  102. tone_phase = 0;
  103. tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
  104. if(0) {
  105. Serial.print("AudioSynthWaveform.begin(tone_amp = ");
  106. Serial.print(t_amp);
  107. Serial.print(", tone_hi = ");
  108. Serial.print(t_hi);
  109. Serial.print(", tone_incr = ");
  110. Serial.print(tone_incr,HEX);
  111. // Serial.print(", tone_hi = ");
  112. // Serial.print(t_hi);
  113. Serial.println(")");
  114. }
  115. return(true);
  116. }
  117. void AudioSynthWaveform::update(void)
  118. {
  119. audio_block_t *block;
  120. short *bp;
  121. // temporary for ramp in sine
  122. uint32_t ramp_mag;
  123. // temporaries for TRIANGLE
  124. uint32_t mag;
  125. short tmp_amp;
  126. if(tone_freq == 0)return;
  127. // L E F T C H A N N E L O N L Y
  128. block = allocate();
  129. if(block) {
  130. bp = block->data;
  131. switch(tone_type) {
  132. case TONE_TYPE_SINE:
  133. for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
  134. // The value of ramp_up is always initialized to RAMP_LENGTH and then is
  135. // decremented each time through here until it reaches zero.
  136. // The value of ramp_up is used to generate a Q15 fraction which varies
  137. // from [0 - 1), and multiplies this by the current sample
  138. if(ramp_up) {
  139. // ramp up to the new magnitude
  140. // ramp_mag is the Q15 representation of the fraction
  141. // Since ramp_up can't be zero, this cannot generate +1
  142. ramp_mag = ((ramp_length-ramp_up)<<15)/ramp_length;
  143. ramp_up--;
  144. // adjust tone_phase to Q15 format and then adjust the result
  145. // of the multiplication
  146. *bp = (short)((arm_sin_q15(tone_phase>>17) * tone_amp) >> 15);
  147. *bp++ = (*bp * ramp_mag)>>15;
  148. }
  149. else if(ramp_down) {
  150. // ramp down to zero from the last magnitude
  151. // The value of ramp_down is always initialized to RAMP_LENGTH and then is
  152. // decremented each time through here until it reaches zero.
  153. // The value of ramp_down is used to generate a Q15 fraction which varies
  154. // from (1 - 0], and multiplies this by the current sample
  155. // avoid RAMP_LENGTH/RAMP_LENGTH because Q15 format
  156. // cannot represent +1
  157. ramp_mag = ((ramp_down - 1)<<15)/ramp_length;
  158. ramp_down--;
  159. // adjust tone_phase to Q15 format and then adjust the result
  160. // of the multiplication
  161. *bp = (short)((arm_sin_q15(tone_phase>>17) * last_tone_amp) >> 15);
  162. *bp++ = (*bp * ramp_mag)>>15;
  163. } else {
  164. // adjust tone_phase to Q15 format and then adjust the result
  165. // of the multiplication
  166. *bp++ = (short)((arm_sin_q15(tone_phase>>17) * tone_amp) >> 15);
  167. }
  168. // phase and incr are both unsigned 32-bit fractions
  169. tone_phase += tone_incr;
  170. }
  171. break;
  172. case TONE_TYPE_SQUARE:
  173. for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
  174. if(tone_phase & 0x80000000)*bp++ = -tone_amp;
  175. else *bp++ = tone_amp;
  176. // phase and incr are both unsigned 32-bit fractions
  177. tone_phase += tone_incr;
  178. }
  179. break;
  180. case TONE_TYPE_SAWTOOTH:
  181. for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
  182. *bp = ((short)(tone_phase>>16)*tone_amp) >> 15;
  183. bp++;
  184. // phase and incr are both unsigned 32-bit fractions
  185. tone_phase += tone_incr;
  186. }
  187. break;
  188. case TONE_TYPE_TRIANGLE:
  189. for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
  190. if(tone_phase & 0x80000000) {
  191. // negative half-cycle
  192. tmp_amp = -tone_amp;
  193. }
  194. else {
  195. // positive half-cycle
  196. tmp_amp = tone_amp;
  197. }
  198. mag = tone_phase << 2;
  199. // Determine which quadrant
  200. if(tone_phase & 0x40000000) {
  201. // negate the magnitude
  202. mag = ~mag + 1;
  203. }
  204. *bp++ = ((short)(mag>>17)*tmp_amp) >> 15;
  205. tone_phase += tone_incr;
  206. }
  207. break;
  208. }
  209. // send the samples to the left channel
  210. transmit(block,0);
  211. release(block);
  212. }
  213. }
  214. #endif
  215. #if 0
  216. void AudioSineWaveMod::frequency(float f)
  217. {
  218. if (f > AUDIO_SAMPLE_RATE_EXACT / 2 || f < 0.0) return;
  219. phase_increment = (f / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
  220. }
  221. void AudioSineWaveMod::update(void)
  222. {
  223. audio_block_t *block, *modinput;
  224. uint32_t i, ph, inc, index, scale;
  225. int32_t val1, val2;
  226. //Serial.println("AudioSineWave::update");
  227. modinput = receiveReadOnly();
  228. ph = phase;
  229. inc = phase_increment;
  230. block = allocate();
  231. if (!block) {
  232. // unable to allocate memory, so we'll send nothing
  233. if (modinput) {
  234. // but if we got modulation data, update the phase
  235. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  236. ph += inc + modinput->data[i] * modulation_factor;
  237. }
  238. release(modinput);
  239. } else {
  240. ph += phase_increment * AUDIO_BLOCK_SAMPLES;
  241. }
  242. phase = ph;
  243. return;
  244. }
  245. if (modinput) {
  246. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  247. index = ph >> 24;
  248. val1 = sine_table[index];
  249. val2 = sine_table[index+1];
  250. scale = (ph >> 8) & 0xFFFF;
  251. val2 *= scale;
  252. val1 *= 0xFFFF - scale;
  253. block->data[i] = (val1 + val2) >> 16;
  254. //Serial.print(block->data[i]);
  255. //Serial.print(", ");
  256. //if ((i % 12) == 11) Serial.println();
  257. ph += inc + modinput->data[i] * modulation_factor;
  258. }
  259. release(modinput);
  260. } else {
  261. ph = phase;
  262. inc = phase_increment;
  263. for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  264. index = ph >> 24;
  265. val1 = sine_table[index];
  266. val2 = sine_table[index+1];
  267. scale = (ph >> 8) & 0xFFFF;
  268. val2 *= scale;
  269. val1 *= 0xFFFF - scale;
  270. block->data[i] = (val1 + val2) >> 16;
  271. //Serial.print(block->data[i]);
  272. //Serial.print(", ");
  273. //if ((i % 12) == 11) Serial.println();
  274. ph += inc;
  275. }
  276. }
  277. phase = ph;
  278. transmit(block);
  279. release(block);
  280. }
  281. #endif