1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| public class JVstAudioThread implements Runnable {
private JVstHost2 vst;
private final float[][] fInputs;
private final float[][] fOutputs;
private final byte[] bOutput;
private int blockSize;
private int numOutputs;
private int numAudioOutputs;
private AudioFormat audioFormat;
private SourceDataLine sourceDataLine;
private static final float ShortMaxValueAsFloat = (float) Short.MAX_VALUE;
public JVstAudioThread(JVstHost2 vst) {
this.vst = vst;
numOutputs = vst.numOutputs();
numAudioOutputs = Math.min(2, numOutputs); // because most machines do not offer more than 2 output channels
blockSize = vst.getBlockSize();
fInputs = new float[vst.numInputs()][blockSize];
fOutputs = new float[numOutputs][blockSize];
bOutput = new byte[numAudioOutputs * blockSize * 2];
audioFormat = new AudioFormat((int) vst.getSampleRate(), 16, numAudioOutputs, true, false);
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
sourceDataLine = null;
try {
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat, bOutput.length);
sourceDataLine.start();
} catch (LineUnavailableException lue) {
lue.printStackTrace(System.err);
System.exit(1);
}
}
@Override
protected void finalize() throws Throwable {
try {
// close the sourceDataLine properly when this object is garbage collected
sourceDataLine.drain();
sourceDataLine.close();
} finally {
super.finalize();
}
}
/**
* Converts a float audio array [-1,1] to an interleaved array of 16-bit samples
* in little-endian (low-byte, high-byte) format.
*/
private byte[] floatsToBytes(float[][] fData, byte[] bData) {
int index = 0;
for (int i = 0; i < blockSize; i++) {
for (int j = 0; j < numAudioOutputs; j++) {
short sval = (short) (fData[j][i] * ShortMaxValueAsFloat);
bData[index++] = (byte) (sval & 0x00FF);
bData[index++] = (byte) ((sval & 0xFF00) >> 8);
}
}
return bData;
}
public void run() {
while (true) {
vst.processReplacing(fInputs, fOutputs, blockSize);
sourceDataLine.write(floatsToBytes(fOutputs, bOutput), 0, bOutput.length);
}
}
} |