Skip to content
Snippets Groups Projects
Commit c9995c3f authored by David Huss's avatar David Huss :speech_balloon:
Browse files

Breakout Kick into class, add Snare

parent 93d59028
No related branches found
No related tags found
No related merge requests found
#include <hardware/pwm.h>
#include "Envelopes.h"
#include "Hardware.h"
#include "Kick.h"
#include "Snare.h"
// Hardware definitions
#define MODESWITCH_PIN_A 0
#define MODESWITCH_PIN_B 1
#define PUSHBUTTON_PIN 6
......@@ -7,40 +12,40 @@
#define FREQ_POT_PIN 27
#define INV_POT_PIN 28
#define CHORD_POT_PIN 29
#define DEBUG_MODE false
#define SAMPLES 512
// KICKDRUM SETTINGS
#define KICK_BASE_FREQ 0.15
#define KICK_FREQ_RANGE 2.0
#define KICK_BASE_FREQ 0.22
#define KICK_FREQ_RANGE 10.0
#define KICK_SIGH_DELAY_MS 300
#define KICK_SIGH_AMOUNT 0.02
#define KICK_SIGH_AMOUNT 0.04
#define KICK_SIGH_SPEED 0.0004
// SNAREDRUM SETTINGS
#define SNARE_BASE_FREQ 0.5
#define SNARE_FREQ_RANGE 40.0
#define SNARE_SIGH_DELAY_MS 100
#define SNARE_SIGH_AMOUNT 0.1
#define SNARE_SIGH_SPEED 0.0004
int wave[SAMPLES];
EnvelopeSimpleLinear kick_volume_envelope;
EnvelopeSimpleLog kick_pitch_envelope;
float pitch_sigh = 0.0;
// Switch
OnOffOnSwitch mode_switch(MODESWITCH_PIN_A, MODESWITCH_PIN_B);
Kick kick;
Snare snare;
double last_trigger = 0;
float pitch_sigh = 0.0;
bool gate_high, old_gate_high;//push sw
int freq_pot;
float osc_freq;
int chord_pot;
float volume_decay;
int inv_pot;
float pitch_sigh_amount = KICK_SIGH_AMOUNT;
float pitch_sigh_speed = KICK_SIGH_SPEED;
float sigh_incrementer = 0.0;
int voct_input;
float osc_progress = 0;
int slice_num = 0;
......@@ -49,17 +54,27 @@ void setup() {
Serial.begin(9600);
// Mode select switch is a On-Off-On switch with the outer pins connected
// to the pins 0 and 1.
pinMode(MODESWITCH_PIN_A, INPUT_PULLUP);
pinMode(MODESWITCH_PIN_B, INPUT_PULLUP);
mode_switch.setup();
// Push Button
pinMode(PUSHBUTTON_PIN, INPUT_PULLUP);//push sw
// delay(1000);
for (int i = 0; i < SAMPLES; i++) {
wave[i] = (sin(2 * M_PI * i / SAMPLES)) * 511;
// Serial.println(wave[i]);
}
kick.setup();
kick.base_frequency = KICK_BASE_FREQ;
kick.frequency_range = KICK_FREQ_RANGE;
kick.pitch_envelope_sigh.delay = KICK_SIGH_DELAY_MS;
kick.pitch_envelope_sigh.amount = KICK_SIGH_AMOUNT;
kick.pitch_envelope_sigh.speed = KICK_SIGH_SPEED;
snare.setup();
snare.base_frequency = SNARE_BASE_FREQ;
snare.frequency_range = SNARE_FREQ_RANGE;
snare.pitch_envelope_sigh.delay = SNARE_SIGH_DELAY_MS;
snare.pitch_envelope_sigh.amount = SNARE_SIGH_AMOUNT;
snare.pitch_envelope_sigh.speed = SNARE_SIGH_SPEED;
//-------------------PWM setting-------------------------------
gpio_set_function(2, GPIO_FUNC_PWM);// set GP2 function PWM
......@@ -84,53 +99,54 @@ void loop() {
chord_pot = map(analogRead(CHORD_POT_PIN), 0, 1023, 1023, 0);
inv_pot = map(analogRead(INV_POT_PIN), 0, 1023, 1023, 0);
voct_input = analogRead(VOCT_PIN);
// Serial.println(voct_input);
osc_freq = KICK_BASE_FREQ + freq_pot/1023.0*KICK_FREQ_RANGE;
// Read IO
mode_switch.read();
readGates();
// Update Modulation
if (mode_switch.mode == 0) {
kick.setFrequency(freq_pot/1023.0);
// Bigger decay values make the envelope shorter
kick_volume_envelope.setSpeed(0.000005 + (float)chord_pot/1023.0/3000.0);
kick_pitch_envelope.setSpeed(0.00001 + (float)inv_pot/1023.0/800.0);
kick.setVolumeDecay(0.000005 + (float)chord_pot/1023.0/3000.0);
kick.setPitchDecay(0.00001 + (float)inv_pot/1023.0/800.0);
// Increase the amount of the pitch envelope if the pitch decay is longer
kick_pitch_envelope.setAmount(2.0 + (1023.0-(float)inv_pot)/1023.0*8.5);
// kick_pitch_envelope.setAmount(0.0);
kick.setPitchAmount(2.0 + (1023.0-(float)inv_pot)/1023.0*8.5);
kick.update();
} else if (mode_switch.mode == 1) {
snare.setFrequency(freq_pot/1023.0);
// Bigger decay values make the envelope shorter
snare.setVolumeDecay(0.000005 + (float)chord_pot/1023.0/3000.0);
snare.setPitchDecay(0.00001 + (float)inv_pot/1023.0/800.0);
// Increase the amount of the pitch envelope if the pitch decay is longer
snare.setPitchAmount(2.0 + (1023.0-(float)inv_pot)/1023.0*8.5);
snare.update();
}
// -------------------push sw , play wave-------------------------------
readGates();
updateKickEnvelopes();
}
void updateKickEnvelopes() {
// Increment the pitch sigh (a slight rise in pitch after
// the initial pitch envelope)
if ((millis() - last_trigger) > KICK_SIGH_DELAY_MS) {
sigh_incrementer += pitch_sigh_speed;
if (sigh_incrementer < 3.1415) {
pitch_sigh = max(0.0, sin(sigh_incrementer));
} else {
pitch_sigh = 0.0;
}
// Serial.println("Min:0,Max:1023");
// Serial.println(kick.render());
}
kick_pitch_envelope.update();
kick_volume_envelope.update();
}
// Timer that pushes out the actual audio with a fixed frequency
// Code inside this block needs to be fast in order to meet the deadlines
void on_pwm_wrap() {
// Clear the PWM register
pwm_clear_irq(slice_num);
// Decrement the volume envelope
// Set the output to the actual level
pwm_set_chan_level(slice_num, PWM_CHAN_A, kick_volume_envelope.value*wave[(int)osc_progress]/2+511);
// Advance the oscillator and reset it if it reached the end
osc_progress += osc_freq + kick_pitch_envelope.value + pitch_sigh * pitch_sigh_amount;
if (osc_progress > SAMPLES) {
osc_progress = 0;
// Set the output to the actual calculated sample
if (mode_switch.mode == 0){
pwm_set_chan_level(slice_num, PWM_CHAN_A, kick.render());
kick.advanceOscillator();
} else if (mode_switch.mode == 1){
pwm_set_chan_level(slice_num, PWM_CHAN_A, snare.render());
snare.advanceOscillator();
} else if (mode_switch.mode == 2){
pwm_set_chan_level(slice_num, PWM_CHAN_A, 511);
// kick.advanceOscillator();
}
}
......@@ -149,19 +165,14 @@ void readGates() {
if (gate_high == 1) {
// Trigger only on first rising flank
if (old_gate_high == 0) {
// Reset the oscillator and the envelopes
osc_progress = 0;
last_trigger = millis();
resetEnvelopes();
// (Re-)Trigger the Kick
if (mode_switch.mode == 0){
kick.trigger();
} else if (mode_switch.mode == 1){
snare.trigger();
} else if (mode_switch.mode == 2){
// kick.trigger();
}
}
}
void resetEnvelopes() {
kick_volume_envelope.reset();
kick_pitch_envelope.reset();
pitch_sigh = 0.0;
sigh_incrementer = 0.0;
}
\ No newline at end of file
......@@ -66,38 +66,55 @@ void EnvelopeSimpleLog::setAmount(float amount) {
this->amount = amount;
}
// // ---- A simple logarithmic falling envelope -------
// class EnvelopeSigh {
// public:
// float counter = 0.0;
// float value;
// float speed = 0.001;
// float delay = 300;
// float amount = 1.0;
// void update();
// void reset();
// void setAmount(float speed);
// void setSpeed(float speed);
// void setDelay(float speed);
// };
// void EnvelopeSimpleLog::update() {
// this->counter -= this->speed;
// if (this->counter <= 0.0) {
// this->counter = 0.0;
// }
// this->value = max(0.0, (log10(0.005 + 1.0 - this->counter)*-1.0))/2.3 * this->amount;
// }
// void EnvelopeSimpleLog::reset() {
// this->counter = 1.0;
// this->value = 0.0;
// }
// void EnvelopeSimpleLog::setSpeed(float speed) {
// this->speed = speed;
// }
// void EnvelopeSimpleLog::setAmount(float amount) {
// this->amount = amount;
// }
\ No newline at end of file
// ---- A sigh envelope -------
class EnvelopeSigh {
public:
float counter = 0.0;
float value;
float speed = 0.001;
float delay = 300;
float amount = 1.0;
double last_trigger;
void update();
void reset();
void trigger();
void setAmount(float speed);
void setSpeed(float speed);
void setDelay(float speed);
};
void EnvelopeSigh::update() {
this->counter -= this->speed;
if (this->counter <= 0.0) {
this->counter = 0.0;
}
if ((millis() - this->last_trigger) > this->delay) {
this->counter += this->speed;
if (this->counter < 3.1415) {
this->value = max(0.0, sin(this->counter)) * this->amount;
} else {
this->value = 0.0;
}
}
}
void EnvelopeSigh::trigger() {
this->last_trigger = millis();
}
void EnvelopeSigh::reset() {
this->counter = 1.0;
this->value = 0.0;
}
void EnvelopeSigh::setSpeed(float speed) {
this->speed = speed;
}
void EnvelopeSigh::setAmount(float amount) {
this->amount = amount;
}
void EnvelopeSigh::setDelay(float delay) {
this->delay = delay;
}
\ No newline at end of file
class OnOffOnSwitch {
public:
OnOffOnSwitch(int leftpin, int rightpin) {
this->leftpin = leftpin;
this->rightpin = rightpin;
}
int leftpin;
int rightpin;
int mode;
void setup();
void read();
};
void OnOffOnSwitch::setup() {
pinMode(this->leftpin, INPUT_PULLUP);
pinMode(this->rightpin, INPUT_PULLUP);
}
// Reads the mode switch, a tri-state On-Off-On toggle switch
// Assign the resulting mode to the mode_selection variable
void OnOffOnSwitch::read() {
bool left = digitalRead(this->leftpin);
bool right = digitalRead(this->rightpin);
if (left && right) {
// Center
this->mode = 1;
} else if (!left && right) {
// Left
this->mode = 2;
} else if (left && !right) {
// Right
this->mode = 0;
}
}
\ No newline at end of file
#define SAMPLES 1048
class Kick {
public:
float frequency;
float base_frequency;
float frequency_range;
EnvelopeSimpleLinear volume_envelope;
EnvelopeSimpleLog pitch_envelope;
EnvelopeSigh pitch_envelope_sigh;
void setup();
void update();
void reset();
void trigger();
float render();
void advanceOscillator();
void setVolumeDecay(float speed);
void setPitchDecay(float speed);
void setPitchAmount(float amount);
void setFrequency(float frequency);
private:
int wavetable[SAMPLES];
float osc_progress = 0.0;
};
void Kick::setup() {
// Fill the wavetable with a sine-wave
for (int i = 0; i < SAMPLES; i++) {
this->wavetable[i] = (sin(2 * M_PI * i / SAMPLES)) * 511;
}
this->volume_envelope.amount = 1.0;
}
void Kick::update() {
this->volume_envelope.update();
this->pitch_envelope.update();
this->pitch_envelope_sigh.update();
}
void Kick::reset() {
this->volume_envelope.reset();
this->pitch_envelope.reset();
this->pitch_envelope_sigh.reset();
this->osc_progress = 0;
}
void Kick::trigger() {
this->reset();
this->pitch_envelope_sigh.trigger();
}
float Kick::render() {
return this->volume_envelope.value * this->wavetable[(int)this->osc_progress] / 2 + 511;
}
void Kick::advanceOscillator() {
this->osc_progress += this->frequency + this->pitch_envelope.value + this->pitch_envelope_sigh.value;
if (this->osc_progress > SAMPLES) {
this->osc_progress = 0;
}
}
void Kick::setVolumeDecay(float speed) {
this->volume_envelope.setSpeed(speed);
}
void Kick::setPitchDecay(float speed) {
this->pitch_envelope.setSpeed(speed);
}
void Kick::setPitchAmount(float amount) {
this->pitch_envelope.setAmount(amount);
}
void Kick::setFrequency(float frequency) {
this->frequency = this->base_frequency + frequency * this->frequency_range;
}
\ No newline at end of file
#define SAMPLES 1048
class Snare {
public:
float frequency;
float base_frequency;
float frequency_range;
EnvelopeSimpleLinear volume_envelope;
EnvelopeSimpleLog pitch_envelope;
EnvelopeSigh pitch_envelope_sigh;
void setup();
void update();
void reset();
void trigger();
float render();
void advanceOscillator();
void setVolumeDecay(float speed);
void setPitchDecay(float speed);
void setPitchAmount(float amount);
void setFrequency(float frequency);
private:
int sinetable[SAMPLES];
int noisetable[SAMPLES];
float osc_progress = 0.0;
};
void Snare::setup() {
// Fill the sinetable with a sine-wave
for (int i = 0; i < SAMPLES; i++) {
this->sinetable[i] = (sin(2 * M_PI * i / SAMPLES)) * 511;
}
for (int i = 0; i < SAMPLES; i++) {
this->noisetable[i] = random(0, 1023);
}
this->volume_envelope.amount = 1.0;
}
void Snare::update() {
this->volume_envelope.update();
this->pitch_envelope.update();
this->pitch_envelope_sigh.update();
}
void Snare::reset() {
this->volume_envelope.reset();
this->pitch_envelope.reset();
this->pitch_envelope_sigh.reset();
this->osc_progress = 0;
}
void Snare::trigger() {
this->reset();
this->pitch_envelope_sigh.trigger();
}
float Snare::render() {
return this->volume_envelope.value * (this->sinetable[(int)this->osc_progress] + this->pitch_envelope.value * noisetable[(int)this->osc_progress]) / 2 + 511;
}
void Snare::advanceOscillator() {
this->osc_progress += this->frequency + this->pitch_envelope.value + this->pitch_envelope_sigh.value;
if (this->osc_progress > SAMPLES) {
this->osc_progress = 0;
}
}
void Snare::setVolumeDecay(float speed) {
this->volume_envelope.setSpeed(speed);
}
void Snare::setPitchDecay(float speed) {
this->pitch_envelope.setSpeed(speed);
}
void Snare::setPitchAmount(float amount) {
this->pitch_envelope.setAmount(amount);
}
void Snare::setFrequency(float frequency) {
this->frequency = this->base_frequency + frequency * this->frequency_range;
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ int waveform_selection = 0;
int f0 = 35; // base osc frequency
int j = 0;
int select_mode = 0; // 0=chord without root , 1=chord with root,2=arpeggio
int mode_selection = 0; // 0=chord without root , 1=chord with root,2=arpeggio
int inversion = 0; // 0-7
int old_invAD = 0; // countermeasure of input ADC noise
int new_invAD = 0; // countermeasure of input ADC noise
......@@ -154,17 +154,17 @@ void on_pwm_wrap() {
}
}
if (select_mode != 2){
if ((chord_mode==2 || chord_mode==3 || chord_mode==4) && select_mode == 0) {
if (mode_selection != 2){
if ((chord_mode==2 || chord_mode==3 || chord_mode==4) && mode_selection == 0) {
pwm_set_chan_level(slice_num, PWM_CHAN_A, wavetable[(int)osc_progress[0]]/4+wavetable[(int)osc_progress[1]]/4+wavetable[(int)osc_progress[3]]/4+511);
} else if ((chord_mode == 2 ||chord_mode == 3 ||chord_mode == 4) && select_mode == 1) {
} else if ((chord_mode == 2 ||chord_mode == 3 ||chord_mode == 4) && mode_selection == 1) {
pwm_set_chan_level(slice_num, PWM_CHAN_A, wavetable[(int)osc_progress[0]]/4+wavetable[(int)osc_progress[1]]/4+wavetable[(int)osc_progress[2]]/4+wavetable[(int)osc_progress[4]]/4+511);
} else if ((chord_mode == 0 || chord_mode == 1|| chord_mode == 5) && select_mode == 0) {
} else if ((chord_mode == 0 || chord_mode == 1|| chord_mode == 5) && mode_selection == 0) {
pwm_set_chan_level(slice_num, PWM_CHAN_A, wavetable[(int)osc_progress[0]]/5+wavetable[(int)osc_progress[1]]/5+wavetable[(int)osc_progress[2]]/5+wavetable[(int)osc_progress[3]]/5+511);
} else if ((chord_mode == 0 || chord_mode == 1|| chord_mode == 5) && select_mode == 1) {
} else if ((chord_mode == 0 || chord_mode == 1|| chord_mode == 5) && mode_selection == 1) {
pwm_set_chan_level(slice_num, PWM_CHAN_A, wavetable[(int)osc_progress[0]]/5+wavetable[(int)osc_progress[1]]/5+wavetable[(int)osc_progress[2]]/5+wavetable[(int)osc_progress[3]]/5+wavetable[(int)osc_progress[4]]/5+511);
}
} else if (select_mode == 2){
} else if (mode_selection == 2){
pwm_set_chan_level(slice_num, PWM_CHAN_A, wavetable[(int)osc_progress[5]]/2+511);
}
}
......@@ -381,19 +381,19 @@ void loop() {
}
// Reads the mode switch, a tri-state On-Off-On toggle switch
// Assign the resulting mode to the select_mode variable
// Assign the resulting mode to the mode_selection variable
void readModeSwitch() {
bool left = digitalRead(MODESWITCH_PIN_A);
bool right = digitalRead(MODESWITCH_PIN_B);
if (left && right) {
// Chord with bass
select_mode = 1;
mode_selection = 1;
} else if (!left && right) {
// Arpreggio
select_mode = 2;
mode_selection = 2;
} else if (left && !right) {
// Chord without bass
select_mode = 0;
mode_selection = 0;
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment