/// <reference path="../CommandGlobals.d.ts" />
// Hey, thanks for checking out WavTool! Let's make a metronome!


// We'll start by setting up some controls. (It's always best to do this at the very start of your code.)

// Calls to wavtool.numberSetting create sliders over in the "Run Code" area to the right.
// When you hit run, the value of the bpm constant will be whatever you dial in on the slider!
const bpm = wavtool.numberSetting({ min: 40, max: 200, name: 'BPM' });
const duration = wavtool.numberSetting({ min: 0, max: 240, default: 30, name: 'Duration (Seconds)' });
const beatsPerBar = Math.floor(wavtool.numberSetting({ min: 1, max: 16, default: 4, name: 'Beats per Bar' }));
const amplitude = wavtool.numberSetting({ min: 0, max: 1, default: 1, name: 'Amplitude' });

// In wavtool, time values usually need to be converted to samples.
// The math below gets us a number of samples for the duration of one beat,
// and for the duration of the whole generated channel.
const samplesPerBeat = (60 / bpm) * project.sampleRate;
const lengthInSamples = duration * project.sampleRate;

// These values tune the sound of the metronome click itself.
// Try making changes, and then clicking Run Code to generate new tracks!
const clickLengthSamples = (wavtool.sampleRate * 0.02); // 0.02 seconds
const firstBeatFrequency = 1500; // 1500hz
const otherBeatFrequency = 750;
const frequencyDropAmount = 0.4; // Frequency will pitch down by this factor over the click length.

// It's time to generate our audio!
// At the bottom of the code below we're choosing a length, number of channels, and title.
// The callback in the middle is the interesting part.
project.generateTrack(
  (i) => {
    // First, let's figure out if the current moment should have a click signal.
    // If not, we'll just return 0 for this sample, to create silence.
    if (i % samplesPerBeat >= clickLengthSamples) {
      return 0;
    } else {
      // We're going to generate high pitched ticks for the first beat in each bar,
      // and low-pitched ticks for the other beats. Let's figure out which beat this is,
      // and set clickFrequency accordingly.
      const beatNumberInBar = Math.floor((i % (samplesPerBeat * beatsPerBar)) / samplesPerBeat);
      const clickFrequency = beatNumberInBar === 0 ? firstBeatFrequency : otherBeatFrequency;

      // Now, let's figure out how fat we are into the click sound.
      // clickProgress will be 0 at the start of click sound, and 1 at the end of the click sound.
      const indexInBeat = i % samplesPerBeat;
      const clickProgress = 1 - (indexInBeat / clickLengthSamples); // 0-1

      // To generate a percussive chirp, we linearly decrease the frequency over the course of the click.
      // As clickProgress increases, the frequency gets lower.
      const frequency = clickFrequency * ((1 - frequencyDropAmount) + (clickProgress * frequencyDropAmount))

      // Amplitude also decreases over time, though this time it follows a logarithmic curve.
      const currentAmplitude = Math.pow(clickProgress, 2) * amplitude;

      // Finally, we use wavtool.sin to grab the appropriate sample for our output sin wave!
      // We're done!
      return wavtool.sin(indexInBeat * frequency) * currentAmplitude

      // A quick note about wavtool.sin:
      //   wavtool.sin is just like Math.sin, but it takes care of multiplying by (2 * Pi) and dividing by the sample rate.
      //   Math.sin(100 * currentSample * (2 * Math.PI) / sampleRate) === wavtool.sin(currentSample * 100)
    }
  },
  lengthInSamples,
  1,
  `Metronome at ${bpm.toFixed(2)} BPM`
)
