package jass.generators; import jass.engine.*; import java.net.*; /** A force model based on looping through a buffer, loaded from an audio file/url or provided by caller. @author Kees van den Doel (kvdoel@cs.ubc.ca) */ public class LoopBuffer extends Out { /** Buffer to loop */ protected float[] loopBuffer; /** Buffer length */ protected int loopBufferLength; /** Playback volume. */ protected float volume = 1; /** Loop speed through buffer in seconds per second. */ protected float speed = 1; /** Current fractional position [0 1] of pointer in buffer. */ protected float x = 0; /** Current integer position of pointer in buffer. */ protected int ix = 0; /** Current fractional speed [0 1] of pointer in buffer per sample. */ protected float dx; /** Current integer speed of pointer in buffer per sample. */ protected int dix; /** Sampling rate in Hertz of Out. */ public float srate; /** Sampling rate ratio, srateLoopBuffer/srate */ private float srateRatio = 1; /** Sampling rate in Hertz of loaded buffer. */ public float srateLoopBuffer; private String name = "x"; /** For derived classes @param bufferSize biffer size */ public LoopBuffer(int bufferSize) { super(bufferSize); // this is the internal buffer size } /** Construct loop force from named file. @param srate sampling rate in Hertz. @param bufferSize bufferSize of this Out @param fn Audio file name. */ public LoopBuffer(float srate,int bufferSize, String fn) { super(bufferSize); // this is the internal buffer size AudioFileBuffer afBuffer = new AudioFileBuffer(fn); loopBuffer = afBuffer.buf; loopBufferLength = loopBuffer.length; srateLoopBuffer = afBuffer.srate; this.srate = srate; srateRatio = srateLoopBuffer/srate; setSpeed(speed); this.name = fn; /* System.out.println(name); for(int i=0;i<loopBuffer.length;i++) { System.out.println(loopBuffer[i]); } */ } /** Construct loop force from named URL. @param srate sampling rate in Hertz. @param bufferSize bufferSize of this Out @param url Audio file url name. */ public LoopBuffer(float srate,int bufferSize, URL url) { super(bufferSize); // this is the internal buffer size AudioFileBuffer afBuffer = new AudioFileBuffer(url); loopBuffer = afBuffer.buf; loopBufferLength = loopBuffer.length; srateLoopBuffer = afBuffer.srate; this.srate = srate; srateRatio = srateLoopBuffer/srate; setSpeed(speed); this.name = url.toString(); } /** Construct loop force and provide buffer at same sampling rate. @param srate sampling rate in Hertz. @param bufferSize bufferSize of this Out. @param loopBuffer looping buffer. */ public LoopBuffer(float srate,int bufferSize, float[] loopBuffer) { super(bufferSize); // this is the internal buffer size this.loopBuffer = loopBuffer; srateLoopBuffer = this.srate = srate; loopBufferLength = loopBuffer.length; setSpeed(speed); } /** Get the loopbuffer as array. @return The containing loopbuffer */ public float[] getLoopBuffer() { return loopBuffer; } /** Set force magnitude. @param val Volume. */ public void setVolume(float val) { //System.out.println(name+" volume= "+val); volume = val; } /** Set loopspeed. @param speed Loop speed., 1 corresponding to original recorded speed. */ public void setSpeed(float speed) { this.speed = speed; float tmp = speed * srateRatio; dix = (int)tmp; dx = tmp - dix; } /** Get next sample value, interpolating in between sample points. */ protected float getNextSample() { ix += dix; x += dx; if(x > 1.f) { x -= 1.f; ix++; } while(ix >= loopBufferLength) { ix -= loopBufferLength; } int next_index; if(ix == loopBufferLength-1) { next_index = 0; } else { next_index = ix+1; } float val = (1.f - dx) * loopBuffer[ix] + dx * loopBuffer[next_index]; return (float)(val * volume); } /** Compute the next buffer. */ public void computeBuffer() { int bufsz = getBufferSize(); for(int k=0;k<bufsz;k++) { buf[k] = getNextSample(); } } }