summaryrefslogtreecommitdiffstats
path: root/WaveClass4PolyPlusLPF_BETA
diff options
context:
space:
mode:
Diffstat (limited to 'WaveClass4PolyPlusLPF_BETA')
-rw-r--r--WaveClass4PolyPlusLPF_BETA/ADSRslow.h307
-rw-r--r--WaveClass4PolyPlusLPF_BETA/Wave.h183
-rw-r--r--WaveClass4PolyPlusLPF_BETA/WaveClass4PolyPlusLPF_BETA.ino434
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
-}
-
-
-