Subversion Repositories DIN Is Noise

Rev

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

/*
* drone.cc
* DIN Is Noise is copyright (c) 2006-2018 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/



#include "din.h"
#include "drone.h"
#include "console.h"
#include "audio.h"

drone::drone (int _bottom) {
  step = vol = 0;
  range = 0;
  pos = 0.0f;
  r = g = b = 0.5f;
  cx = cy = 0;
  x = y = 0;
  dy = 0;
  xv = x; yv = y;
  xa = x; ya = y;
  sel = 0;
  state = DEAD;
  frozen = 0;
  froze_at = 0;
  handle_size = DRONE_HANDLE_SIZE;
  trail.num_points = 0;
  trail.total_points = TRAIL_LENGTH;
  id = ++UID;
  V = 6;
  vx = 0; if (_bottom >= BOTTOM) vy = 1; else vy = -1;
  v_mult = 1.0f;
  A = 0.25f;
  ax = 1; ay = 0;
  gravity = 0;
  bounces = 0;
  attractor = 0;
  orbiting = 0;
  launcher = 0;
  tracking = 0;
  tracked_drone = 0;
  dpm = 60;
  ++ref;
  birth = -1;
  life = drone::LIFE_TIME;
  insert = drone::INSERT_TIME;
  launched_by = 0;
  target = 0;
  cur_target = 0;
  num_targets = 0;
  update_pv = 0;
}

drone::~drone () {
  --ref;
}

void drone::move_center () {
  cx += (x - xi);
  cy += (y - yi);
}

void drone::set_center (int xx, int yy) {
  cx = xx;
  cy = yy;
  if (!mod.active) set_xy (xx, yy);
}

void drone::set_xy (int xx, int yy) {

  // position
  x = xx;
  y = yy;

  // height, volume
  dy = y - BOTTOM;
  vol = dy * DELTA_VOLUME;

  // locate range on microtonal-keyboard
  range = din0.find_range (x, range);

  // locate pitch on microtonal-keyboard
  ::range& dr = din0.ranges[range];
  int delta_left = x - dr.extents.left;
  if (SNAP_TO_NOTES) { // pitch is either left or right notes of a range
    int delta_right = dr.extents.right - x;
    pos = delta_left * 1.0f / dr.extents.width;
    int note_num;
    if (pos <= din0.dinfo.snap.left) note_num = 0;
    else if (pos >= din0.dinfo.snap.right) note_num = 1;
    else goto normal;
    if (note_num) { pos = 1; x = dr.extents.right; } else { pos = 0; x = dr.extents.left;}
    step = dr.notes[note_num].step;
  } else {
    pos = delta_left * 1.0f / dr.extents.width;
    normal:
    float n0step = dr.notes[0].step, n1step = dr.notes[1].step;
    step = n0step + pos * (n1step - n0step);
  }

  calc_handle (); // update drone handle

  update_pv = EMPLACE; // update pitch volume b4 rendering drones
   
}


void drone::calc_handle () {
  y = BOTTOM + dy;
  handle (x - handle_size, y - handle_size, x + handle_size, y + handle_size);
}

void drone::update_pitch_volume (float dmv) {
  // update pitch & vol on drone's player
  float v = dmv * fdr.amount * vol;
  player.set_interpolated_pitch_volume (step, v);
  --update_pv;
}


void drone::change_bpm (mod_params& mp, beat2value& bv, float delta) {
  float bpm = mp.bpm + delta;
  mp.set_bpm (bv, bpm);
}

void drone::change_bpm (int i, int what, float delta) {
  if (what == drone_modulation::FM) {
    change_bpm (mod.fm, drone_modulation::fm_crv, delta);
    cons << "drone: " << i << ", FM bpm = " << mod.fm.bpm << eol;
  } else {
    change_bpm (mod.am, drone_modulation::am_crv, delta);
    cons << "drone: " << i << ", AM bpm = " << mod.am.bpm << eol;
  }
  //trail.exists = mod.calc_active ();
  mod.calc_active ();
}

void drone::change_depth (int i, int what, float delta) {
  if (what == drone_modulation::FM) {
    mod.fm.depth += delta;
    cons << "drone: " << i << ", FM depth = " << mod.fm.depth << eol;
  } else {
    mod.am.depth += delta;
    cons << "drone: " << i << ", AM depth = " << mod.am.depth << eol;
  }
  //trail.exists = mod.calc_active ();
  mod.calc_active ();
}

mod_params::mod_params (beat2value& bv) {
  int reset = 1;
  clear (bv, reset);
}

void mod_params::clear (beat2value& bv, int reset) {
  depth = 0;
  set_bpm (bv, bv.bpm, reset);
}

void mod_params::set_bpm (beat2value& bv, float value, int reset) {
  bv.set_bpm (value);
  bpm = bv.bpm;
  extern audio_out aout;
  db = bv.delta * aout.samples_per_channel; // modulate once every audio buffer
  if (reset) b = bv.sol.firstx;
}

void mod_params::calc (beat2value& bv) {
  result = depth * bv.sol (b, db);
}

void drone::clear_targets () {
  targets.clear ();
  cur_target = 0;
  num_targets = 0;
}

void drone::handle_time_pass () {
  double tp = ui_clk() - froze_at;
  if (birth != -1) birth += tp;
  if (launcher) launch_every.startt += tp;
}