Subversion Repositories DIN Is Noise

Rev

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

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



#include "din.h"
#include "drone.h"
#include "console.h"
#include "audio.h"
#include "utils.h"
#include "vector2d.h"
#include "menu.h"
#include <math.h>

extern multi_curve drone_mod_am_crv, drone_mod_fm_crv;
extern solver warp_vol, warp_pitch;
extern int TRAIL_LENGTH;
extern const char spc;

drone::drone (float bottom) : trail (TRAIL_LENGTH), mod (&drone_mod_fm_crv, &drone_mod_am_crv) {
  is = drone::IS;
  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;
  sx = 0;
  sel = 0;
  state = DEAD;
  frozen = 0;
  froze_at = 0;
  handle_size = drone::HANDLESIZE;
  id = ++UID;
  V = V0;
  initv (bottom);
  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;
  launched_by = 0;
  reincarnate = 0;
  switch (are) {
    case IMMORTAL:
      birth = -1;
      break;
    case MORTAL:
      birth = ui_clk ();
      break;
    case REINCARNATE:
      birth = ui_clk ();
      reincarnate = 1;
      break;
  }
  life = LIFETIME;
  insert = INSERTTIME;
  target = 0;
  cur_target = 0;
  num_targets = 0;
  update_pv = UNSET;
  snap = 0;
  nconn = 0;
  type = CHAIN;
  gab.set (1.0f, 0.0f, 0, 1.0f);
  tovol = 0.0f;
  finl = 0;
  note_num = -1;
}

void drone::initv (float y) {
  vx0 = vx = 0;
  vx = 0; if (y >= BOTTOM) vy0 = vy = 1; else vy0 = vy = -1;
}

void drone::resetv () {
  V = V0;
  vx = vx0;
  vy = vy0;
}

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

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

drone* drone::eval_conns () {
  if (nconn) {
    int n = 0;
    proc_conn [this] = true;
    list<double>::iterator mi = mags.begin();
    drone_iterator p = connections.begin ();
    drone* c0 = *p;
    for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
      drone* pdc = *p;
      if (proc_conn[pdc] == false) {
        proc_conn [pdc] = true;
        drone& dc = *pdc;
        double now = magnitude (cx, cy, dc.cx, dc.cy);
        double org = *mi;
        if (now > org) {
          double lead = STIFFNESS * (now - org);
          float ux, uy; unit_vector<float, int> (ux, uy, dc.cx, dc.cy, cx, cy);
          dc.set_center (dc.cx + lead * ux, dc.cy + lead * uy);
          ++n;
        }
      }
    }
    if (n) return this; else return c0;
  }
  return 0;
}

void drone::remagconns () {
  list<double>::iterator mi = mags.begin();
  drone_iterator p = connections.begin ();
  for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
    drone* pd = *p;
    *mi = magnitude<double> (cx, cy, pd->cx, pd->cy);
  }
}

void drone::set_center (float xx, float yy, int e) {
  cx = xx;
  cy = yy;
  if (frozen) set_pos (cx + mod.fm.result, cy + mod.am.result);
  if (e) eval_conns ();
}

void drone::set_pos (float xx, float yy) {

  // position
  x = xx;
  y = yy;

  // position affects velocity?
  if (posafxvel.yes && !mod.am.autorot.yes && !gravity && !tracking && !orbiting) {
    double mag = magnitude (posafxvel.pt.x, posafxvel.pt.y, x, y);
    if (mag > posafxvelt::minmag) {
      direction (vx, vy, posafxvel.pt.x, posafxvel.pt.y, x, y);
      vx /= mag;
      vy /= mag;
      posafxvel.pt.x = x;
      posafxvel.pt.y = y;
    }
  }

  // locate range on microtonal-keyboard
  range = din0.find_range (x, range);
  ::range& dr = din0.ranges[range];

  // pitch position in range
  int delta_left = x - dr.extents.left;
  pos = delta_left * 1.0f / dr.extents.width;
  if (pos < 0 || pos > 1.0f) ; else pos = warp_pitch (pos);

  // pitch snap
  if (snap) {
    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;
      sx = dr.extents.right;
    } else {
      pos = 0;
      sx = dr.extents.left;
    }
  } else {
    normal:
    note_num = -1;
    sx = x;
  }

  calc_handle ();

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

}

void drone::calc_handle () {
  //handle (sx - handle_size, round(y) - handle_size, sx + handle_size, round(y) + handle_size);
  handle (sx - handle_size, y - handle_size, sx + handle_size, y + handle_size);
}

