This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

lfo.c

Committer:
Clemo
Date:
2014-10-28
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb

File content as of revision 1:8ae4ab73ca6a:

/*
Copyright 2013 Paul Soulsby www.soulsbysynths.com
    This file is part of Atmegatron.

    Atmegatron is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Atmegatron is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Atmegatron.  If not, see <http://www.gnu.org/licenses/>.
*/

//**********Bipolar LFO.  16 waveforms, each 64 samples long.*************** 

#include "atmegatron.h"

//lfo waveforms store in PROGMEM
const signed char lfo_store[16][LFO_LEN] =
{
  {0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126,127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12,0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126,-127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12},  //sine
  {0,8,16,24,32,40,48,56,64,71,79,87,95,103,111,119,127,119,111,103,95,87,79,71,64,56,48,40,32,24,16,8,0,-8,-16,-24,-32,-40,-48,-56,-64,-71,-79,-87,-95,-103,-111,-119,-127,-119,-111,-103,-95,-87,-79,-71,-64,-56,-48,-40,-32,-24,-16,-8},                  //triangle
  {127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4,0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60,-64,-67,-71,-75,-79,-83,-87,-91,-95,-99,-103,-107,-111,-115,-119,-123},                  //saw down
  {-127,-127,-127,-127,-127,-126,-126,-126,-126,-126,-126,-125,-125,-125,-125,-124,-124,-124,-123,-123,-122,-122,-121,-121,-120,-119,-118,-118,-117,-116,-115,-113,-112,-111,-109,-107,-105,-103,-101,-99,-96,-93,-90,-87,-83,-79,-74,-69,-64,-58,-52,-45,-37,-29,-20,-11,0,12,24,38,53,69,87,107},  //Exponential ramp up
  {0,25,48,70,88,102,112,118,120,118,114,108,101,95,89,86,85,86,89,95,101,108,114,118,120,118,112,102,88,70,48,25,0,-25,-48,-70,-88,-102,-112,-118,-120,-118,-114,-108,-101,-95,-89,-86,-85,-86,-89,-95,-101,-108,-114,-118,-120,-118,-112,-102,-88,-70,-48,-25},      //3rd sine harmonics
  {127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},  //5%
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},              //25%
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},                              //50% 
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},                                              //75%
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127},                                                          //95%
  {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127},    //Ramp up and hold
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4},  //Hold and ramp down
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127},  //duh dugga
  {127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127},          //dugga duh
  {-104,-72,-14,91,-35,38,-20,-21,83,47,22,-73,-111,-104,-28,27,79,25,34,-112,-45,20,36,-30,-124,-74,-95,56,63,-91,94,78,-121,-27,49,-110,-25,24,-9,11,-80,65,-10,-56,-101,116,105,58,-67,-108,-127,95,-71,88,54,-2,83,109,-37,59,40,-77,84,-28},    //noise
  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127}    //DC offset                                                          //95%
};
unsigned long  lfo_ticklen = 500;          //ticks per LFO cycle.  only used when MIDI clock not present.  default = 500 ticks, therefore 1 cycle per beat
unsigned long  lfo_clockticklen = 24;      //clock ticks per LFO cylcle.  only used when MIDI clock present.  24 ticks per beat, therefore 1 cycle per beat  
unsigned long lfo_starttick = 0;           //tick lfo starts oscillating at
unsigned long lfo_curtick = 0;             //cur tick of lfo

//lets and gets
unsigned int lfo_speed = 8191;             //speed of lfo.  not actual ticks, just a reference in a lookup table that is then divided to equal actual ticks.
byte lfo_curtable = 0;                     //current lfo waveform
boolean lfo_invert = false;                //lfo invert mode
signed char lfo_level = 0;                        //lfo output (-127 - 127)

//lets and gets
//LFO speed.  Stored as a lookup table of multipliers, not actual ticks
void LFO_Let_Speed(unsigned int newspeed)
{
  lfo_speed = newspeed;
  lfo_ticklen = ((unsigned long)lfo_speed+1) * MASTER_BEATTICK >> 13;    //Calculate lfo tick length.  This method is a way of calculating ticks without using slow (and memory consuming) floating point maths.  e.g. 1 cycle per beat = 8192 * 500 >> 13 = 500 
  if (lfo_ticklen<2){
    lfo_ticklen = 2;                                                     //Speed must be 2 or great otherwise divide by 0 in LFO_calcval
  }
  lfo_clockticklen = ((unsigned long)lfo_speed+1) * 24 >> 13;            //same as above, this time for when MIDI clock is present
  if (lfo_clockticklen<2){
        lfo_clockticklen = 2;                                            //Speed must be 2 or great otherwise divide by 0 in LFO_calcval
  }
}
unsigned int LFO_Get_Speed(void)
{
  return lfo_speed;
}
//set and get lfo waveform
void LFO_Let_Type(byte newtable)
{
  lfo_curtable = newtable;
}
byte LFO_Get_Type(void)
{
  return lfo_curtable;
}
//set and get invert mode
void LFO_Let_Invert(boolean newinv)
{
  lfo_invert = newinv;
}
boolean LFO_Get_Invert(void)
{
  return lfo_invert;
}
//return current lfo level (-127 - 127)
signed char LFO_Get_Level(void)
{
  if (lfo_invert==true){
    return -lfo_level;      //invert output if invert mode on
  }
  else{
    return lfo_level;  
  }
}

//LFO meat
//reset lfo start tick.  lfo is reset when first key is pressed
void LFO_Reset(void)
{
  if (MIDI_Get_ClockPresent()==false){
    lfo_starttick = master_tick;
  }
}
//calculate the current output of the lfo
void LFO_CalcVal(void)
{
  unsigned long pos; 
  int index;
  //char lfoval;
  if (MIDI_Get_ClockPresent()==false){                                    //if midi clock not used:
    lfo_curtick = master_tick - lfo_starttick;                            //get ticks since lfo started
    pos = lfo_curtick % lfo_ticklen;                                      //calculate position within cycle in ticks
    index = (pos * LFO_LEN) / lfo_ticklen;                                //convert to position within wavetable array
  }
  else{
    pos = MIDI_Get_ClockTick() % lfo_clockticklen;                        //calculate position within cycle in clock ticks
    index = (pos * LFO_LEN) / lfo_clockticklen;                           //convert to position within wavetable array
  }
  lfo_level = lfo_store[lfo_curtable][index];      //set lfo level
}