Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: Large wavetables using waveform object.

  1. #1

    Large wavetables using waveform object.

    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

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    459
    Quote Originally Posted by thedreiskre View Post
    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.

  3. #3
    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.

  4. #4
    Senior Member
    Join Date
    Jul 2020
    Posts
    459
    Quote Originally Posted by thedreiskre View Post
    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_...ewObjects.html

  5. #5
    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!

  6. #6
    Junior Member
    Join Date
    Feb 2018
    Location
    France
    Posts
    17
    Quote Originally Posted by thedreiskre View Post
    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" ?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •