diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2016-03-14 19:27:50 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2016-03-14 19:27:50 +0200 |
| commit | b791625011d2f1c6fa604a3ff67d7479fcffa7de (patch) | |
| tree | e35046626dcb22181f82f07d08df1288fb4552b1 /WaveClass4PolyPlusLPF_BETA | |
| parent | ca6cf59e549db308b305f1a7469536d37ff372e6 (diff) | |
Fork fakebitpolytechnic/cheapsynth
Diffstat (limited to 'WaveClass4PolyPlusLPF_BETA')
| -rw-r--r-- | WaveClass4PolyPlusLPF_BETA/ADSRslow.h | 307 | ||||
| -rw-r--r-- | WaveClass4PolyPlusLPF_BETA/Wave.h | 183 | ||||
| -rw-r--r-- | WaveClass4PolyPlusLPF_BETA/WaveClass4PolyPlusLPF_BETA.ino | 434 |
3 files changed, 0 insertions, 924 deletions
diff --git a/WaveClass4PolyPlusLPF_BETA/ADSRslow.h b/WaveClass4PolyPlusLPF_BETA/ADSRslow.h deleted file mode 100644 index 760d136..0000000 --- a/WaveClass4PolyPlusLPF_BETA/ADSRslow.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * ADSR.h - * - * Copyright 2012 Tim Barrass. - * - * This file is part of Mozzi. - * - * Mozzi 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. - * - * Mozzi 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 Mozzi. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef ADSR_H_ -#define ADSR_H_ - -#include "Arduino.h" -//#include <util/atomic.h> -#include "Line.h" -#include "mozzi_fixmath.h" - -/** A simple ADSR envelope generator. -@todo Test whether using the template parameter makes any difference to speed, -and rationalise which units which do and don't need them. -Template objects are messy when you try to use pointers to them, -you have to include the whole template shebang in the pointer handling. -*/ -template <unsigned int CONTROL_UPDATE_RATE> -class ADSR -{ -private: - - const unsigned int AUDIO_TICKS_PER_CONTROL; - - unsigned int phase_control_step_counter; - unsigned int phase_num_control_steps; - - enum {ATTACK,DECAY,SUSTAIN,RELEASE,IDLE}; - - - struct phase{ - byte phase_type; - unsigned int control_steps; - unsigned long audio_steps; - Q8n0 level; - }attack,decay,sustain,release,idle; - - phase * current_phase; - - // Linear audio rate transitions for envelope - Line <unsigned long> transition; - - inline - unsigned int convertMsecToControlSteps(unsigned int msec){ - return (uint) (((ulong)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift - } - - inline - void setPhase(phase * next_phase) { - phase_control_step_counter = 0; - phase_num_control_steps = next_phase->control_steps; - transition.set(Q8n0_to_Q16n16(next_phase->level),next_phase-> control_steps); - current_phase = next_phase; - } - - - - inline - void checkForAndSetNextPhase(phase * next_phase) { - if (++phase_control_step_counter >= phase_num_control_steps){ - setPhase(next_phase); - } - } - - - inline - void checkForAndSetIdle() { - if (++phase_control_step_counter >= phase_num_control_steps){ - transition.set(0,0,1); - current_phase = &idle; - } - } - - - -inline - void setTime(phase * p, unsigned int msec) - { - p->control_steps=convertMsecToControlSteps(msec); - p->audio_steps = (ulong) p->control_steps * AUDIO_TICKS_PER_CONTROL; - } - - -public: - - /** Constructor. - */ - ADSR():AUDIO_TICKS_PER_CONTROL(AUDIO_RATE/CONTROL_UPDATE_RATE) - { - attack.phase_type = ATTACK; - decay.phase_type = DECAY; - sustain.phase_type = SUSTAIN; - release.phase_type = RELEASE; - idle.phase_type = IDLE; - release.level = 0; - } - - -/** Updates the internal controls of the ADSR. - Call this in updateControl(). - */ - void update(){ // control rate - - switch(current_phase->phase_type) { - - case ATTACK: - checkForAndSetNextPhase(&decay); - break; - - case DECAY: - checkForAndSetNextPhase(&sustain); - break; - - case SUSTAIN: - checkForAndSetNextPhase(&release); - break; - - case RELEASE: - checkForAndSetIdle(); - break; - - } - } - - /** Advances one audio step along the ADSR and returns the level. - Call this in updateAudio(). - @return the next value, as an unsigned int. - */ - inline - unsigned int next() - { - return Q16n16_to_Q16n0(transition.next()); - } - - - - /** Start the attack phase of the ADSR. THis will restart the ADSR no matter what phase it is up to. - */ - inline - void noteOn(){ - setPhase(&attack); - } - - - - /** Start the release phase of the ADSR. - @todo fix release for rate rather than steps (time), so it releases at the same rate whatever the current level. - */ - inline - void noteOff(){ - setPhase(&release); - } - - - - - - /** Set the attack level of the ADSR. - @param value the attack level. - */ - inline - void setAttackLevel(byte value) - { - attack.level=value; - } - - - - /** Set the decay level of the ADSR. - @param value the decay level. - */ - inline - void setDecayLevel(byte value) - { - decay.level=value; - } - - - /** Set the sustain level of the ADSR. - @param value the sustain level. Usually the same as the decay level, - for a steady sustained note. - */ - inline - void setSustainLevel(byte value) - { - sustain.level=value; - } - - /** Set the release level of the ADSR. Normally you'd make this 0, - but you have the option of some other value. - @param value the release level (normally 0). - */ - inline - void setReleaseLevel(byte value) - { - release.level=value; - } - - - - /** Set the attack and decay levels of the ADSR. This assumes a conventional - ADSR where the sustain continues at the same level as the decay, till the release ramps to 0. - @param attack the new attack level. - @param value the new sustain level. - */ - inline - void setADLevels(byte attack, byte decay) - { - setAttackLevel(attack); - setDecayLevel(decay); - setSustainLevel(decay); - setReleaseLevel(0); - } - - - - - - - - /** Set the attack time of the ADSR in milliseconds. - The actual time taken will be resolved within the resolution of CONTROL_RATE. - @param value the unsigned int attack time in milliseconds. - */ - inline - void setAttackTime(unsigned int msec) - { - setTime(&attack, msec); - } - - - /** Set the decay time of the ADSR in milliseconds. - The actual time taken will be resolved within the resolution of CONTROL_RATE. - @param value the unsigned int decay time in milliseconds. - */ - inline - void setDecayTime(unsigned int msec) - { - setTime(&decay, msec); - } - - - /** Set the sustain time of the ADSR in milliseconds. - The actual time taken will be resolved within the resolution of CONTROL_RATE. - The sustain phase will finish if the ADSR recieves a noteOff(). - @param value the unsigned int sustain time in milliseconds. - */ - inline - void setSustainTime(unsigned int msec) - { - setTime(&sustain, msec); - } - - - - /** Set the release time of the ADSR in milliseconds. - The actual time taken will be resolved within the resolution of CONTROL_RATE. - @param value the unsigned int release time in milliseconds. - */ - inline - void setReleaseTime(unsigned int msec) - { - setTime(&release, msec); - } - - - - /** Set the attack, decay and release times of the ADSR in milliseconds. - The actual times will be resolved within the resolution of CONTROL_RATE. - @param attack_ms the new attack time in milliseconds. - @param decay_ms the new decay time in milliseconds. - @param decay_ms the new sustain time in milliseconds. - @param release_ms the new release time in milliseconds. - */ - inline - void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms) - { - setAttackTime(attack_ms); - setDecayTime(decay_ms); - setSustainTime(sustain_ms); - setReleaseTime(release_ms); - } - - -}; - -#endif /* ADSR_H_ */ - diff --git a/WaveClass4PolyPlusLPF_BETA/Wave.h b/WaveClass4PolyPlusLPF_BETA/Wave.h deleted file mode 100644 index a9afd72..0000000 --- a/WaveClass4PolyPlusLPF_BETA/Wave.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Wave.h - * - * Simon Green 2013. - * - * Based on Mozzi "Oscil.h" - */ - -#ifndef WAVE_H_ -#define WAVE_H_ - -#include "Arduino.h" -#include "mozzi_fixmath.h" -#include <util/atomic.h> - -// fractional bits for oscillator index precision -#define OSCIL_F_BITS 16 -#define OSCIL_F_BITS_AS_MULTIPLIER 65536 -#define NUM_TABLE_CELLS 256 -#define ADJUST_FOR_NUM_TABLE_CELLS 8 -#define UPDATE_RATE AUDIO_RATE - -/** Generate waveform -*/ - -enum WaveType { WAVE_SAW=0, WAVE_TRI, WAVE_RECT, WAVE_NOISE }; - -class Wave -{ -public: - /** Constructor. "Wave mywave;" makes a Wave oscillator - */ - Wave () { - phase_fractional = 0; - phase_increment_fractional = 0; - wavetype = WAVE_SAW; - noise = 0xACE1; - pulse_width = 128; - } - - /** Increments one step along the phase. - @return the next value. - */ - inline - char next() - { - incrementPhase(); - - char w; - //ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - int n = (phase_fractional >> OSCIL_F_BITS) & (NUM_TABLE_CELLS-1); - switch(wavetype) { - case WAVE_SAW: - w = n - 128; - break; - case WAVE_TRI: - if (n & 0x80) // >= 128 - w = ((n^0xFF)<<1)-128; - else - w = (n<<1)-128; - break; - case WAVE_RECT: - if (n > pulse_width) - w = 127; - else - w = -127; - break; - case WAVE_NOISE: - noise = (noise >> 1) ^ (-(noise & 1) & 0xB400u); - w = noise>>8; - break; - } - } - return w; - } - - /** Set the wave type - */ - inline - void setType(WaveType x) - { - wavetype = x; - } - - WaveType getType() { return wavetype; } - - /** Set the pulse width for rectangle wave - */ - inline - void setPulseWidth(unsigned char x) - { - pulse_width = x; - } - - /** Set the oscillator frequency with an unsigned int. This is faster than using a - float, so it's useful when processor time is tight, but it can be tricky with - low and high frequencies, depending on the size of the wavetable being used. If - you're not getting the results you expect, try explicitly using a float, or try - setFreq_Q24n8() or or setFreq_Q16n16(). - @param frequency to play the wave table. - */ - inline - void setFreq (unsigned int frequency) { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - phase_increment_fractional = ((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)*frequency)/UPDATE_RATE) << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS); - } - } - - - /** Set the oscillator frequency with a float. Using a float is the most reliable - way to set frequencies, -Might- be slower than using an int but you need either - this, setFreq_Q24n8() or setFreq_Q16n16() for fractional frequencies. - @param frequency to play the wave table. - */ - inline - void setFreq(float frequency) - { // 1 us - using float doesn't seem to incur measurable overhead with the oscilloscope - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - phase_increment_fractional = (unsigned long)((((float)NUM_TABLE_CELLS * frequency)/UPDATE_RATE) * OSCIL_F_BITS_AS_MULTIPLIER); - } - } - - - /** Set the frequency using Q24n8 fixed-point number format. - This might be faster than the float version for setting low frequencies such as - 1.5 Hz, or other values which may not work well with your table size. A Q24n8 - representation of 1.5 is 384 (ie. 1.5 * 256). Can't be used with UPDATE_RATE - less than 64 Hz. - @param frequency in Q24n8 fixed-point number format. - */ - inline - void setFreq_Q24n8(Q24n8 frequency) - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - //phase_increment_fractional = (frequency* (NUM_TABLE_CELLS>>3)/(UPDATE_RATE>>6)) << (F_BITS-(8-3+6)); - phase_increment_fractional = (((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)>>3)*frequency)/(UPDATE_RATE>>6)) - << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS - (8-3+6)); - } - } - - - /** Set the frequency using Q16n16 fixed-point number format. This is useful in - combination with Q16n16_mtof(), a fast alternative to mtof(), using Q16n16 - fixed-point format instead of floats. Note: this should work OK with tables 2048 cells or smaller and - frequencies up to 4096 Hz. Can't be used with UPDATE_RATE less than 64 Hz. - @param frequency in Q16n16 fixed-point number format. - */ - inline - void setFreq_Q16n16(Q16n16 frequency) - { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - //phase_increment_fractional = ((frequency * (NUM_TABLE_CELLS>>7))/(UPDATE_RATE>>6)) << (F_BITS-16+1); - phase_increment_fractional = (((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)>>7)*frequency)/(UPDATE_RATE>>6)) - << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS - 16 + 1); - - } - } - -private: - /** Increments the phase of the oscillator without returning a sample. - */ - inline - void incrementPhase() - { - //phase_fractional += (phase_increment_fractional | 1); // odd phase incr, attempt to reduce frequency spurs in output - phase_fractional += phase_increment_fractional; - } - - unsigned long phase_fractional; - volatile unsigned long phase_increment_fractional; - - unsigned char pulse_width; - uint16_t noise; - - WaveType wavetype; -}; - -#endif /* WAVE_H_ */ diff --git a/WaveClass4PolyPlusLPF_BETA/WaveClass4PolyPlusLPF_BETA.ino b/WaveClass4PolyPlusLPF_BETA/WaveClass4PolyPlusLPF_BETA.ino deleted file mode 100644 index 8469753..0000000 --- a/WaveClass4PolyPlusLPF_BETA/WaveClass4PolyPlusLPF_BETA.ino +++ /dev/null @@ -1,434 +0,0 @@ - -/* Example of a sound being triggered by MIDI input. - * - * Demonstrates playing notes with Mozzi in response to MIDI input, - * using the standard Arduino MIDI library: - * http://playground.arduino.cc/Main/MIDILibrary - * - * Mozzi help/discussion/announcements: - * https://groups.google.com/forum/#!forum/mozzi-users - * - * Tim Barrass 2013. - * This example code is in the public domain. - * - * sgreen - modified to use standard Arduino midi library, added saw wave, lowpass filter - * Audio output from pin 9 (pwm) - * Midi plug pin 2 (centre) to Arduino gnd, pin 5 to RX (0) - * http://www.philrees.co.uk/midiplug.htm - * Now with drums! (still has all this code in there, commented out : ) - -S Green: -mod controller/ribbon is low pass filter cut-off -big button switches between tri/rectangle/noise/saw -(noise is at constant frequency) - -NB think mostly fixed, but may still be possible to crash filter with loud sounds, hit reset! - - */ - - -#include <MIDI.h> -#include <MozziGuts.h> -#include <Oscil.h> // oscillator template -#include <Line.h> // for envelope -#include <Sample.h> -#include <mozzi_utils.h> -#include <mozzi_analog.h> - -#include <tables/sin2048_int8.h> // sine table for oscillator -//#include <tables/saw2048_int8.h> -//#include <tables/triangle2048_int8.h> - -#include <mozzi_midi.h> -#include <ADSRslow.h> -#include <fixedMath.h> -#include <LowPassFilter.h> -#include "Wave.h" -#include <WaveShaper.h> -#include <tables/waveshape_compress_512_to_488_int16.h> - -#define MAX_NOTES 4 -//Dave G: now seems to do 4 note polyphony without clicking (higher notes are a bit grainy) -int threshold=255/MAX_NOTES; - -#define DRUM_SAMPLES 0 - -/* -#if DRUM_SAMPLES -#include "kick909.h" -#include "snare909.h" -#include "hihatc909.h" -#include "hihato909.h" -#endif -*/ - -// use #define for CONTROL_RATE, not a constant -#define CONTROL_RATE 128 // powers of 2 please - -#define ENABLE_MIDI 1 -#define DEBUG 0 -#define BPM 120 -#define STEPS_PER_BEAT 4 - -unsigned long stepCounter = 0; -unsigned long ticksPerStep = (60*CONTROL_RATE) / (BPM*STEPS_PER_BEAT); - -// audio sinewave oscillator -//Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> osc(SIN2048_DATA); -//Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> osc(SAW2048_DATA); -//Oscil <TRIANGLE2048_NUM_CELLS, AUDIO_RATE> osc(TRIANGLE2048_DATA); -//Wave myosc; -//Wave lfo; -Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> lfo(SIN2048_DATA); -WaveShaper <int> aCompress(WAVESHAPE_COMPRESS_512_TO_488_DATA); // to compress instead of dividing by 2 after adding signals - -struct Channel { - Wave osc; - //Oscil <TRIANGLE2048_NUM_CELLS, AUDIO_RATE> osc; - ADSR <CONTROL_RATE> env; - byte note; - byte gain; -}; -Channel chan[MAX_NOTES]; -byte currentChan = 0; - -// envelope generator -//ADSR <CONTROL_RATE> envelope; -LowPassFilter lpf; -int crushCtrl = 0; -int gain = 32; -float octave = 1.0f; - -boolean enableDrums = false; - -int step = 0; -int waveType = 1; - -int button0_old = 0; -int button1_old = 0; - -#if DRUM_SAMPLES -// drums -Sample <kick909_NUM_CELLS, AUDIO_RATE> kickSamp(kick909_DATA); -Sample <snare909_NUM_CELLS, AUDIO_RATE> snareSamp(snare909_DATA); -Sample <hihatc909_NUM_CELLS, AUDIO_RATE> hihatcSamp(hihatc909_DATA); -Sample <hihato_NUM_CELLS, AUDIO_RATE> hihatoSamp(hihato_DATA); -#endif - -byte pattern[4][16] = { - //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 hhc - 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, // 1 hho - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // 2 s - 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 // 3 k -}; - -// pin defines -#define LED 13 // to see if MIDI is being recieved -#define BUTTON0_PIN 2 -#define BUTTON1_PIN 3 - -// forward declarations -void HandleNoteOn(byte channel, byte note, byte velocity); -void HandleNoteOff(byte channel, byte note, byte velocity); -void HandleControlChange (byte channel, byte number, byte value); -void HandlePitchBend (byte channel, int bend); - -void setup() { - // init IO pins - pinMode(LED, OUTPUT); - -#if 0 - pinMode(BUTTON0_PIN, INPUT); - digitalWrite(BUTTON0_PIN, HIGH); // turn on pull-up resistor - - pinMode(BUTTON1_PIN, INPUT); - digitalWrite(BUTTON1_PIN, HIGH); // turn on pull-up resistor -#endif - -#if DEBUG - Serial.begin(57600); // for debugging -#endif - -#if ENABLE_MIDI - // Initiate MIDI communications, listen to all channels - MIDI.begin(MIDI_CHANNEL_OMNI); - - // Connect the HandleNoteOn function to the library, so it is called upon reception of a NoteOn. - MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function - MIDI.setHandleNoteOff(HandleNoteOff); // Put only the name of the function - MIDI.setHandleControlChange(HandleControlChange); - MIDI.setHandlePitchBend(HandlePitchBend); - MIDI.setHandleContinue(HandleContinue); - MIDI.setHandleStop(HandleStop); -#endif - -#if 0 - //osc.setFreq(440u); // default frequency - //myosc.setFreq(440.0f); - myosc.setFreq(440.0f*4.0f); - myosc.setPulseWidth(32); - - envelope.setADLevels(255, 200); - envelope.setTimes(50, 200, 65535, 200); -#endif - - for(int i=0; i<MAX_NOTES; i++) - { - chan[i].osc.setType(WAVE_TRI); - //chan[i].osc.setTable(TRIANGLE2048_DATA); - chan[i].osc.setPulseWidth(16); - chan[i].env.setADLevels(128, 100); - chan[i].env.setTimes(100, 200, 65535, 200); - } - - //lfo.setType(WAVE_TRI); - lfo.setFreq(10.0f); - - lpf.setResonance(128); - lpf.setCutoffFreq(255); - -#if DRUM_SAMPLES - kickSamp.setFreq((float) kick909_SAMPLERATE / (float) kick909_NUM_CELLS); - snareSamp.setFreq((float) snare909_SAMPLERATE / (float) snare909_NUM_CELLS); - hihatcSamp.setFreq((float) hihatc909_SAMPLERATE / (float) hihatc909_NUM_CELLS); - hihatoSamp.setFreq((float) hihato_SAMPLERATE / (float) hihato_NUM_CELLS); - //snareSamp.start(); -#endif - - //setupFastAnalogRead(); // optional - adcEnableInterrupt(); // for analog reads - - startMozzi(CONTROL_RATE); -} - -void HandleNoteOn(byte channel, byte note, byte velocity) { - //osc.setFreq(mtof(note)); // simple but less accurate frequency - //osc.setFreq_Q16n16(Q16n16_mtof(Q8n0_to_Q16n16(note))); // accurate frequency - //myosc.setFreq(mtof(note)); // accurate frequency - //envelope.noteOn(); - - // start note on next channel - NB no "note priority" at this stage - chan[currentChan].note = note; - chan[currentChan].osc.setFreq( mtof(note) ); // accurate frequency - chan[currentChan].env.noteOn(); - currentChan = (currentChan + 1) % MAX_NOTES; // just wraps around for now - - digitalWrite(LED,HIGH); -} - -void HandleNoteOff(byte channel, byte note, byte velocity) { - //envelope.noteOff(); - - // find which channel was playing this note - for(int i=0; i<MAX_NOTES; i++) { - if (chan[i].note == note) { - // kill it - chan[i].env.noteOff(); - } - } - - digitalWrite(LED,LOW); -} - -void HandleControlChange (byte channel, byte number, byte value) -{ - // http://www.indiana.edu/~emusic/cntrlnumb.html - switch(number) { - case 1: // modulation wheel - //gain = value*2; - lpf.setCutoffFreq( int(value*1.5f) ); // control messages are in [0, 127] range - break; -/* - case 105: - lpf.setCutoffFreq(value*2); // control messages are in [0, 127] range - break; -*/ - case 106: - //lpf.setResonance(value*2); - crushCtrl = value; - break; - } -} - -// pitchbend = control strip + button on Keytar -void HandlePitchBend (byte channel, int bend) -{ - //bend value from +/-8192 - //lfo.setFreq((unsigned int) (bend+8192)>>7); - for(int i=0; i<MAX_NOTES; i++) { - chan[i].osc.setPulseWidth((bend+8192) >> 8); - } - -} - -void HandleStop () { //this is the Back button on the Xbox keyboard -// octave *= 2.0f; -// if (octave > 16.0f) octave = 1.0f; -//Dave G: no longer used : ) -} - -void HandleContinue () { // the big round button on all keytars - - // change wave - waveType = (waveType + 1) & 3; - - for(int i=0; i<MAX_NOTES; i++) - { -#if 0 - switch(waveType) { - case 0: - chan[i].osc.setTable(TRIANGLE2048_DATA); - break; - case 1: - chan[i].osc.setTable(SAW2048_DATA); - break; - case 2: - chan[i].osc.setTable(SIN2048_DATA); - break; - } -#else - for(int i=0; i<MAX_NOTES; i++) - { - chan[i].osc.setType((WaveType) waveType); - } -#endif - } -} - -void updateControl(){ -#if ENABLE_MIDI - MIDI.read(); -#endif - - //envelope.update(); - - // update playing envelopes - for(int i=0; i<MAX_NOTES; i++) { - chan[i].env.update(); - chan[i].gain=chan[i].env.next(); - if (chan[i].gain>threshold) {chan[i].gain=threshold;} - // threshold=255/MAX_NOTES, genuinely not sure if this is best approach but stops crashes :) - } - -#if 0 - // push buttons - int button0 = !digitalRead(BUTTON0_PIN); // active low - int button1 = !digitalRead(BUTTON1_PIN); - - /* - if (button0) { - // trigger - //envelope.noteOn(); - //lpf.reset(); - digitalWrite(LED, HIGH); - } else { - digitalWrite(LED, LOW); - } - */ - - if (button0 && !button0_old) { - lfo.setType((WaveType) ((((int) lfo.getType()) + 1) % 3)); - } - button0_old = button0; - - if (button1 & !button1_old) { - waveType = (waveType + 1) & 3; - //myosc.setType((WaveType) waveType); - for(int i=0; i<MAX_NOTES; i++) - { - chan[i].osc.setType((WaveType) waveType); - } - } - button1_old = button1; -#endif - -#if DRUM_SAMPLES - if (enableDrums) { - // drums - stepCounter++; - if (stepCounter > ticksPerStep) { - step = (step+1) & 0xf; - stepCounter = 0; - if (pattern[0][step]) hihatcSamp.start(); - if (pattern[1][step]) hihatoSamp.start(); - if (pattern[2][step]) snareSamp.start(); - if (pattern[3][step]) kickSamp.start(); - } - } -#endif - -#if 0 - // knobs - int knob0 = adcGetResult(0); // [0, 1023] - int knob1 = adcGetResult(1); - //lpf.setCutoffFreq(knob0>>2); - //lpf.setResonance(knob1>>2); - - //crushCtrl = knob1>>7; - lfo.setFreq((float) knob0); - //myosc.setFreq((float) knob1); - //myosc.setFreq((unsigned int) knob0*20); - //myosc.setPulseWidth((unsigned char) (knob1>>2)); - - // start the next read cycle in the background - adcReadAllChannels(); -#endif - -#if DEBUG - Serial.println(knob0); -#endif -} - -// strip the low bits off! -int bitCrush(int x, int a) -{ - return (x>>a)<<a; -} - -int updateAudio() -{ - //int x = (int) (envelope.next() * osc.next())>>8; - //int x = (int) (envelope.next() * myosc.next())>>8; - //int x = (int) (envelope.next() * (lfo.next() * myosc.next())>>8)>>8; - //int x = (int) lfo.next(); - //int x = (int) (lfo.next() * myosc.next())>>8; - //int x = (int) (envelope.next() * lpf.next(myosc.next()))>>8; - //int x = (envelope.next() * lpf.next(osc.next()))>>8; - //x = bitCrush(x, crushCtrl>>4); - //x = bitCrush(x, crushCtrl); - //x = (x * crushCtrl)>>4; // simple gain - //x = x>>2; - //x = lpf.next(x); - - // sum up channels - int x = 0; - for(int i=0; i<MAX_NOTES; i++) { - x += (int) (chan[i].gain * chan[i].osc.next())>>8; - } -//Dave G: helps crash less if goes through some sort of waveshaper here? - x = aCompress.next(256u + x); - - //x = (x*gain)>>8; - //x = (x * lfo.next())>>8; - x = lpf.next(x); - -#if DRUM_SAMPLES - if (enableDrums) { - // drums please! - int drums = kickSamp.next() + snareSamp.next() + hihatcSamp.next() + hihatoSamp.next(); - //drums = (drums>>4)<<4; - x += drums*2; - } -#endif - - return x; -} - - -void loop() { - audioHook(); // required here -} - - - |
