teensy audio WAVEFORM_ARBITRARY example?

A. Williams

Well-known member
Can anybody give a short example of using the arbitrary waveform code pieces with the teensy audio adapter board?

I am trying my damnedest to figure out how to use the abitrary waveform function to no avail, and there seems to be no documentation of WAVEFORM_ARBITRARY in use anywhere on the internet.
 
(I'm responding from a hotel and don't have a T3.1/audioboard in front of me)
I agree an example would be good to add. However, there is some information available.

Just checking that you read the documentation
http://www.pjrc.com/teensy/gui/?info=AudioSynthWaveform

which says
arbitraryWaveform(array, maxFreq);

Configure the waveform to be used with WAVEFORM_ARBITRARY. Array must be an array of 256 samples. Currently, the data is used without any filtering, which can cause aliasing with frequencies above 172 Hz. For higher frequency output, you must bandwidth limit your waveform data. Someday, "maxFreq" will be used to do this automatically.

The bandlimiting warning is not as serious as it sounds, since the built-in square, pulse, triangle and sawtooth waveforms are not bandlimited either. The limitation to 256 samples is better than it sounds, because linear interpolation is used between samples so the waveform is actually a 256-element piecewise linear approximation.

Turning now to the code, in (your arduino install location)/libraries/Audio/synth_waveform.h you see the definitions
Code:
  void arbitraryWaveform(const int16_t *data, float maxFreq) {
	arbdata = data;
  }
and
Code:
const int16_t *arbdata;

As noted, maxFreq can be anything as it is ignored currently. The data for the arbitrary waveform is signed, 16-bit integers.

Now, C/C++ are languages which unfortunately consider arrays, pointers and addresses to all be the same thing so we look at synth_waveform.cpp to find out more about this array.
Code:
case WAVEFORM_ARBITRARY:
      if (!arbdata) {
		release(block);
		return;
      }
      // len = 256
      for (int i = 0; i < AUDIO_BLOCK_SAMPLES;i++) {
		index = tone_phase >> 23;
		val1 = *(arbdata + index);
		val2 = *(arbdata + ((index + 1) & 255));
		scale = (tone_phase >> 7) & 0xFFFF;
		val2 *= scale;
		val1 *= 0xFFFF - scale;
		val3 = (val1 + val2) >> 16;
		*bp++ = (short)((val3 * tone_amp) >> 15);
		tone_phase += tone_incr;
		tone_phase &= 0x7fffffff;
      }
      break;
OK, confirmation (in a comment) that it is an array of 256 elements (not 257, like the sine function uses. Comparing this code to that of the sine function in the same file may however be helpful as they are similar, differing only in how they wrap around the waveform data array).

The sine data contains a full 360 degrees of sine data. Similarly the arbitrary waveform table must contain a full period of the waveform data, meaning that the first sample will be used right after the last sample (they should be similar values to avoid a discontinuity). Only a single table is used, not multiple tables of progressively decreased harmonic content, so ensure the harmonics are sufficient for the lowest frequency you plan to use; if aliasing is apparent, a steep low-pass filter at 18-21kHz before the DAC can be beneficial.

One last hint. Software aimed at sampling may well allow you to save out one-cycle waveform tables, but is likely to want to know both the frequency of the sample and the sampling rate; it will then write out a table with as many samples as are needed. However, for use with the audio library both of those items are irrelevant. Just pick values such that it gives you a table with exactly 256 entries.

As an example, if the sampling rate is fixed at 44.1kHz then you would tell it the frequency is 44100 / 256 = 172.26Hz. (you saw that number earlier, in the documentation; this is why). Similarly for 48kHz, say the frequency is 187.5Hz. Both will give you a table of 256 entries.

Hope that helps.
 
thank you for all this information!
i am, unfortunately unable to visualize this without seeing a piece of code with abitrary waveform in use, though i will look over the information given here again and again to see if i can figure anything out.
 
My main problem is, i don't really understand how to input the data necessary, I wish there was just a short example of a waveform built with the arbitrary waveform function, but I suppose these are uncharted waters?
 
i'm guessing these need to go somewhere in the code
Code:
waveform1.begin(volume, frequency, WAVEFORM_ARBITRARY);
  waveform1.arbitraryWaveform(*data,maxFreq);
void arbitraryWaveform(const int16_t *data, float maxFreq) {}
?
but i'm unsure how you would declare/edit the array of data and what type of variables would populate it
 
I wish there was just a short example of a waveform built with the arbitrary waveform function, but I suppose these are uncharted waters?

I also wish this. So far, I've seen message from a couple people who've said they used it, but not any complete code.

I really don't have time to work on a nice example... but if anyone who's actually used this to do something interesting wants to contribute one, I'd love to include it with future versions of the library!
 
Back
Top