Subversion Repositories DIN Is Noise

Rev

Rev 518 | Rev 1365 | 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-2018 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/


#include "triggered_note.h"
#include "chrono.h"
#include "main.h"
#include "utils.h"

extern ui_clock ui_clk;
extern audio_out aout;

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

  tn = n;
  start_hz = tn.hz;

  key = k;

  state = ATTACK;
  abs_attack = 0;

  x = xx; y = yy;

  r = rr; g = gg; b = bb;

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

  volume_now = 0;
  volume_max = vmax;

  decay_time = 0;
  decay_start_volume = 0;

}

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 ) {

  extern float SAMPLE_DURATION;
  extern float MIN_TIME;

  switch (state) {

    case ATTACK:

      if (equals (attack_time, 0.0f)) attack_time = MIN_TIME;
      //if (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
      for (int i = 0; i < n; ++i) vol[i] *= volume_max; // scale volume
      volume_now = vol[n-1]; // volume at end of volume buffer is volume now of the note
      player.master (L, R, wav, n, vol);
      decay_start_volume = volume_now;

      break;

    case DECAY:

      if (equals (decay_time, 0.0f)) decay_time = MIN_TIME;
      //if (decay_time == 0.0f) decay_time = MIN_TIME;
      decay_time = fabs (decay_start_volume) / 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;
      player.master (L, R, wav, n, vol);
      volume_now = vol[n-1];
      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))
    //if (volume_max == 0.0f || decay_start_volume == 0.0f)
      state = FINISHED;
    else
      abs_decay = 0;
  }
}

void triggered_note::set_freq (float f) {
  tn.set_freq (f);
  player.set_interpolated_pitch (tn.step);
}

int triggered_note::update_solver (multi_curve& crv) {
  sol.update ();
  if (crv.num_vertices) player.set_mix (crv);
  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 ();
  }
}