Added basic LFO

This commit is contained in:
Christian Colglazier 2021-11-06 16:48:17 -04:00
parent 175a836715
commit b834f3168a
10 changed files with 229 additions and 31 deletions

View File

@ -0,0 +1,108 @@
#include "lfo_droplet.h"
void LFO::Init(DaisyPatch* m_patch,
float samplerate,
AnalogControl freqKnob,
AnalogControl ampKnob) {
patch = m_patch;
osc.Init(samplerate);
osc.SetAmp(1);
wave = 0;
freqCtrl.Init(freqKnob, 0.1f, 35.0f, Parameter::LOGARITHMIC);
ampCtrl.Init(ampKnob, 0.0f, 1.0f, Parameter::LINEAR);
}
void LFO::Process(DacHandle::Channel chn) {
osc.SetFreq(freqCtrl.Process());
osc.SetWaveform(wave);
patch->seed.dac.WriteValue(
chn,
uint16_t((osc.Process() + 1.f) *
.5f * ampCtrl.Process() * 4095.f));
}
void LFO::UpdateWave(int change) {
wave = (MAX_WAVE + wave + change) % MAX_WAVE;
}
uint8_t LFO::GetWave() {
return wave;
}
LFODroplet::LFODroplet(DaisyPatch* m_patch,
DropletState m_state,
float sample_rate) :
Droplet(m_patch,
m_state) {
switch (GetState()) {
default:
case DropletState::kFull:
lfo[0].Init(Patch(),
sample_rate,
Patch()->controls[Patch()->CTRL_1],
Patch()->controls[Patch()->CTRL_2]);
lfo[1].Init(Patch(),
sample_rate,
Patch()->controls[Patch()->CTRL_3],
Patch()->controls[Patch()->CTRL_4]);
break;
case DropletState::kLeft:
lfo[0].Init(Patch(),
sample_rate,
Patch()->controls[Patch()->CTRL_1],
Patch()->controls[Patch()->CTRL_2]);
break;
case DropletState::kRight:
lfo[0].Init(Patch(),
sample_rate,
Patch()->controls[Patch()->CTRL_3],
Patch()->controls[Patch()->CTRL_4]);
break;
}
}
LFODroplet::~LFODroplet() {}
void LFODroplet::Control() {
Patch()->ProcessAnalogControls();
Patch()->encoder.Debounce();
lfo[0].UpdateWave(Patch()->encoder.Increment());
if (GetState() == DropletState::kFull) {
lfo[1].UpdateWave(Patch()->encoder.Increment());
}
}
void LFODroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) {
Patch()->ProcessAnalogControls();
for(size_t i = 0; i < size; i++) {
if (GetState() == DropletState::kRight) {
lfo[0].Process(DacHandle::Channel::TWO);
} else {
lfo[0].Process(DacHandle::Channel::ONE);
}
if (GetState() == DropletState::kFull) {
lfo[1].Process(DacHandle::Channel::TWO);
}
}
}
void LFODroplet::Draw() {
if (GetState() == DropletState::kFull) {
WriteCenteredString(Patch(),
(GetScreenMax()-GetScreenMin())/2,
54,
Font_6x8,
WaveToString(lfo[0].GetWave()));
} else {
WriteDoubleCentered(Patch(),
GetScreenMin() +
(GetScreenMax()-GetScreenMin())/2,
54,
GetScreenMax()-GetScreenMin(),
Font_6x8,
WaveToString(lfo[0].GetWave()));
}
DrawName("LFO");
}

View File

@ -0,0 +1,82 @@
#pragma once
#ifndef CASCADE_DROPLETS_LFO_DROPLET_H_
#define CASCADE_DROPLETS_LFO_DROPLET_H_
#include "daisysp.h"
#include "daisy_patch.h"
#include "droplet.h"
#include "../util.h"
using namespace daisy;
using namespace daisysp;
#define MAX_WAVE Oscillator::WAVE_POLYBLEP_TRI
class LFO {
private:
Oscillator osc;
Parameter freqCtrl;
Parameter ampCtrl;
float amp;
float freq;
uint8_t wave;
float value;
DaisyPatch* patch;
public:
void Init(DaisyPatch* m_patch,
float samplerate,
AnalogControl freqKnob,
AnalogControl ampKnob);
void Process(DacHandle::Channel chn);
void UpdateWave(int change);
uint8_t GetWave();
};
class LFODroplet: public Droplet {
private:
LFO lfo[2];
public:
/*
* Constructor for a LFO droplet.
*
* @param m_patch pointer to patch
* @param m_state droplet position
*/
LFODroplet(DaisyPatch* m_patch,
DropletState m_state,
float sample_rate);
/*
* Destructor for vco droplet.
*/
~LFODroplet();
/*
* Processes user controls and inputs.
*/
void Control();
/*
* Processes audio input and outputs.
*
* @param in the audio inputs for the patch
* @param out the audio outputs for the patch
* @param size the number of inputs and outputs
*/
void Process(AudioHandle::InputBuffer in,
AudioHandle::OutputBuffer out,
size_t size);
/*
* Processes information to be shown on the display.
*/
void Draw();
};
#endif // CASCADE_DROPLETS_LFO_DROPLET_H_

View File

