package net.pms.util;
import java.io.IOException;
import java.io.OutputStream;
public class PCMAudioOutputStream extends FlowParserOutputStream {
protected int nbchannels;
protected int sampleFrequency;
protected int bitsperSample;
protected int blocksize;
protected byte payload[];
protected boolean wavMode; // WAVEform (RIFF) output mode not used at the moment
protected boolean headerSent;
public PCMAudioOutputStream(OutputStream source, int nbchannels, int sampleFrequency, int bitsperSample) {
super(source, 600000);
this.nbchannels = nbchannels;
this.sampleFrequency = sampleFrequency;
this.bitsperSample = bitsperSample;
swapOrderBits = 2; // swap endian
init();
}
protected void init() {
if (!wavMode) {
blocksize = (2 * ((nbchannels + 1) / 2)) * sampleFrequency * bitsperSample / 1600;
payload = new byte[4];
switch (nbchannels) {
case 1:
payload[2] = 17;
break;
case 2:
payload[2] = 49;
break;
case 3:
payload[2] = 65;
break;
case 4:
payload[2] = 113;
break;
case 5:
payload[2] = -127;
break;
case 6:
payload[2] = -111;
break;
case 7:
payload[2] = -95;
break;
case 8:
payload[2] = -79;
break;
default:
break;
}
payload[0] = (byte) ((blocksize >> 8) & 0xff);
payload[1] = (byte) ((blocksize + 256) % 256);
if (sampleFrequency == 96000) {
payload[2] = (byte) (payload[2] + 3);
}
if (sampleFrequency == 192000) {
payload[2] = (byte) (payload[2] + 4);
}
payload[3] = (byte) (16 * (bitsperSample - 12));
} else {
// http://fr.wikipedia.org/wiki/WAVEform_audio_format#En-t.C3.AAte_de_fichier_WAV
int BytePerBloc = nbchannels * bitsperSample / 8;
int BytePerSec = sampleFrequency * BytePerBloc;
payload = new byte [44];
payload[0] = 82; // "RIFF"
payload[1] = 73;
payload[2] = 70;
payload[3] = 70;
payload[8] = 87; // "WAVEfmt "
payload[9] = 65;
payload[10] = 86;
payload[11] = 69;
payload[12] = 102;
payload[13] = 109;
payload[14] = 116;
payload[15] = 32;
payload[16] = 16; // BlocSize
payload[20] = 1; // AudioFormat: 1 = PCM
payload[22] = (byte) nbchannels; // Nb channels
payload[25] = (byte)(sampleFrequency & 0xff); // frequency
payload[24] = (byte)((sampleFrequency >> 8) & 0xff);
payload[30] = (byte)(BytePerSec & 0xff); // BytePerSec
payload[29] = (byte)((BytePerSec >> 8) & 0xff);
payload[32] = (byte)(BytePerBloc & 0xff); //BytePerBloc
payload[34] = (byte)(bitsperSample & 0xff); // bits per sample
payload[36] = 100; // "data"
payload[37] = 97;
payload[38] = 116;
payload[39] = 97;
payload[40] = -1;
payload[41] = -1;
payload[42] = -1;
payload[43] = -1;
}
}
@Override
protected void afterChunkSend() throws IOException {
}
@Override
protected void analyzeBuffer(byte[] data, int off, int len) {
streamableByteNumber = blocksize;
}
@Override
protected void beforeChunkSend() throws IOException {
if (!wavMode) {
writePayload(payload);
} else if (!headerSent) {
writePayload(payload);
headerSent = true;
}
}
}