/*  Example playing a looped sampled sound while
    changing the start end end loop points,
    and sliding the frequency around,
    using Mozzi sonification library.

    Demonstrates Sample(), looping with random
    changes to loop and frequency parameters
    scheduled with EventDelay.

    Circuit: Audio output on digital pin 9 on a Uno or similar, or
    DAC/A14 on Teensy 3.1, or
    check the README or http://sensorium.github.io/Mozzi/

   Mozzi documentation/API
   https://sensorium.github.io/Mozzi/doc/html/index.html

   Mozzi help/discussion/announcements:
   https://groups.google.com/forum/#!forum/mozzi-users

   Copyright 2012-2024 Tim Barrass and the Mozzi Team

   Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.

*/

#define MOZZI_CONTROL_RATE 128
#include <Mozzi.h>
#include <Sample.h> // Sample template
#include <samples/abomb16384_int8.h> // table for Sample
#include <EventDelay.h>
#include <mozzi_rand.h>

// use: Sample <table_size, update_rate> SampleName (wavetable)
Sample <ABOMB_NUM_CELLS, MOZZI_AUDIO_RATE> aSample(ABOMB_DATA);

// for scheduling changes
EventDelay  kTriggerDelay;


const float playspeed = 1.3;
float playspeedmod = 0;
float speedchange = 0;

const unsigned int full = (int) (1000.f/playspeed) - 23; // adjustment approx for MOZZI_CONTROL_RATE difference

void setup(){
  randSeed(); // reseed the random generator for different results each time the sketch runs
  aSample.setFreq(playspeed*((float) ABOMB_SAMPLERATE / (float) ABOMB_NUM_CELLS));
  kTriggerDelay.set(full);
  aSample.setLoopingOn();
  startMozzi();
}


unsigned int chooseStart(){
  return rand((unsigned int)ABOMB_NUM_CELLS);
}


unsigned int chooseEnd(unsigned int startpos){
  return rand(startpos, (unsigned int) ABOMB_NUM_CELLS);
}


void chooseSpeedMod(){
  if (rand((byte)3) == 0){
    speedchange = (float)rand((char)-100,(char)100)/8000;
    float startspeed = (float)rand((char)-100,(char)100)/100;
    playspeedmod = playspeed + startspeed;
  }
  else{
    speedchange = 0;
    playspeedmod = playspeed;
  }
}


void chooseStartEnd(){
  unsigned int s,e;
  if (rand((byte)2) == 0){
    s = chooseStart();
    e = chooseEnd(s);
  }
  else{
    s = 0;
    e = ABOMB_NUM_CELLS;
  }
  aSample.setStart(s);
  aSample.setEnd(e);
}


void updateControl(){
  if(kTriggerDelay.ready()){
    chooseStartEnd();
    chooseSpeedMod();
    kTriggerDelay.start();
  }
  playspeedmod += speedchange;
  aSample.setFreq(playspeedmod);
}


AudioOutput updateAudio(){
  return MonoOutput::from8Bit(aSample.next());
}


void loop(){
  audioHook();
}
