Encoder to change scale for 7 buttons

Hi everyone! I’ve been programming Arduino for a few years now. This is my first shot at Daisy Seed, and I started with Daisyduino. It worked ok, but I wanted access to more robust effects ect.so I switched to Daisylib. Just to tug at your heart strings a bit and give you a little context, I’m building a simple synth for my 4 year old niece. My mom (her Grandma) is a ukulele virtuoso. My plan is to have an encoder and a 7 segment display that can set the buttons to any key major or minor, so Grandma can set the key and Niece can play along and make real in key music! So far I have 7 buttons, 7 pots 1 encoder and 1 7 segment display. The pots are set up to set the frequency for the Oscillators on each button. I saw the DaisyDrone ( https://github.com/cutlasses/DaisyDrone ) and figured it would be relatively easy to port it over… it wasn’t. I have the pots, encoder and 7 segment display wired up to the seed exactly like the Daisydrone schematic but I am having a heck of a time adding in my buttons and scales. Here’s my code so far. I’d love any suggestions on how to complete my project and any suggestions on improving my code would be fantastic as well… this is my first foray away from arduino and into C++. Me, my Mom and my Niece Caiden thank you SO much in advance! Feel free to ask for any clarification you may need. Thanks so much!

#include <array>

#include "daisy_seed.h"
#include "daisysp.h"
using namespace daisy;
using namespace daisysp;
using namespace daisy::seed;

// Declare a DaisySeed object called hw
DaisySeed  hw;

// Declare Oscillators
Oscillator osc1, osc2, osc3, osc4, osc5, osc6, osc7;

// Declare Attack/Decay Envelopes
AdEnv      env1, env2, env3, env4, env5, env6, env7;

// Declare Buttons
Switch button1, button2, button3, button4, button5, button6, button7;

void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                   AudioHandle::InterleavingOutputBuffer out, size_t size)
{
    // Create a mess of float variables
    float osc1_out, env1_out, osc2_out, env2_out, osc3_out, env3_out, osc4_out, env4_out, osc5_out, env5_out, osc6_out, env6_out, osc7_out, env7_out;
    
    //Nobody likes a bouncy button
    button1.Debounce();
    button2.Debounce();
    button3.Debounce();
    button4.Debounce();
    button5.Debounce();
    button6.Debounce();
    button7.Debounce();
    
    //If you push the button,...
    if(button1.RisingEdge())
    {
        env1.Trigger(); //Trigger the envelope!
    }
    if(button2.RisingEdge())
    {
        env2.Trigger();
    }
    if(button3.RisingEdge())
    {
        env3.Trigger();
    }
    if(button4.RisingEdge())
    {
        env4.Trigger();
    }
    if(button5.RisingEdge())
    {
        env5.Trigger();
    }
    if(button6.RisingEdge())
    {
        env6.Trigger();
    }
    if(button7.RisingEdge())
    {
        env7.Trigger();
    }
    
    //Set Oscillators to a static "A minor" scale
    //osc1.SetFreq(220);
    //osc2.SetFreq(246.94);
    //osc3.SetFreq(261.63);
    //osc4.SetFreq(293.66);
    //osc5.SetFreq(329.63);
    //osc6.SetFreq(349.23);
    //osc7.SetFreq(392);
    
    //Use the knobs to set the frequency of each Oscillator
    //Convert floating point knob to midi (0-127)
    //Then convert midi to freq. in Hz
    osc1.SetFreq(mtof(hw.adc.GetFloat(0) * 127));
    osc2.SetFreq(mtof(hw.adc.GetFloat(1) * 127));
    osc3.SetFreq(mtof(hw.adc.GetFloat(2) * 127));
    osc4.SetFreq(mtof(hw.adc.GetFloat(3) * 127));
    osc5.SetFreq(mtof(hw.adc.GetFloat(4) * 127));
    osc6.SetFreq(mtof(hw.adc.GetFloat(5) * 127));
    osc7.SetFreq(mtof(hw.adc.GetFloat(6) * 127));
                 
    //Fill the block with samples
    for(size_t i = 0; i < size; i+=7)
    {
        //Get the next envelope value
        env1_out = env1.Process();
        //Set the oscillator volume to the latest env value
        osc1.SetAmp(env1_out);
        //get the next oscillator sample
        osc1_out = osc1.Process();
        
        env2_out = env2.Process();
        osc2.SetAmp(env2_out);
        osc2_out = osc2.Process();
        
        env3_out = env3.Process();
        osc3.SetAmp(env3_out);
        osc3_out = osc3.Process();
        
        env4_out = env4.Process();
        osc4.SetAmp(env4_out);
        osc4_out = osc4.Process();
        
        env5_out = env5.Process();
        osc5.SetAmp(env5_out);
        osc5_out = osc5.Process();
        
        env6_out = env6.Process();
        osc6.SetAmp(env6_out);
        osc6_out = osc6.Process();
        
        env7_out = env7.Process();
        osc7.SetAmp(env7_out);
        osc7_out = osc7.Process();
        
        //Set the left and right outputs
        out[i] = osc1_out + osc2_out + osc3_out + osc4_out + osc5_out + osc6_out + osc7_out;
        out[i + 1] = osc1_out + osc2_out + osc3_out + osc4_out + osc5_out + osc6_out + osc7_out;
    }
}


