This is a part of the Kinetiszer project.
lfo.c@1:8ae4ab73ca6a, 2014-10-28 (annotated)
- Committer:
- Clemo
- Date:
- Tue Oct 28 20:09:12 2014 +0000
- Revision:
- 1:8ae4ab73ca6a
- Parent:
- 0:cb80470434eb
First publication (untested)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Clemo | 0:cb80470434eb | 1 | /* |
Clemo | 0:cb80470434eb | 2 | Copyright 2013 Paul Soulsby www.soulsbysynths.com |
Clemo | 0:cb80470434eb | 3 | This file is part of Atmegatron. |
Clemo | 0:cb80470434eb | 4 | |
Clemo | 0:cb80470434eb | 5 | Atmegatron is free software: you can redistribute it and/or modify |
Clemo | 0:cb80470434eb | 6 | it under the terms of the GNU General Public License as published by |
Clemo | 0:cb80470434eb | 7 | the Free Software Foundation, either version 3 of the License, or |
Clemo | 0:cb80470434eb | 8 | (at your option) any later version. |
Clemo | 0:cb80470434eb | 9 | |
Clemo | 0:cb80470434eb | 10 | Atmegatron is distributed in the hope that it will be useful, |
Clemo | 0:cb80470434eb | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
Clemo | 0:cb80470434eb | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Clemo | 0:cb80470434eb | 13 | GNU General Public License for more details. |
Clemo | 0:cb80470434eb | 14 | |
Clemo | 0:cb80470434eb | 15 | You should have received a copy of the GNU General Public License |
Clemo | 0:cb80470434eb | 16 | along with Atmegatron. If not, see <http://www.gnu.org/licenses/>. |
Clemo | 0:cb80470434eb | 17 | */ |
Clemo | 0:cb80470434eb | 18 | |
Clemo | 0:cb80470434eb | 19 | //**********Bipolar LFO. 16 waveforms, each 64 samples long.*************** |
Clemo | 0:cb80470434eb | 20 | |
Clemo | 0:cb80470434eb | 21 | #include "atmegatron.h" |
Clemo | 0:cb80470434eb | 22 | |
Clemo | 0:cb80470434eb | 23 | //lfo waveforms store in PROGMEM |
Clemo | 0:cb80470434eb | 24 | const signed char lfo_store[16][LFO_LEN] = |
Clemo | 0:cb80470434eb | 25 | { |
Clemo | 0:cb80470434eb | 26 | {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 |
Clemo | 0:cb80470434eb | 27 | {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 |
Clemo | 0:cb80470434eb | 28 | {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 |
Clemo | 0:cb80470434eb | 29 | {-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 |
Clemo | 0:cb80470434eb | 30 | {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 |
Clemo | 0:cb80470434eb | 31 | {127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-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% |
Clemo | 0:cb80470434eb | 32 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-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% |
Clemo | 0:cb80470434eb | 33 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-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% |
Clemo | 0:cb80470434eb | 34 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,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% |
Clemo | 0:cb80470434eb | 35 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,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% |
Clemo | 0:cb80470434eb | 36 | {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 |
Clemo | 0:cb80470434eb | 37 | {127,127,127,127,127,127,127,127,127,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 |
Clemo | 0:cb80470434eb | 38 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-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 |
Clemo | 0:cb80470434eb | 39 | {127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,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 |
Clemo | 0:cb80470434eb | 40 | {-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 |
Clemo | 0:cb80470434eb | 41 | {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,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% |
Clemo | 0:cb80470434eb | 42 | }; |
Clemo | 0:cb80470434eb | 43 | unsigned long lfo_ticklen = 500; //ticks per LFO cycle. only used when MIDI clock not present. default = 500 ticks, therefore 1 cycle per beat |
Clemo | 0:cb80470434eb | 44 | 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 |
Clemo | 0:cb80470434eb | 45 | unsigned long lfo_starttick = 0; //tick lfo starts oscillating at |
Clemo | 0:cb80470434eb | 46 | unsigned long lfo_curtick = 0; //cur tick of lfo |
Clemo | 0:cb80470434eb | 47 | |
Clemo | 0:cb80470434eb | 48 | //lets and gets |
Clemo | 0:cb80470434eb | 49 | 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. |
Clemo | 0:cb80470434eb | 50 | byte lfo_curtable = 0; //current lfo waveform |
Clemo | 0:cb80470434eb | 51 | boolean lfo_invert = false; //lfo invert mode |
Clemo | 0:cb80470434eb | 52 | signed char lfo_level = 0; //lfo output (-127 - 127) |
Clemo | 0:cb80470434eb | 53 | |
Clemo | 0:cb80470434eb | 54 | //lets and gets |
Clemo | 0:cb80470434eb | 55 | //LFO speed. Stored as a lookup table of multipliers, not actual ticks |
Clemo | 0:cb80470434eb | 56 | void LFO_Let_Speed(unsigned int newspeed) |
Clemo | 0:cb80470434eb | 57 | { |
Clemo | 0:cb80470434eb | 58 | lfo_speed = newspeed; |
Clemo | 0:cb80470434eb | 59 | 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 |
Clemo | 0:cb80470434eb | 60 | if (lfo_ticklen<2){ |
Clemo | 0:cb80470434eb | 61 | lfo_ticklen = 2; //Speed must be 2 or great otherwise divide by 0 in LFO_calcval |
Clemo | 0:cb80470434eb | 62 | } |
Clemo | 0:cb80470434eb | 63 | lfo_clockticklen = ((unsigned long)lfo_speed+1) * 24 >> 13; //same as above, this time for when MIDI clock is present |
Clemo | 0:cb80470434eb | 64 | if (lfo_clockticklen<2){ |
Clemo | 0:cb80470434eb | 65 | lfo_clockticklen = 2; //Speed must be 2 or great otherwise divide by 0 in LFO_calcval |
Clemo | 0:cb80470434eb | 66 | } |
Clemo | 0:cb80470434eb | 67 | } |
Clemo | 0:cb80470434eb | 68 | unsigned int LFO_Get_Speed(void) |
Clemo | 0:cb80470434eb | 69 | { |
Clemo | 0:cb80470434eb | 70 | return lfo_speed; |
Clemo | 0:cb80470434eb | 71 | } |
Clemo | 0:cb80470434eb | 72 | //set and get lfo waveform |
Clemo | 0:cb80470434eb | 73 | void LFO_Let_Type(byte newtable) |
Clemo | 0:cb80470434eb | 74 | { |
Clemo | 0:cb80470434eb | 75 | lfo_curtable = newtable; |
Clemo | 0:cb80470434eb | 76 | } |
Clemo | 0:cb80470434eb | 77 | byte LFO_Get_Type(void) |
Clemo | 0:cb80470434eb | 78 | { |
Clemo | 0:cb80470434eb | 79 | return lfo_curtable; |
Clemo | 0:cb80470434eb | 80 | } |
Clemo | 0:cb80470434eb | 81 | //set and get invert mode |
Clemo | 0:cb80470434eb | 82 | void LFO_Let_Invert(boolean newinv) |
Clemo | 0:cb80470434eb | 83 | { |
Clemo | 0:cb80470434eb | 84 | lfo_invert = newinv; |
Clemo | 0:cb80470434eb | 85 | } |
Clemo | 0:cb80470434eb | 86 | boolean LFO_Get_Invert(void) |
Clemo | 0:cb80470434eb | 87 | { |
Clemo | 0:cb80470434eb | 88 | return lfo_invert; |
Clemo | 0:cb80470434eb | 89 | } |
Clemo | 0:cb80470434eb | 90 | //return current lfo level (-127 - 127) |
Clemo | 0:cb80470434eb | 91 | signed char LFO_Get_Level(void) |
Clemo | 0:cb80470434eb | 92 | { |
Clemo | 0:cb80470434eb | 93 | if (lfo_invert==true){ |
Clemo | 0:cb80470434eb | 94 | return -lfo_level; //invert output if invert mode on |
Clemo | 0:cb80470434eb | 95 | } |
Clemo | 0:cb80470434eb | 96 | else{ |
Clemo | 0:cb80470434eb | 97 | return lfo_level; |
Clemo | 0:cb80470434eb | 98 | } |
Clemo | 0:cb80470434eb | 99 | } |
Clemo | 0:cb80470434eb | 100 | |
Clemo | 0:cb80470434eb | 101 | //LFO meat |
Clemo | 0:cb80470434eb | 102 | //reset lfo start tick. lfo is reset when first key is pressed |
Clemo | 0:cb80470434eb | 103 | void LFO_Reset(void) |
Clemo | 0:cb80470434eb | 104 | { |
Clemo | 0:cb80470434eb | 105 | if (MIDI_Get_ClockPresent()==false){ |
Clemo | 0:cb80470434eb | 106 | lfo_starttick = master_tick; |
Clemo | 0:cb80470434eb | 107 | } |
Clemo | 0:cb80470434eb | 108 | } |
Clemo | 0:cb80470434eb | 109 | //calculate the current output of the lfo |
Clemo | 0:cb80470434eb | 110 | void LFO_CalcVal(void) |
Clemo | 0:cb80470434eb | 111 | { |
Clemo | 0:cb80470434eb | 112 | unsigned long pos; |
Clemo | 0:cb80470434eb | 113 | int index; |
Clemo | 0:cb80470434eb | 114 | //char lfoval; |
Clemo | 0:cb80470434eb | 115 | if (MIDI_Get_ClockPresent()==false){ //if midi clock not used: |
Clemo | 0:cb80470434eb | 116 | lfo_curtick = master_tick - lfo_starttick; //get ticks since lfo started |
Clemo | 0:cb80470434eb | 117 | pos = lfo_curtick % lfo_ticklen; //calculate position within cycle in ticks |
Clemo | 0:cb80470434eb | 118 | index = (pos * LFO_LEN) / lfo_ticklen; //convert to position within wavetable array |
Clemo | 0:cb80470434eb | 119 | } |
Clemo | 0:cb80470434eb | 120 | else{ |
Clemo | 0:cb80470434eb | 121 | pos = MIDI_Get_ClockTick() % lfo_clockticklen; //calculate position within cycle in clock ticks |
Clemo | 0:cb80470434eb | 122 | index = (pos * LFO_LEN) / lfo_clockticklen; //convert to position within wavetable array |
Clemo | 0:cb80470434eb | 123 | } |
Clemo | 0:cb80470434eb | 124 | lfo_level = lfo_store[lfo_curtable][index]; //set lfo level |
Clemo | 0:cb80470434eb | 125 | } |
Clemo | 0:cb80470434eb | 126 |