ERIS CORE
eris_synth_waveform.cpp
Go to the documentation of this file.
1 /* Audio Library for Teensy 3.X
2  * Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com
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 
27 #include <Arduino.h>
28 #include "eris_synth_waveform.h"
29 #include "arm_math.h"
30 #include "utility/dspinst.h"
31 
32 // uncomment for more accurate but more computationally expensive frequency modulation
33 //#define IMPROVE_EXPONENTIAL_ACCURACY
34 #define BASE_AMPLITUDE 0x6000 // 0x7fff won't work due to Gibb's phenomenon, so use 3/4 of full range.
35 
36 
37 //added for Eris Core
39  //select from an array of static waveforms stored in program memory
40  if (program < 128){
41  arbdata = wt[program];
42  }
43 }
44 
46 {
47  audio_block_t *block;
48  int16_t *bp, *end;
49  int32_t val1, val2;
50  int16_t magnitude15;
51  uint32_t i, ph, index, index2, scale;
52  const uint32_t inc = phase_increment;
53 
55  if (magnitude == 0) {
56  phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
57  return;
58  }
59  block = allocate();
60  if (!block) {
61  phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
62  return;
63  }
64  bp = block->data;
65 
66  switch(tone_type) {
67  case WAVEFORM_SINE:
68  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
69  index = ph >> 24;
70  val1 = AudioWaveformSine[index];
71  val2 = AudioWaveformSine[index+1];
72  scale = (ph >> 8) & 0xFFFF;
73  val2 *= scale;
74  val1 *= 0x10000 - scale;
75  *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
76  ph += inc;
77  }
78  break;
79 
80  case WAVEFORM_ARBITRARY:
81  if (!arbdata) {
82  release(block);
83  phase_accumulator += inc * AUDIO_BLOCK_SAMPLES;
84  return;
85  }
86  // len = 256
87  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
88  index = ph >> 21;
89  index2 = index + 1;
90  if (index2 >= 2048) index2 = 0;
91  val1 = *(arbdata + index);
92  val2 = *(arbdata + index2);
93  scale = (ph >> 8) & 0xFFFF;
94  val2 *= scale;
95  val1 *= 0x10000 - scale;
96  *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
97  ph += inc;
98  }
99  break;
100 
101  case WAVEFORM_SQUARE:
102  magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
103  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
104  if (ph & 0x80000000) {
105  *bp++ = -magnitude15;
106  } else {
107  *bp++ = magnitude15;
108  }
109  ph += inc;
110  }
111  break;
112 
113  case WAVEFORM_BANDLIMIT_SQUARE:
114  for (int i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
115  {
116  uint32_t new_ph = ph + inc ;
117  int16_t val = band_limit_waveform.generate_square (new_ph, i) ;
118  *bp++ = (val * magnitude) >> 16 ;
119  ph = new_ph ;
120  }
121  break;
122 
123  case WAVEFORM_SAWTOOTH:
124  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
125  *bp++ = signed_multiply_32x16t(magnitude, ph);
126  ph += inc;
127  }
128  break;
129 
130  case WAVEFORM_SAWTOOTH_REVERSE:
131  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
132  *bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, ph);
133  ph += inc;
134  }
135  break;
136 
137  case WAVEFORM_BANDLIMIT_SAWTOOTH:
138  case WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE:
139  for (i = 0 ; i < AUDIO_BLOCK_SAMPLES; i++)
140  {
141  uint32_t new_ph = ph + inc ;
142  int16_t val = band_limit_waveform.generate_sawtooth (new_ph, i) ;
143  if (tone_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE)
144  *bp++ = (val * -magnitude) >> 16 ;
145  else
146  *bp++ = (val * magnitude) >> 16 ;
147  ph = new_ph ;
148  }
149  break;
150 
151  case WAVEFORM_TRIANGLE:
152  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
153  uint32_t phtop = ph >> 30;
154  if (phtop == 1 || phtop == 2) {
155  *bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16;
156  } else {
157  *bp++ = (((int32_t)ph >> 15) * magnitude) >> 16;
158  }
159  ph += inc;
160  }
161  break;
162 
163  case WAVEFORM_TRIANGLE_VARIABLE:
164  do {
165  uint32_t rise = 0xFFFFFFFF / (pulse_width >> 16);
166  uint32_t fall = 0xFFFFFFFF / (0xFFFF - (pulse_width >> 16));
167  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
168  if (ph < pulse_width/2) {
169  uint32_t n = (ph >> 16) * rise;
170  *bp++ = ((n >> 16) * magnitude) >> 16;
171  } else if (ph < 0xFFFFFFFF - pulse_width/2) {
172  uint32_t n = 0x7FFFFFFF - (((ph - pulse_width/2) >> 16) * fall);
173  *bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
174  } else {
175  uint32_t n = ((ph + pulse_width/2) >> 16) * rise + 0x80000000;
176  *bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
177  }
178  ph += inc;
179  }
180  } while (0);
181  break;
182 
183  case WAVEFORM_PULSE:
184  magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
185  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
186  if (ph < pulse_width) {
187  *bp++ = magnitude15;
188  } else {
189  *bp++ = -magnitude15;
190  }
191  ph += inc;
192  }
193  break;
194 
195  case WAVEFORM_BANDLIMIT_PULSE:
196  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++)
197  {
198  int32_t new_ph = ph + inc ;
199  int32_t val = band_limit_waveform.generate_pulse (new_ph, pulse_width, i) ;
200  *bp++ = (int16_t) ((val * magnitude) >> 16) ;
201  ph = new_ph ;
202  }
203  break;
204 
205  case WAVEFORM_SAMPLE_HOLD:
206  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
207  *bp++ = sample;
208  uint32_t newph = ph + inc;
209  if (newph < ph) {
210  sample = random(magnitude) - (magnitude >> 1);
211  }
212  ph = newph;
213  }
214  break;
215  }
217 
218  if (tone_offset) {
219  bp = block->data;
220  end = bp + AUDIO_BLOCK_SAMPLES;
221  do {
222  val1 = *bp;
223  *bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
224  } while (bp < end);
225  }
226  transmit(block, 0);
227  release(block);
228 }
229 
230 //--------------------------------------------------------------------------------
231 
233  //select from an array of static waveforms stored in program memory
234  if (program < 128){
235  arbdata = wt[program];
236  }
237 }
238 
240 {
241  audio_block_t *block, *moddata, *shapedata;
242  int16_t *bp, *end;
243  int32_t val1, val2;
244  int16_t magnitude15;
245  uint32_t i, ph, index, index2, scale, priorphase;
246  const uint32_t inc = phase_increment;
247 
248  moddata = receiveReadOnly(0);
249  shapedata = receiveReadOnly(1);
250 
251  // Pre-compute the phase angle for every output sample of this update
252  ph = phase_accumulator;
253  priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1];
254  if (moddata && modulation_type == 0) {
255  // Frequency Modulation
256  bp = moddata->data;
257  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
258  int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
259  int32_t ipart = n >> 27; // 4 integer bits
260  n &= 0x7FFFFFF; // 27 fractional bits
261  #ifdef IMPROVE_EXPONENTIAL_ACCURACY
262  // exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
263  // mail list, Wed, 3 Sep 2014 10:08:55 +0200
264  int32_t x = n << 3;
265  n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
266  int32_t sq = multiply_32x32_rshift32_rounded(x, x);
267  n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
268  n = n + (multiply_32x32_rshift32_rounded(sq,
269  multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
270  n = n << 1;
271  #else
272  // exp2 algorithm by Laurent de Soras
273  // https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
274  n = (n + 134217728) << 3;
275 
276  n = multiply_32x32_rshift32_rounded(n, n);
277  n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
278  n = n + 715827882;
279  #endif
280  uint32_t scale = n >> (14 - ipart);
281  uint64_t phstep = (uint64_t)inc * scale;
282  uint32_t phstep_msw = phstep >> 32;
283  if (phstep_msw < 0x7FFE) {
284  ph += phstep >> 16;
285  } else {
286  ph += 0x7FFE0000;
287  }
288  phasedata[i] = ph;
289  }
290  release(moddata);
291  } else if (moddata) {
292  // Phase Modulation
293  bp = moddata->data;
294  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
295  // more than +/- 180 deg shift by 32 bit overflow of "n"
296  uint32_t n = ((uint32_t)(*bp++)) * modulation_factor;
297  phasedata[i] = ph + n;
298  ph += inc;
299  }
300  release(moddata);
301  } else {
302  // No Modulation Input
303  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
304  phasedata[i] = ph;
305  ph += inc;
306  }
307  }
308  phase_accumulator = ph;
309 
310  // If the amplitude is zero, no output, but phase still increments properly
311  if (magnitude == 0) {
312  if (shapedata) release(shapedata);
313  return;
314  }
315  block = allocate();
316  if (!block) {
317  if (shapedata) release(shapedata);
318  return;
319  }
320  bp = block->data;
321 
322  // Now generate the output samples using the pre-computed phase angles
323  switch(tone_type) {
324  case WAVEFORM_SINE:
325  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
326  ph = phasedata[i];
327  index = ph >> 24;
328  val1 = AudioWaveformSine[index];
329  val2 = AudioWaveformSine[index+1];
330  scale = (ph >> 8) & 0xFFFF;
331  val2 *= scale;
332  val1 *= 0x10000 - scale;
333  *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
334  }
335  break;
336 
337  case WAVEFORM_ARBITRARY:
338  if (!arbdata) {
339  release(block);
340  if (shapedata) release(shapedata);
341  return;
342  }
343  // len = 256
344  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
345  ph = phasedata[i];
346  index = ph >> 21;//ERIS CORE -- change from 24 (256 sample) to 21 (2048 samples)
347  index2 = index + 1;
348  if (index2 >= 2048) index2 = 0;
349  val1 = *(arbdata + index);
350  val2 = *(arbdata + index2);
351  scale = (ph >> 8) & 0xFFFF;
352  val2 *= scale;
353  val1 *= 0x10000 - scale;
354  *bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
355  }
356  break;
357 
358  case WAVEFORM_PULSE:
359  if (shapedata) {
360  magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
361  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
362  uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16;
363  if (phasedata[i] < width) {
364  *bp++ = magnitude15;
365  } else {
366  *bp++ = -magnitude15;
367  }
368  }
369  break;
370  } // else fall through to orginary square without shape modulation
371 
372  case WAVEFORM_SQUARE:
373  magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
374  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
375  if (phasedata[i] & 0x80000000) {
376  *bp++ = -magnitude15;
377  } else {
378  *bp++ = magnitude15;
379  }
380  }
381  break;
382 
383  case WAVEFORM_BANDLIMIT_PULSE:
384  if (shapedata)
385  {
386  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++)
387  {
388  uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16;
389  int32_t val = band_limit_waveform.generate_pulse (phasedata[i], width, i) ;
390  *bp++ = (int16_t) ((val * magnitude) >> 16) ;
391  }
392  break;
393  } // else fall through to orginary square without shape modulation
394 
395  case WAVEFORM_BANDLIMIT_SQUARE:
396  for (i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
397  {
398  int32_t val = band_limit_waveform.generate_square (phasedata[i], i) ;
399  *bp++ = (int16_t) ((val * magnitude) >> 16) ;
400  }
401  break;
402 
403  case WAVEFORM_SAWTOOTH:
404  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
405  *bp++ = signed_multiply_32x16t(magnitude, phasedata[i]);
406  }
407  break;
408 
409  case WAVEFORM_SAWTOOTH_REVERSE:
410  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
411  *bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, phasedata[i]);
412  }
413  break;
414 
415  case WAVEFORM_BANDLIMIT_SAWTOOTH:
416  case WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE:
417  for (i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
418  {
419  int16_t val = band_limit_waveform.generate_sawtooth (phasedata[i], i) ;
420  val = (int16_t) ((val * magnitude) >> 16) ;
421  *bp++ = tone_type == WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE ? (int16_t) -val : (int16_t) +val ;
422  }
423  break;
424 
425  case WAVEFORM_TRIANGLE_VARIABLE:
426  if (shapedata) {
427  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
428  uint32_t width = (shapedata->data[i] + 0x8000) & 0xFFFF;
429  uint32_t rise = 0xFFFFFFFF / width;
430  uint32_t fall = 0xFFFFFFFF / (0xFFFF - width);
431  uint32_t halfwidth = width << 15;
432  uint32_t n;
433  ph = phasedata[i];
434  if (ph < halfwidth) {
435  n = (ph >> 16) * rise;
436  *bp++ = ((n >> 16) * magnitude) >> 16;
437  } else if (ph < 0xFFFFFFFF - halfwidth) {
438  n = 0x7FFFFFFF - (((ph - halfwidth) >> 16) * fall);
439  *bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
440  } else {
441  n = ((ph + halfwidth) >> 16) * rise + 0x80000000;
442  *bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
443  }
444  ph += inc;
445  }
446  break;
447  } // else fall through to orginary triangle without shape modulation
448 
449  case WAVEFORM_TRIANGLE:
450  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
451  ph = phasedata[i];
452  uint32_t phtop = ph >> 30;
453  if (phtop == 1 || phtop == 2) {
454  *bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16;
455  } else {
456  *bp++ = (((int32_t)ph >> 15) * magnitude) >> 16;
457  }
458  }
459  break;
460  case WAVEFORM_SAMPLE_HOLD:
461  for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
462  ph = phasedata[i];
463  if (ph < priorphase) { // does not work for phase modulation
464  sample = random(magnitude) - (magnitude >> 1);
465  }
466  priorphase = ph;
467  *bp++ = sample;
468  }
469  break;
470  }
471 
472  if (tone_offset) {
473  bp = block->data;
474  end = bp + AUDIO_BLOCK_SAMPLES;
475  do {
476  val1 = *bp;
477  *bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
478  } while (bp < end);
479  }
480  if (shapedata) release(shapedata);
481  transmit(block, 0);
482  release(block);
483 }
484 
static void release(audio_block_t *block)
static audio_block_t * allocate(void)
Definition: AudioStream.cpp:92
audio_block_t * receiveReadOnly(unsigned int index=0)
void transmit(audio_block_t *block, unsigned char index=0)
void arbitraryProgram(uint8_t program)
BandLimitedWaveform band_limit_waveform
uint32_t phasedata[AUDIO_BLOCK_SAMPLES]
BandLimitedWaveform band_limit_waveform
void arbitraryProgram(uint8_t program)
virtual void update(void)
const int16_t AudioWaveformSine[257]
const int16_t ** wt
int16_t data[AUDIO_BLOCK_SAMPLES]
Definition: AudioStream.h:78