int main(void)
{
    // Configure and Initialize the Daisy Seed
    // These are separate to allow reconfiguration of any of the internal
    // components before initialization.
    hw.Configure();
    hw.Init(true);
    hw.SetAudioBlockSize(6); // number of samples handled
    //How many samples well output per second
    float sample_rate = hw.AudioSampleRate();
    
    // Create an array of 7 AdcChannelConfig objects
    const int num_adc_channels = 7;
    AdcChannelConfig my_adc_config[num_adc_channels];

    //Initialize the knobs
    my_adc_config[0].InitSingle(hw.GetPin(15));
    my_adc_config[1].InitSingle(hw.GetPin(16));
    my_adc_config[2].InitSingle(hw.GetPin(17));
    my_adc_config[3].InitSingle(hw.GetPin(18));
    my_adc_config[4].InitSingle(hw.GetPin(19));
    my_adc_config[5].InitSingle(hw.GetPin(20));
    my_adc_config[6].InitSingle(hw.GetPin(21));
    
    //Initialize the buttons
    button1.Init(hw.GetPin(13), sample_rate / 48.f);
    button2.Init(hw.GetPin(12), sample_rate / 48.f);
    button3.Init(hw.GetPin(11), sample_rate / 48.f);
    button4.Init(hw.GetPin(10), sample_rate / 48.f);
    button5.Init(hw.GetPin(9), sample_rate / 48.f);
    button6.Init(hw.GetPin(8), sample_rate / 48.f);
    button7.Init(hw.GetPin(7), sample_rate / 48.f);
    
    //Set the ADC to use our configuration
    hw.adc.Init(my_adc_config, num_adc_channels);
    
    //Set up oscillators
    osc1.Init(sample_rate);
    osc1.SetWaveform(osc1.WAVE_TRI);
    osc1.SetAmp(0.22f);
    osc1.SetFreq(1000);
    
    osc2.Init(sample_rate);
    osc2.SetWaveform(osc2.WAVE_TRI);
    osc2.SetAmp(0.22f);
    osc2.SetFreq(1000);
    
    osc3.Init(sample_rate);
    osc3.SetWaveform(osc3.WAVE_TRI);
    osc3.SetAmp(0.22f);
    osc3.SetFreq(1000);
    
    osc4.Init(sample_rate);
    osc4.SetWaveform(osc4.WAVE_TRI);
    osc4.SetAmp(0.22f);
    osc4.SetFreq(1000);
    
    osc5.Init(sample_rate);
    osc5.SetWaveform(osc5.WAVE_TRI);
    osc5.SetAmp(0.22f);
    osc5.SetFreq(1000);
    
    osc6.Init(sample_rate);
    osc6.SetWaveform(osc6.WAVE_TRI);
    osc6.SetAmp(0.22f);
    osc6.SetFreq(1000);
    
    osc7.Init(sample_rate);
    osc7.SetWaveform(osc7.WAVE_TRI);
    osc7.SetAmp(0.22f);
    osc7.SetFreq(1000);
    
    //Set up volume envelopes
    env1.Init(sample_rate);
    //Envelope attack and decay times
    env1.SetTime(ADENV_SEG_ATTACK, .11);
    env1.SetTime(ADENV_SEG_DECAY, .44);
    //minimum and maximum envelope values
    env1.SetMin(0.0);
    env1.SetMax(1.0f);
    env1.SetCurve(1); // linear
    
    env2.Init(sample_rate);
    env2.SetTime(ADENV_SEG_ATTACK, .11);
    env2.SetTime(ADENV_SEG_DECAY, .44);
    env2.SetMin(0.0);
    env2.SetMax(1.0f);
    env2.SetCurve(1);
    
    env3.Init(sample_rate);
    env3.SetTime(ADENV_SEG_ATTACK, .11);
    env3.SetTime(ADENV_SEG_DECAY, .44);
    env3.SetMin(0.0);
    env3.SetMax(1.0f);
    env3.SetCurve(1);
    
    env4.Init(sample_rate);
    env4.SetTime(ADENV_SEG_ATTACK, .11);
    env4.SetTime(ADENV_SEG_DECAY, .44);
    env4.SetMin(0.0);
    env4.SetMax(1.0f);
    env4.SetCurve(1);
    
    env5.Init(sample_rate);
    env5.SetTime(ADENV_SEG_ATTACK, .11);
    env5.SetTime(ADENV_SEG_DECAY, .44);
    env5.SetMin(0.0);
    env5.SetMax(1.0f);
    env5.SetCurve(1);
    
    env6.Init(sample_rate);
    env6.SetTime(ADENV_SEG_ATTACK, .11);
    env6.SetTime(ADENV_SEG_DECAY, .44);
    env6.SetMin(0.0);
    env6.SetMax(1.0f);
    env6.SetCurve(1);
    
    env7.Init(sample_rate);
    env7.SetTime(ADENV_SEG_ATTACK, .11);
    env7.SetTime(ADENV_SEG_DECAY, .44);
    env7.SetMin(0.0);
    env7.SetMax(1.0f);
    env7.SetCurve(1);
    
    //Start the adc
    hw.adc.Start();
    
    //Start calling the audio callback
    hw.StartAudio(AudioCallback);

    // Loop forever
    while(1) {
    }
}


EDIT: So far this code works great… I just need the 7 segment display and encoder to change the scale of the buttons!

Welcome @subminimal!!
It’s lovely to hear that you’re creating an instrument for your family! :slight_smile:

I think pod’s Encoder example in the DaisyExamples folder should be a good reference for this project.

OK cool. I’m going to check that out. Thank you for the lead!

1 Like