void drone::update_pitch_volume () {

  ::range& dr = din0.ranges[range];
  dy = y - BOTTOM;
  float iv = dy * 1.0f / dr.extents.height;
  if (dy < 0) vol = -warp_vol (-iv); else vol = warp_vol (iv);

  if (note_num == -1) {
    float n0step = dr.notes[0].step, n1step = dr.notes[1].step;
    float nstep = n0step + pos * (n1step - n0step);
    if (nstep > 0) step = nstep;
  } else {
    step = dr.notes[note_num].step;
  }

  if (is == DRONE) {
    float v = fdr.amount * mastervolume * gab.amount * vol;
    player.set_interpolated_pitch_volume (step, v);
  } else
    setnoise ();

  --update_pv;

}


void drone::setnoise () {
  nsr.set_samples (1.0f / step);
  nsr.set_spread ( fabs(vol) );
}



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

void drone::change_bpm (int i, int what, float delta) {
  if (what == modulator::FM) {
    change_bpm (mod.fm, delta);
    cons << "drone: " << i << ", FM bpm = " << mod.fm.bv.bpm << eol;
  } else {
    change_bpm (mod.am, delta);
    cons << "drone: " << i << ", AM bpm = " << mod.am.bv.bpm << eol;
  }
}

void drone::change_depth (int i, int what, float delta) {
  if (what == modulator::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;
  }
}

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

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

int drone::freeze () {
  ++frozen;
  froze_at = ui_clk ();
  update_pv = drone::EMPLACE;
  return 1;
}

int drone::thaw () {
  if (--frozen < 1) {
    frozen = 0;
    handle_time_pass ();
    return 1;
  }
  return 0;
}


group::group (std::vector<drone*> mem, int _n) {
  n = _n;
  if (n) {
    drones.resize (n);
    for (int i = 0; i < n; ++i) drones[i] = mem[i];
  }
}

std::ostream& operator<< (std::ostream& f, drone::arrowt& aw) {
  f << aw.u << spc << aw.v << spc;
  return f;
}

std::ostream& operator<< (std::ostream& f, drone::chuckt& ch) {
  f << ch.len << spc << ch.speed << spc << ch.dir << spc << ch.ux << spc << ch.uy << spc;
  if (ch.sun) f << ch.sun->id << spc; else f << 0 << spc;
  if (ch.sat) f << ch.sat->id; else f << 0;
  return f;
}

std::istream& operator>> (std::istream& f, drone::chuckt& ch) {
  f >> ch.len >> ch.speed >> ch.dir >> ch.ux >> ch.uy;
  uintptr_t sun; f >> sun; ch.sun = (drone*) sun;
  uintptr_t sat; f >> sat; ch.sat = (drone*) sat;
  return f;
}

void drone::chuckt::re (drone& p) {
  if (sun) {
    p.chuck.len = unit_vector (p.chuck.ux, p.chuck.uy, sun->cx, sun->cy, p.cx, p.cy);
  }
}

/*connect::connect (drone* _d1, drone* _d2) {
  dirty = 1;
  d1 = _d1;
  d2 = _d2;
  mag = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
  p1.x = d1->cx; p1.y = d1->cy;
  p2.x = d2->cx; p2.y = d2->cy;
  align_vel ();
}

void connect::align_vel () {
  unit_vector<float,float>(d1->vx, d1->vy, d1->cx, d1->cy, d2->cx, d2->cy);
  //d2->vx = d1->vx;
  //d2->vy = d1->vy;
}

int connect::eval (drone** ret) {
  double magnew = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
  if (magnew > mag) {
    float ux, uy; unit_vector (ux, uy, d1->cx, d1->cy, d2->cx, d2->cy);
    double lead = magnew - mag;
    int d1mov = ((p1.x != d1->cx) || (p1.y != d1->cy));
    int d2mov = ((p2.x != d2->cx) || (p2.y != d2->cy));
    int d12mov = d1mov && d2mov;
    if (d12mov) {
      lead /= 2.0;
      d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
      d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
      ret[0] = d1;
      ret[1] = d2;
    } else {
      if (d1mov) {
        d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
        ret[0] = d2;
        ret[1] = 0;
      } else if (d2mov) {
        d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
        ret[0] = d1;
        ret[1] = 0;
      }
    }
    align_vel ();
    p1.x = d1->cx; p1.y = d1->cy;
    p2.x = d2->cx; p2.y = d2->cy;
    dirty = 0;
    return 1;
  }
  dirty = 0;
  return 0;
}

void connect::draw () {
  glBegin (GL_LINES);
    glColor3f (d1->r, d1->g, d1->b);
    glVertex2i (d1->cx, d1->cy);
    glColor3f (d2->r, d2->g, d2->b);
    glVertex2i (d2->cx, d2->cy);
  glEnd ();
}*/