@ -105,28 +105,6 @@ void VCODroplet::Draw() {
AnimationInc(); AnimationInc();
} }
std::string VCODroplet::WaveToString(uint8_t wf) {
switch(wf){
case Oscillator::WAVE_TRI:
return "Triangle";
case Oscillator::WAVE_SQUARE:
return "Square";
case Oscillator::WAVE_SIN:
return "Sine";
case Oscillator::WAVE_SAW:
return "Saw";
case Oscillator::WAVE_RAMP:
return "Ramp";
case Oscillator::WAVE_POLYBLEP_TRI:
return "PolyBLEP Triangle";
case Oscillator::WAVE_POLYBLEP_SQUARE:
return "PolyBLEP Square";
case Oscillator::WAVE_POLYBLEP_SAW:
return "PolyBLEP Saw";
}
return "";
}
void VCODroplet::SetWaveState(uint8_t wf) { void VCODroplet::SetWaveState(uint8_t wf) {
switch(wf){ switch(wf){
case Oscillator::WAVE_TRI: case Oscillator::WAVE_TRI:

View File

@ -24,14 +24,6 @@ private:
const double pi = std::acos(-1); const double pi = std::acos(-1);
Wave* wave_graphic = new Wave(WaveShape::kTriangle, 21, GetTitleHeight()); Wave* wave_graphic = new Wave(WaveShape::kTriangle, 21, GetTitleHeight());
/*
* Converts oscilator to name of wave shape.
*
* @param wf wave shape
* @return name of wave shap
*/
std::string WaveToString(uint8_t wf);
/* /*
* Sets the vco wave shap to display on screen. * Sets the vco wave shap to display on screen.
* *

View File

@ -115,6 +115,10 @@ static void AudioThrough(AudioHandle::InputBuffer in,
Droplet* GetDroplet(DropletState state) { Droplet* GetDroplet(DropletState state) {
switch(selected_menu->GetState()) { switch(selected_menu->GetState()) {
default: default:
case MenuState::kLFO:
return new LFODroplet(&patch,
state,
sample_rate);
case MenuState::kMixer: case MenuState::kMixer:
return new MixerDroplet(&patch, return new MixerDroplet(&patch,
state); state);

View File

@ -12,6 +12,7 @@
#include "menu.h" #include "menu.h"
#include "droplets/droplet.h" #include "droplets/droplet.h"
#include "droplets/droplet_manager.h" #include "droplets/droplet_manager.h"
#include "droplets/lfo_droplet.h"
#include "droplets/mixer_droplet.h" #include "droplets/mixer_droplet.h"
#include "droplets/noise_droplet.h" #include "droplets/noise_droplet.h"
#include "droplets/vca_droplet.h" #include "droplets/vca_droplet.h"

View File

@ -9,6 +9,7 @@ Menu::Menu(DaisyPatch* m_patch,
head = new MenuItem(MenuState::kSplit, "Split"); head = new MenuItem(MenuState::kSplit, "Split");
head->AddItemEnd(new MenuItem(MenuState::kChange, "")); head->AddItemEnd(new MenuItem(MenuState::kChange, ""));
head->AddItemEnd(new MenuItem(MenuState::kLFO, "LFO"));
head->AddItemEnd(new MenuItem(MenuState::kMixer, "Mixer")); head->AddItemEnd(new MenuItem(MenuState::kMixer, "Mixer"));
head->AddItemEnd(new MenuItem(MenuState::kNoise, "Noise")); head->AddItemEnd(new MenuItem(MenuState::kNoise, "Noise"));
head->AddItemEnd(new MenuItem(MenuState::kVCA, "VCA")); head->AddItemEnd(new MenuItem(MenuState::kVCA, "VCA"));

View File

@ -5,7 +5,7 @@
#include <string> #include <string>
enum class MenuState {kSplit, kChange, kMixer, kNoise, kVCA, kVCO}; enum class MenuState {kSplit, kChange, kLFO, kMixer, kNoise, kVCA, kVCO};
class MenuItem { class MenuItem {
private: private:

View File

@ -93,3 +93,25 @@ void WriteDoubleCentered(DaisyPatch* patch,
std::string text) { std::string text) {
WriteDoubleCentered(patch, x, y, width, font, text, true); WriteDoubleCentered(patch, x, y, width, font, text, true);
} }
std::string WaveToString(uint8_t wf) {
switch(wf){
case Oscillator::WAVE_TRI:
return "Triangle";
case Oscillator::WAVE_SQUARE:
return "Square";
case Oscillator::WAVE_SIN:
return "Sine";
case Oscillator::WAVE_SAW:
return "Saw";
case Oscillator::WAVE_RAMP:
return "Ramp";
case Oscillator::WAVE_POLYBLEP_TRI:
return "PolyBLEP Triangle";
case Oscillator::WAVE_POLYBLEP_SQUARE:
return "PolyBLEP Square";
case Oscillator::WAVE_POLYBLEP_SAW:
return "PolyBLEP Saw";
}
return "";
}

View File

@ -3,11 +3,13 @@
#ifndef CASCADE_UTIL_H_ #ifndef CASCADE_UTIL_H_
#define CASCADE_UTIL_H_ #define CASCADE_UTIL_H_
#include "daisysp.h"
#include "daisy_patch.h" #include "daisy_patch.h"
#include <string> #include <string>
using namespace daisy; using namespace daisy;
using namespace daisysp;
#define SSD1309_WIDTH 128 #define SSD1309_WIDTH 128
@ -128,4 +130,12 @@ void WriteDoubleCentered(DaisyPatch* patch,
FontDef font, FontDef font,
std::string text); std::string text);
/*
* Converts oscilator to name of wave shape.
*
* @param wf wave shape
* @return name of wave shap
*/
std::string WaveToString(uint8_t wf);
#endif // CASCADE_UTIL_H_ #endif // CASCADE_UTIL_H_