package jass.generators;
import jass.engine.*;
import java.io.*;
/** Vibration model of object, capable of playing sound.
Extended to keep track of current excitation and capable of modes being turned
on/off.
@author Kees van den Doel (kvdoel@cs.ubc.ca)
*/
public class QuenchableModalObjectWithOneContact extends ModalObjectWithOneContact {
/** True for the modes that are on */
protected boolean[] onBit;
/** Create and initialize, but don't set any modal parameters.
@param srate sampling rate in Hertz.
@param nf number of modes.
@param np number of locations.
@param bufferSize Buffer size used for real-time rendering.
*/
public QuenchableModalObjectWithOneContact(float srate,int nf,int np,int bufferSize) {
super(srate,nf,np,bufferSize);
allocateonBit(nf);
}
/** Create and initialize with provided modal data.
@param m modal model to load.
@param srate sampling rate in Hertz.
@param bufferSize Buffer size used for real-time rendering.
*/
public QuenchableModalObjectWithOneContact(ModalModel m,float srate,int bufferSize) {
super(m,srate,bufferSize);
allocateonBit(m.nf);
}
/**
Allocate and turn on modes
*/
private void allocateonBit(int nf) {
onBit = new boolean[nf];
for(int i=0;i<nf;i++) {
onBit[i] = true;
}
}
/**
Turn mode on/off.
@param mode mode number
@param on true if turn on, fals if turn off
*/
public void setOnBit(int mode,boolean on) {
if(on) {
onBit[mode] = true;
} else {
if(onBit[mode]) {
onBit[mode] = false;
yt_1[mode] = yt_2[mode] = 0;
} // else was off already
}
}
/** Return current excitation of mode. Approximated as (y(t)^2 + (dy/dt)^2/(2pif)^2)/2).
A pulse excitation of strength x should produce excitation of (ax)^2/2, with "a"
gain of mode.
@param k mode number
@return excitation
*/
public float getModeExcitation(int k) {
double y2term = yt_1[k]*yt_1[k];
double dy2term = (yt_1[k] - yt_2[k])*srate/(6.2831853*modalModel.fscale*modalModel.f[k]);
dy2term *= dy2term;
return (float)((y2term + dy2term)/2);
}
/** Apply external force[] and compute response through bank of modal filters.
As in super class but skip off modes.
@param output user provided output buffer.
@param force input force.
@param nsamples number of samples to compute.
*/
protected void computeModalFilterBank(float[] output, float[] force, int nsamples) {
boolean isnul = true;
for(int k=0;k<nsamples;k++) {
output[k] = 0;
if(Math.abs(force[k])>=eps) {
isnul = false;
}
}
int nf = modalModel.nfUsed;
if(isnul) {
for(int i=0;i<nf;i++) {
if(Math.abs(yt_1[i]) >= eps || Math.abs(yt_2[i]) >= eps) {
isnul = false;
break;
}
}
}
if(isnul) {
return;
}
for(int i=0;i<nf;i++) {
if(onBit[i]) {
float tmp_twoRCosTheta = twoRCosTheta[i];
float tmp_R2 = R2[i];
float tmp_a = ampR[i];
float tmp_yt_1 = yt_1[i];
float tmp_yt_2 = yt_2[i];
for(int k=0;k<nsamples;k++) {
float ynew = tmp_twoRCosTheta * tmp_yt_1 -
tmp_R2 * tmp_yt_2 + tmp_a * force[k];
// commenting out the force[k] changes performance 650->718
tmp_yt_2 = tmp_yt_1;
tmp_yt_1 = ynew;
output[k] += ynew;
}
yt_1[i] = tmp_yt_1;
yt_2[i] = tmp_yt_2;
}
}
}
}