Go Down

Topic: optimizing code: help avoiding modulus.. (Read 1 time) previous topic - next topic

tommyrosa

i tried that already, but it ended up consuming more cycles than just doing "conta % pitch" .... :(
things just had to be tricky...

just to let you guys know, i also found out that the reminder of any number divided by 2^n could be calculated as num & (2^n - 1), and so i changed the code to only give pitch prescalers which were powers of 2, but that had the side effect of providing very
inaccurate frequencies (it would yield 300 hz instead of 350 hz, which is really quite noticeable..)

another alternative i explored was considering A % B as A - B * (A/B)... i tried precomputing 1/B before and storing the value in another variable, say C... so technically i could do A - B*(A*C)......but the problem with this is that it always gave 0 as a result.. since 1/B would always give 0 in integer math...




DuaneB

Listening to the demonstration video -

http://www.youtube.com/watch?v=wJZVMu78T9g

It doesn't look like the most promising basis for a polyphonic synth project.

DDS is a lot less computationally expensive and sounds an awful lot better as well.

Duane B

rcarduino.blogspot.com

robtillaart


The code in reply #1 should work but all the variables used in the IRQ should be volatile.

However I would change the order of the statements a bit especially for the var n which is used as an index.
First test if it is out of range before using it.
Code: [Select]

void DAC_out()
{
  conta++;  //overflow should not be too much of a problem..in case change to unsigned long..
  if (conta >= pitch)
  {
    conta = 0;
    if (n >= steps) n=0;
    PORTD=out[n++];
  }
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dhenry

If pitch is a known constant, it can be made easier.

Otherwise, you can  use successive subtract; or division on a machine with hardware dividers / multipliers:

Code: [Select]

  if (conta - (conta / pitch) * pitch) {
    PORTD=...


Successive subtraction can be done line this
Code: [Select]

  while (conta >= pitch) conta -= pitch;
  if (conta==0) {
    PORTD=...


This will destroy conta so if you don't want that, use that code on a copy of conta.

robtillaart

Quote
If pitch is a known constant, it can be made easier.

in the first post of OP - pitch is set in set_freq() outside the Interrupt routine, so it is possibly not constant
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up