Using integer math instead of floating point?

Status
Not open for further replies.

thedreiskre

Active member
I'm using floating point math for interpolation through a wavetable, but it seems quite inefficient and requires converting ints to floats and vice versa.
Is there a way to convert my code to work using only integers?
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;

			tablePos = (abs(shapedata->data[i]) * 0.00003051757) * 3;
			// 3 is table length. (table length of 3 allows for table of 4 waves)
			//TODO add a set length function.



			switch (interpolationType)
			{
				case INTERPOLATION_SMOOTH:
					//sample 1
					val1 = *(arbdata + index + (((int)(tablePos)) * 256));
					val3 = *(arbdata + index + (((int)(tablePos + 1)) * 256));
					val1 = (int)(val1 * (1 - (tablePos - (int)(tablePos))));
					val3 = (int)(val3 * (tablePos - (int)(tablePos)));
					
					//sample 2
					val2 = *(arbdata + index2 + (((int)(tablePos)) * 256));
					val4 = *(arbdata + index2 + (((int)(tablePos + 1)) * 256));
					val2 = (int)(val2 * (1 - (tablePos - (int)(tablePos))));
					val4 = (int)(val4 * (tablePos - (int)(tablePos)));
					
					//merge
					val2 = val2 + val4;
					val1 = val1 + val3;

					break;
				case INTERPOLATION_STEP:
					val1 = *(arbdata + index + (((int)(tablePos + 0.01)) * 256));
					val2 = *(arbdata + index2 + (((int)(tablePos + 0.01)) * 256));
					//add 0.01 so that the top wave can be reached.
					break;
			}
			

			

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

Any help would be much appreciated.
 
Try scaling your numbers by some factor. Like 100 or 1000. Just make sure you don't overflow the maximum integer value.

This is an old trick called "fixed point math", for old microprocessors that did not have floating point. The original Forth language comes to mind.

Come to think of it, is your interpolated number going to end up as an integer in the end? Then just do it all in integer math.

Unless you have some other reason for it. For example, in my project I am using double precision floating point math. In the end I do not need all those digits, but there are some intermediate steps where I want to avoid truncation errors, and it is easier to make everything a double and worry about the conversion to int at the end.
 
I'm using floating point math for interpolation through a wavetable, but it seems quite inefficient and requires converting ints to floats and vice versa.

(Binary) fixed point is normally used for this, for instance fix10.22 would signify 10 integer bits and 22 fractional bits in a 32 bit integer.

Most languages don't have explicit support for fixed point, so you have to manage it yourself, keeping track of where the point
is in each variable, and scaling for multiply and divide suitable (by shifts).

So you might write a multiply for 10.22 fixed point thus:
Code:
int32_t fix10_22_mult (int32_t a, int32_t b)
{
  int64_t res = a ; // need 64 bit intermediate
  res *= b ;   // result before scaling, in fix20.44
  res += 1<<21 ;  // round to nearest semantics (optional)
  return (int32_t) (res >> 22) ; // scale back to fix10.22
}

Addition and subtraction are easy of course...
 
Yeah the interpolated number does end up as an integer. I just don't know where to really start converting it all into integer math, because the interpolation is modular but the multiplier for the sample position isn't modular. I was thinking if i made tablepos an int, i could maybe rshift it to get multipliers for the sample position... but i don't really know where to go from there :)
 
This looks interesting mark, I think i saw some of this in paul's code for waveformMod, it really looks like something useful to learn. I will look into this and also the arm special instructions (with the really long function names).
 
Last edited:
My advice: always test to make sure you have a speed problem before you used fixed point over floating point.
 
Status
Not open for further replies.
Back
Top