Large wavetables using waveform object.

Status
Not open for further replies.

thedreiskre

Active member
I have managed to create wavetables containing ~5 waves by assigning them to seperate waveform objects and then fading between them. However this is starting to get quite CPU intensive for more waves. I have been trying to figure out the best way to adapt the waveform arbitrary code, to allow for wavetables in 1 object. My plan is to store the table position as a float, eg. 1.7 would be somewhere between wave 1 and 2. Then have 1 sample from wave 1 have a "weight" of 0.7, and 1 sample from wave 2 have a weight of 0.3. My intention was to have the waves be stored in a single long array of integers, then have the table position value be an offset. So for example, a position value of 1.7 would result in an offset of (1 * 256) for wave 1, (2*256) for wave 2, and a mix of (0.7 * wave1) and (0.3 * wave2). Okay so this sounds simple enough, however when i was trying to see how to implement it, I couldn't understand a lot of the existing waveform arbitrary code. How would the offset be done? and would having a longer arbdata array break all the existing code? also, what is going on with all the pointers and scale and *bp++ ?

Sorry if this is either painfully simple, or overly optimistic, I haven't been using c++ for too long so please go easy :)
 
I have managed to create wavetables containing ~5 waves by assigning them to seperate waveform objects and then fading between them. However this is starting to get quite CPU intensive for more waves. I have been trying to figure out the best way to adapt the waveform arbitrary code, to allow for wavetables in 1 object. My plan is to store the table position as a float, eg. 1.7 would be somewhere between wave 1 and 2. Then have 1 sample from wave 1 have a "weight" of 0.7, and 1 sample from wave 2 have a weight of 0.3. My intention was to have the waves be stored in a single long array of integers, then have the table position value be an offset. So for example, a position value of 1.7 would result in an offset of (1 * 256) for wave 1, (2*256) for wave 2, and a mix of (0.7 * wave1) and (0.3 * wave2). Okay so this sounds simple enough, however when i was trying to see how to implement it, I couldn't understand a lot of the existing waveform arbitrary code. How would the offset be done? and would having a longer arbdata array break all the existing code? also, what is going on with all the pointers and scale and *bp++ ?

Sorry if this is either painfully simple, or overly optimistic, I haven't been using c++ for too long so please go easy :)

You mean AudioSynthWaveform with WAVEFORM_ARBITRARY? Or AudioSynthWavetable?

With the former why not just have two waveform objects and cross-fade between them - its trivial and
cheap to reset the table. So first you crossfade wave0 to wave1, then wave1 to wave2 by replacing wave0 by
wave2 in one of the objects, etc.

BTW the code for WAVEFORM_ARBITRARY just does a linear interpolation in the waveform table using the current phase accumulator.
 
I was doing the crossfading before and it worked well, I was just looking really for a way to modulate the table position using LFOs and envelopes. I was hoping to get the shape input to work as table position, but if there is a way to use the output from LFOs and envelopes in my arduino sketch to fade between waveforms it would make the whole thing so much simpler.

Once again thanks for all the help markT.
 
I was doing the crossfading before and it worked well, I was just looking really for a way to modulate the table position using LFOs and envelopes. I was hoping to get the shape input to work as table position, but if there is a way to use the output from LFOs and envelopes in my arduino sketch to fade between waveforms it would make the whole thing so much simpler.

Once again thanks for all the help markT.

In that case a custom AudioStream object to implement it is the way to go. You'd use an input stream to select wavetables
and interpolation sample-by-sample. Programming the audio library perhaps you should look at the tutorial, in particular:
https://www.pjrc.com/teensy/td_libs_AudioNewObjects.html
 
I have managed to modify the waveform object to work with wavetables - the only current problem is that the interpolation all uses floats, and the audio stream inputs are 16 bit ints.
Code:
	case WAVEFORM_ARBITRARY:
		if (!arbdata) {
			release(block);
			if (shapedata) release(shapedata);
			return;
		}
		// len = 256
		for (i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
			ph = phasedata[i];
			index = ph >> 24;
			index2 = index + 1;
			if (index2 >= 256) index2 = 0;

			//calculate table sample set 1.
			val1 = *(arbdata + index + (((int)(tablePos)) * 256));
			val3 = *(arbdata + index + (((int)(tablePos + 1)) * 256));
			//scale using table position
			val1 = (int)(val1 * (1 - (tablePos - (int)(tablePos))));
			val3 = (int)(val3 * (tablePos - (int)(tablePos)));
			//merge
			val1 = val1 + val3;

			//calculate table sample set 2.
			val2 = *(arbdata + index2 + (((int)(tablePos)) * 256));
			val4 = *(arbdata + index2 + (((int)(tablePos + 1)) * 256));
			//scale using table position
			val2 = (int)(val1 * (1 - (tablePos - (int)(tablePos))));
			val4 = (int)(val3 * (tablePos - (int)(tablePos)));
			//merge
			val2 = val2 + val4;

			scale = (ph >> 8) & 0xFFFF;
			val2 *= scale;
			val1 *= 0x10000 - scale;
			*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
		}
		break;

If anyone has any ideas about a way to do this using integers, it would be much appreciated!
 
If anyone has any ideas about a way to do this using integers, it would be much appreciated!


You can express the coefficients of each table integers.

example:

coef 1 for table 1 = float 1.3 = 1.3 * 1024
coef 2 for table 2 = float 0.7 = 0.7 * 1024

resul = ( sample_from_table_1 * coef1 + sample_from_table_2 * coef2 ) >> 10 ;

You can also build the result table outside the "update" because anyway the modulation from one wave to another would not be done in the audio domain, so the interpolation can be calculated outside the "update" ?
 
Status
Not open for further replies.
Back
Top