Subversion Repositories DIN Is Noise

Rev

Rev 1857 | Rev 2275 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* triggered_note.cc
* DIN Is Noise is copyright (c) 2006-2023 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/


#include "triggered_note.h"
#include "chrono.h"
#include "main.h"
#include "utils.h"
#include "color.h"
#include <cmath>

extern int SAMPLE_RATE;
extern float SAMPLE_DURATION;
extern float MIN_TIME;

triggered_note::triggered_note (const note& n, float vmax, float xx, float yy, int _what, int k, int pmx) {

  tn = n;
  start_hz = tn.hz;

  volume.now = 0;
  volume.max = vmax;

  state = ATTACK;
  abs_attack = 0;

  decay_time = 0;
  decay_start_volume = 0;
  abs_decay = 0;

  x = xx; y = yy;

  key = k;

  prev_mousex = pmx;
  bend = 1;
  bend_x = 0;

  what = _what;
  if (what == NOISE) {
    nsr.set_samples (SAMPLE_RATE / tn.hz);
    nsr.set_spread (volume.max);
    volume.mult = volume.max;
    r = 1.0f; g = r; b = g;
  } else {
    volume.mult = 1.0f;
    set_rnd_color (r, g, b);
  }

}

void triggered_note::setup (multi_curve* wav, multi_curve* atk, multi_curve* dk) {
  sol (wav);
  float y; sol.mcrv->get_vertex (sol.mcrv->last_vertex, decay_lastx, y);
  player.fill_pitch (tn.step);
  player.set_wave (&sol);
  attack (atk);
  decay (dk);
  startt = ui_clk ();
}

void triggered_note::eval (float* L, float* R, float* wav, float* vol, int n, float attack_time, float decay_time, gotog& __gotog ) {


  float& vn_1 = vol[n-1];

  switch (state) {

    case ATTACK:

      if (equals (attack_time, 0.0f)) attack_time = MIN_TIME;
      delta_attack = SAMPLE_DURATION * 1.0f / attack_time;
      attack (abs_attack, delta_attack, n, vol, _atmin, __gotog); // solve attack curve to get bunch of volumes (range 0 to 1)

      if (what == NOTE) {
        for (int i = 0; i < n; ++i) vol[i] *= volume.max; // scale volume
        player.master (L, R, wav, n, vol);
        volume.now = vn_1;
      } else {
        nsr (L, R, n, vol);
        volume.now = vn_1 * volume.max;
      }

      decay_start_volume = vn_1;

      break;

    case DECAY:

      if (equals (decay_time, 0.0f)) decay_time = MIN_TIME;
      decay_time = fabs (decay_start_volume) * volume.mult / volume.max * decay_time;
      delta_decay = SAMPLE_DURATION * 1.0f / decay_time;
      decay (abs_decay, delta_decay, n, vol, _atmin, _atmax);
      for (int i = 0; i < n; ++i) vol[i] *= decay_start_volume;
      if (what == NOTE) {
        player.master (L, R, wav, n, vol);
        volume.now = vn_1;
      } else {
        nsr (L, R, n, vol);
        volume.now = vn_1 * volume.max;
      }
      float x, y; decay.mcrv->get_vertex (decay.mcrv->last_vertex, x, y);
      if (abs_decay >= x) state = FINISHED;
      break;

  }

}

void triggered_note::eval (float attack_time) {
  if (state == ATTACK) {
    float now = ui_clk ();
    float dt = now - startt;
    if (dt >= attack_time) start_decay ();
  }
}

void triggered_note::start_decay () {
  if (state == ATTACK) {
    state = DECAY;
    if (equals (volume.max, 0.0f) || equals (decay_start_volume, 0.0f))
      state = FINISHED;
    else
      abs_decay = 0;
  }
}

void triggered_note::set_freq (float f) {
  if (what == NOTE) {
    tn.set_freq (f);
    player.set_interpolated_pitch (tn.step);
  } else
    nsr.set_samples (SAMPLE_RATE / f);
}

int triggered_note::update_solver (multi_curve& crv, const string& nam) {
  sol.update ();
  if (crv.num_vertices) player.set_mix (crv, nam);
  return player.mixer.active;
}

void update_triggered_notes (std::list<triggered_note>& tl) {
  for (note_iterator i = tl.begin (), j = tl.end (); i != j; ++i) {
    triggered_note& ti = *i;
    ti.player.realloc ();
  }
}

void update_triggered_noises (std::list<triggered_note>& tl) {
  for (note_iterator i = tl.begin (), j = tl.end (); i != j; ++i) {
    triggered_note& ti = *i;
    ti.nsr.warp (&noiser::interp);
  }
}