#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
#include <ugens.h>
#include <mixerr.h>
#include <Instrument.h>
#include "VMSTART.h"
#include <rt.h>
#include <rtdefs.h>
#include <globals.h>

strumq *curstrumq[6];

extern "C" {

void sset(float, float, float, strumq*);
void randfill(float, int, strumq*);
void filefill(float, int, strumq*);
float strum(float, strumq*);

}

VMSTART::VMSTART() : Instrument()
{

in = NULL;

}

VMSTART::~VMSTART()
{

if (deleteflag == 1) {

delete strumq1;

}

}

// p0 = start; p1 = dur; p2 = pitch (oct.pc); p3 = fundamental decay time
// p4 = nyquist decay time; p5 = amp, p6 = squish; p7 = stereo spread [optional]
// p8 = flag for deleting pluck arrays (used by FRET, BEND, etc.) [optional]
// p9 = flag to re-use random values

int VMSTART::init(float p[], int n_args)
{

int squish;
float outskip, dur, pitch, fdecay, nydecay, amp, freq;

rtsetinput(0, this);

outskip = p[0];
dur = p[1];
pitch = p[2];
fdecay = p[3];
nydecay = p[4];
amp = p[5];
squish = (int)p[6];
spread = p[7];
deleteflag = (int)p[8];
reuse = (int)p[9];

rtsetoutput(outskip, dur, this);

strumq1 = new strumq;
curstrumq[0] = strumq1;
freq = cpspch(pitch);
sset(freq, fdecay, nydecay, strumq1);
if(reuse){

filefill(amp, squish, strumq1);
}
else
randfill(amp, squish, strumq1);

amptable = floc(1);
if (amptable) {

int amplen = fsize(1);
tableset(dur, amplen, amptabs);

}
else

advise("VMSTART", "Setting phrase curve to all 1's.");

skip = (int)(SR / (float)resetval);

return(nsamps);

}

int VMSTART::run()
{

int i, branch, rsamps;
float aamp, out[2];

if(in == NULL) /*first time, so allocate it*/

in = new float[RTBUFSAMPS * inputchans];

Instrument::run();

rsamps = chunksamps*inputchans;

rtgetin(in, this, rsamps);

aamp = 1.0; /* in case amptable == NULL */

branch = 0;
for (i = 0; i < rsamps; i+= inputchans) {

if (--branch < 0) {

if (amptable)

aamp = tablei(cursamp, amptable, amptabs);

branch = skip;

}
out[0] = strum(in[i]/aamp,strumq1) * aamp;

if (outputchans == 2) { /* split stereo files between the channels */

out[1] = (1.0 - spread) * out[0];
out[0] *= spread;

}
rtaddout(out);
cursamp++;

}
return i;

}

Instrument*
makeVMSTART()
{

VMSTART *inst;
inst = new VMSTART();
inst->set_bus_config("VMSTART");
return inst;

}