// Sound to Light v1.0 by Frederik Rosenkjaer.
// Designed to be used with American DJ application "MyDMX" through MIDI Yoke from MIDIox.

// Works like this:
// Put this on a track. Set track to output MIDI to MIDI Yoke
// While Reaper is running in the background, MyDMX can now hear the Control Changes
// generated by this plugin, and can trigger scenes from them (right click on the Scenes,
// and choose "Midi Learn").

// The plugin will transmit a Control Change (#001) with the value of one of the 12 Scenes-
// sliders either in fixed sequence or in ransom order.
// It will only choose between the first X number of sliders, as determined by the
// "Number of Scenes to use"-slider.


desc: Sound to Light v1.0 - Trigger MIDI-CC's from incoming sound

slider1:0<-60,0,.1>Threshold (dB)
slider2:500<100,3000, 10>Re-trig delay (ms)
slider3:2<1,12,1>Number of Scenes to use
slider4:0<0,1,1{STEP,RANDOM}>Mode
slider5:0<0,127,1> Scene #1
slider6:0<0,127,1> Scene #2
slider7:0<0,127,1> Scene #3
slider8:0<0,127,1> Scene #4
slider9:0<0,127,1> Scene #5
slider10:0<0,127,1> Scene #6
slider11:0<0,127,1> Scene #7
slider12:0<0,127,1> Scene #8
slider13:0<0,127,1> Scene #9
slider14:0<0,127,1> Scene #10
slider15:0<0,127,1> Scene #11
slider16:0<0,127,1> Scene #12

in_pin: Trig_Input
out_pin:none

@init
  
  retrigflag = 0;                           // Flag =0 when not inside retrigdelay
  retrigcounter = 0;                        // Counter used for keeping retrig delay
  sceneindex = 0;                           // Array of Scenenumbers to be recalled
  scenenumber = 1;                          // Scene index pointer 


@slider
  threshold = 1/10^(slider1 / -20);         // convert slider input in dB to JS spl values
  retrigdelay = srate * slider2 * 0.001;    // convert retrigdelay from miliseconds to samples

  sceneindex[1] = slider5;
  sceneindex[2] = slider6;
  sceneindex[3] = slider7;
  sceneindex[4] = slider8;
  sceneindex[5] = slider9;
  sceneindex[6] = slider10;
  sceneindex[7] = slider11;
  sceneindex[8] = slider12;
  sceneindex[9] = slider13;
  sceneindex[10] = slider14;
  sceneindex[11] = slider15;
  sceneindex[12] = slider16;


@sample

  retrigflag == 1 ? (                       // Are we currently in a retrig delay period?
    retrigcounter += 1;                     // If so: increase retrigcounter...
    retrigcounter >= retrigdelay ? (        // ...and check if retrig delay has been reached...
      retrigflag = 0;                       // ...set retrig flag to zero if it has..
      retrigcounter = 0;                    // ..and reset the counter
      );
                                                    

    ) : (                                   // If we weren't in retrig delay
      spl0 > threshold ? (                  // ...then check input level

                                            // The following is in case of triggering
        retrigflag = 1;                     // Set retrig flag to start new retrig delay
          slider4 == 0 ? (                  // What mode are we in? STEP? Then...
            scenenumber >= slider3 ? scenenumber = 0; // Check if we're at the end of the chase and restart if so
            scenenumber += 1;
            midisend(0,176,(sceneindex[scenenumber]));// send CC #001 of value sceneindex to channel 1
          ) : (                             // If we were in RANDOM mode then...
            while (
              randomnumber = ceil(rand(slider3)); // Pick a random number
              scenenumber == randomnumber; // If number is the same as previous, try again
            );
            scenenumber = randomnumber;     // Move random number to pointer
            midisend(0,176,(sceneindex[scenenumber])); // Send CC #001 with value of randomly chosen slider
          );
       );
    );
