Skip to content
Snippets Groups Projects
Select Git revision
  • c03a7dda81934ddefd2912ea44c3954d449e2580
  • master default protected
  • variants
  • work
  • v1.0
5 results

board.json.imp_meta

Blame
  • daisy-looper.ino 7.38 KiB
    
    
    // Title: moogladder
    // Description: Sweeps the cutoff with an lfo
    // Hardware: Daisy Seed
    // Author: Ben Sergentanis
    
    #include "DaisyDuino.h"
    #include <SPI.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SH110X.h>
    #include <CpuLoadMeter.h>
    
    #include "leds.h"
    #include "potentiometers.h"
    #include "buttons.h"
    #include "looper.h"
    #include "env_follower.h"
    #include "helpers.h"
    #include "ui.h"
    
    
    #define BUFFER_LENGTH_SECONDS 5
    
    static const size_t buffer_length = 48000 * BUFFER_LENGTH_SECONDS;
    static float DSY_SDRAM_BSS buffer[buffer_length];
    
    // Create instances of audio stuff
    atoav::Looper looper;
    static atoav::EnvelopeFollower input_envelope_follower;
    DelayLine<float, 24000> delayline;
    DSY_SDRAM_BSS ReverbSc reverb;
    static Compressor compressor;
    Oscillator lfo;
    static SampleHold sample_and_hold;
    static WhiteNoise noise;
    static Metro tick;
    
    // Initialize Buttons
    Button button_1 = Button(D7);
    Button button_2 = Button(D8);
    Button button_3 = Button(D9);
    Button button_4 = Button(D10);
    Button button_5 = Button(D13);
    Button button_6 = Button(D14);
    
    // Initialize Potentiometers
    Potentiometer pot_1 = Potentiometer(A0);
    Potentiometer pot_2 = Potentiometer(A1);
    Potentiometer pot_3 = Potentiometer(A3);
    Potentiometer pot_4 = Potentiometer(A2);
    Potentiometer pot_5 = Potentiometer(A4);
    Potentiometer pot_6 = Potentiometer(A5);
    Potentiometer pot_7 = Potentiometer(A6);
    
    // RGB LED               R    G    B
    RGBLed rgb_led = RGBLed(A10, A9, A11);
    
    
    // OLED Display
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define OLED_RESET -1   //   QT-PY / XIAO
    Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
    
    // User Interface
    Ui ui;
    
    // Daisy
    DaisyHardware hw;
    
    // Variables for the Audio-Callback
    size_t num_channels
    ;
    float blocksize;
    float drywetmix = 0.0f;
    float delaymix = 0.0f;
    float delaytime = 100.0f;
    float reverbmix = 0.0f;
    float lfo_amount = 0.0f;
    float pitch_val = 0.5f;
    
    // Actual audio-processing is orchestrated here
    void AudioCallback(float **in, float **out, size_t size) {
      float output = 0.0f;
      float no_delay = 0.0f;
      float wet_delay;
      float out1, out2;
      // set the delay
      delayline.SetDelay(delaytime);
      
      for (size_t i = 0; i < size; i++) {
        uint8_t trig = tick.Process();
        float lfo_value = lfo.Process();
        float noise_value = noise.Process();
        float rand = sample_and_hold.Process(trig, noise_value * 5.0f, sample_and_hold.MODE_SAMPLE_HOLD);
        if (ui.rec_source == REC_SOURCE_NOISE) {
         looper.Record(noise_value * 0.7f);
        }
        // When the metro ticks, trigger the envelope to start.
        float random_amount = (lfo_amount -0.5f) * 2.0;
        if (trig) {
          // tick.SetFreq(rand / (0.1 + random_amount*1000.0f) + 1);
              // If the dial is over 50% jump instead
          if (lfo_amount > 0.5f) {
            looper.addToPlayhead(rand * random_amount* 48000.0f);
            looper.setPlaybackSpeed(pitch_val);
          }
        }
        if (lfo_amount > 0.5f) {
          looper.setPlaybackSpeed(pitch_val);
        } else {
          looper.setPlaybackSpeed(pitch_val + lfo_value * lfo_amount);
        }
    
        float looper_out;
        
        // res.SetDamping(0.1+delaymix*0.2f);
        // Record into the buffer
        if (ui.rec_source == REC_SOURCE_PRE) {
         looper.Record(in[1][i]);
        }
        
        input_envelope_follower.Process(in[1][i]);
    
        // Process the Looper
        looper_out = looper.Process();
    
        // Mix the dry/Wet of the looper
        output = drywetmix * looper_out + in[1][i] * (1.0f - drywetmix);
        
        // output = output * (1.0f - resmix) + res.Process(output*resmix);
        no_delay = output;
        wet_delay = delayline.Read();
        delayline.Write((wet_delay * delaymix * 0.95f)/2.0f + (no_delay*delaymix)/2.0f);
    
        // Add the delay
        output += wet_delay * delaymix;
    
        // Compress the signal
        compressor.Process(output);
    
        // Process reverb
        reverb.Process(output, output, &out1, &out2);
    
        // Mix reverb with the dry signal depending on the amount dialed
        output = output * (1.0f - reverbmix) + out1 * reverbmix;
    
        // Record the output if needed
        if (ui.rec_source == REC_SOURCE_OUT) {
         looper.Record(output);
        }
        
        out[0][i] = out[1][i] = output;
      }
    }
    
    
    
    
    void setup() {
      float sample_rate;
      // Initialize for Daisy pod at 48kHz
      hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
      DAISY.SetAudioBlockSize(64);
      num_channels = hw.num_channels;
      sample_rate = DAISY.get_samplerate();
      blocksize = 64.0f;
    
      // Create a Tick and a noise source for the Sample and Hold
      tick.Init(10, sample_rate);
      noise.Init();
      
      // Initialize Looper with the buffer
      looper.Init(buffer, buffer_length);
    
      // Initialize Envelope Follower for the Level LED
      input_envelope_follower.Init(sample_rate);
      input_envelope_follower.SetAttack(100.0);
      input_envelope_follower.SetDecay(1000.0);
    
      // Initialize Reverb
      reverb.Init(sample_rate);
      reverb.SetFeedback(0.95f);
      reverb.SetLpFreq(18000.0f);
    
      // Initialize Compressor
      compressor.SetThreshold(-64.0f);
      compressor.SetRatio(2.0f);
      compressor.SetAttack(0.005f);
      compressor.SetRelease(0.1250);
    
      // Initialize the LFO for modulations
      lfo.Init(sample_rate);
      lfo.SetWaveform(Oscillator::WAVE_TRI);
      lfo.SetAmp(1);
      lfo.SetFreq(8.0);
    
      // Initialize the Delay at a length of 1 second
      delayline.Init();
      delayline.SetDelay(sample_rate);
    
      // Start serial communications
      Serial.begin(250000);
      Serial.println("Serial communication started");
    
      // Initialize Display
      display.begin(0x3C, true);
      delay(50);
      ui.Render();
      
      // Initialize the LED
      rgb_led.init();
    
      // Set the analog read and write resolution to 12 bits
      analogReadResolution(12);
    
      // Set Knob names and display functions
      pot_1.name = "Start";
      pot_2.name = "Length";
      pot_3.setDisplayMode("Pitch", 1000.0f, POT_DISPLAY_MODE_PERCENT);
      pot_4.setDisplayMode("Mix", 100.0f, POT_DISPLAY_MODE_PERCENT);
      pot_5.setDisplayMode("Delay", 100.0f, POT_DISPLAY_MODE_PERCENT);
      pot_6.setDisplayMode("Reverb", 100.0f, POT_DISPLAY_MODE_PERCENT);
      pot_7.setDisplayMode("LFO", 100.0f, POT_DISPLAY_MODE_PERCENT);
    
      // Set Knob Scaling Modes
      pot_3.setBipolar();
    
      // Initialize Buttons (callbacks are assigned in the Ui class)
      button_1.init();
      button_2.init();
      button_3.init();
      button_4.init();
      button_5.init();
      button_6.init();
    
      // Start the audio Callback
      DAISY.begin(AudioCallback);
    }
    
    void loop() {
      // Read the values from the potentiometers
      float p1 = pot_1.read();
      float p2 = pot_2.read();
      float p3 = pot_3.read();
      float p4 = pot_4.read();
      float p5 = pot_5.read();
      float p6 = pot_6.read();
      float p7 = pot_7.read();
    
      // Update the UI
      ui.update();
    
      // Read the buttons
      button_1.read();
      button_2.read();
      button_3.read();
      button_4.read();
      button_5.read();
      button_6.read();
    
      // Set loop-start and loop-length with the potentiometers
      ui.setLoop(p1, p2);
      
      // Tune the pitch to the ten-fold of the potentiometer 3,
      // a bipolar pot, so it returns values from -1.0 to +1.0
      // Pitch should go 10 octaves up/down (10*1.0 = 1000%)
      pitch_val = 10.0f * p3;
    
      // Set other parameters (from 0.0 to 1.0)
      drywetmix = p4;
      delaymix = p5;
      // Delaytime is in samples
      delaytime = 100.0f + p5 * 23900.0f;
      reverbmix = p6;
      lfo_amount = p7;
    
      // Render the UI (frame rate limited by UI_MAX_FPS in ui.h)
      ui.Render();
    
      // Set the Color and brightness of the RGB LED in 8 bits
      rgb_led.setAudioLevelIndicator(int(input_envelope_follower.getValue() * 255));
    }