/*
* 21.04.2004 Original verion. davagin@udm.ru.
*-----------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------
*/
package davaguine.jmac.tools;
import davaguine.jmac.info.SpecialFrame;
import davaguine.jmac.info.WaveFormat;
/**
* Author: Dmitry Vaguine
* Date: 04.03.2004
* Time: 14:51:31
*/
public class Prepare {
public void prepare(ByteArrayReader pRawData, int nBytes, final WaveFormat pWaveFormatEx, int[] pOutputX, int[] pOutputY, Crc32 pCRC, IntegerPointer pSpecialCodes, IntegerPointer pPeakLevel) {
// initialize the pointers that got passed in
pCRC.init();
pSpecialCodes.value = 0;
// variables
int nTotalBlocks = nBytes / pWaveFormatEx.nBlockAlign;
int R, L;
// the prepare code
if (pWaveFormatEx.wBitsPerSample == 8) {
if (pWaveFormatEx.nChannels == 2) {
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
short b1 = pRawData.readUnsignedByte();
short b2 = pRawData.readUnsignedByte();
R = b1 - 128;
L = b2 - 128;
pCRC.append((byte) b1);
pCRC.append((byte) b2);
// check the peak
if (Math.abs(L) > pPeakLevel.value)
pPeakLevel.value = Math.abs(L);
if (Math.abs(R) > pPeakLevel.value)
pPeakLevel.value = Math.abs(R);
// convert to x,y
pOutputY[nBlockIndex] = L - R;
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
}
} else if (pWaveFormatEx.nChannels == 1) {
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
short b1 = pRawData.readUnsignedByte();
R = b1 - 128;
pCRC.append((byte) b1);
// check the peak
if (Math.abs(R) > pPeakLevel.value)
pPeakLevel.value = Math.abs(R);
// convert to x,y
pOutputX[nBlockIndex] = R;
}
}
} else if (pWaveFormatEx.wBitsPerSample == 24) {
if (pWaveFormatEx.nChannels == 2) {
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
long nTemp = 0;
short b = pRawData.readUnsignedByte();
nTemp |= (b << 0);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 8);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 16);
pCRC.append((byte) b);
if ((nTemp & 0x800000) > 0)
R = (int) (nTemp & 0x7fffff) - 0x800000;
else
R = (int) (nTemp & 0x7fffff);
nTemp = 0;
b = pRawData.readUnsignedByte();
nTemp |= (b << 0);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 8);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 16);
pCRC.append((byte) b);
if ((nTemp & 0x800000) > 0)
L = (int) (nTemp & 0x7fffff) - 0x800000;
else
L = (int) (nTemp & 0x7fffff);
// check the peak
if (Math.abs(L) > pPeakLevel.value)
pPeakLevel.value = Math.abs(L);
if (Math.abs(R) > pPeakLevel.value)
pPeakLevel.value = Math.abs(R);
// convert to x,y
pOutputY[nBlockIndex] = L - R;
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
}
} else if (pWaveFormatEx.nChannels == 1) {
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
long nTemp = 0;
short b = pRawData.readUnsignedByte();
nTemp |= (b << 0);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 8);
pCRC.append((byte) b);
b = pRawData.readUnsignedByte();
nTemp |= (b << 16);
pCRC.append((byte) b);
if ((nTemp & 0x800000) > 0)
R = (int) (nTemp & 0x7fffff) - 0x800000;
else
R = (int) (nTemp & 0x7fffff);
// check the peak
if (Math.abs(R) > pPeakLevel.value)
pPeakLevel.value = Math.abs(R);
// convert to x,y
pOutputX[nBlockIndex] = R;
}
}
} else {
if (pWaveFormatEx.nChannels == 2) {
int LPeak = 0;
int RPeak = 0;
int nBlockIndex = 0;
for (nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
R = pRawData.readShort();
pCRC.append((short) R);
L = pRawData.readShort();
pCRC.append((short) L);
// check the peak
if (Math.abs(L) > LPeak)
LPeak = Math.abs(L);
if (Math.abs(R) > RPeak)
RPeak = Math.abs(R);
// convert to x,y
pOutputY[nBlockIndex] = L - R;
pOutputX[nBlockIndex] = R + (pOutputY[nBlockIndex] / 2);
}
if (LPeak == 0)
pSpecialCodes.value |= SpecialFrame.SPECIAL_FRAME_LEFT_SILENCE;
if (RPeak == 0)
pSpecialCodes.value |= SpecialFrame.SPECIAL_FRAME_RIGHT_SILENCE;
if (Math.max(LPeak, RPeak) > pPeakLevel.value)
pPeakLevel.value = Math.max(LPeak, RPeak);
// check for pseudo-stereo files
nBlockIndex = 0;
while (pOutputY[nBlockIndex++] == 0) {
if (nBlockIndex == (nBytes / 4)) {
pSpecialCodes.value |= SpecialFrame.SPECIAL_FRAME_PSEUDO_STEREO;
break;
}
}
} else if (pWaveFormatEx.nChannels == 1) {
int nPeak = 0;
for (int nBlockIndex = 0; nBlockIndex < nTotalBlocks; nBlockIndex++) {
R = pRawData.readUnsignedShort();
pCRC.append((short) R);
// check the peak
if (Math.abs(R) > nPeak)
nPeak = Math.abs(R);
//convert to x,y
pOutputX[nBlockIndex] = R;
}
if (nPeak > pPeakLevel.value)
pPeakLevel.value = nPeak;
if (nPeak == 0)
pSpecialCodes.value |= SpecialFrame.SPECIAL_FRAME_MONO_SILENCE;
}
}
pCRC.prefinalizeCrc();
// add the special code
pCRC.finalizeCrc();
if (pSpecialCodes.value != 0)
pCRC.doSpecial();
}
public void unprepare(int X, int Y, final WaveFormat waveFormat, final ByteBuffer output, final Crc32 crc) {
// decompress and convert from (x,y) -> (l,r)
// sort of long and ugly.... sorry
int channels = waveFormat.nChannels;
int bitsPerSample = waveFormat.wBitsPerSample;
if (channels == 2) {
if (bitsPerSample == 16) {
// get the right and left values
short nR = (short) (X - (Y / 2));
short nL = (short) (nR + Y);
output.append(nR, nL);
crc.append(nR, nL);
} else if (bitsPerSample == 8) {
byte R = (byte) (X - (Y / 2) + 128);
byte L = (byte) (R + Y);
output.append(R, L);
crc.append(R, L);
} else if (bitsPerSample == 24) {
int RV = X - (Y / 2);
int LV = RV + Y;
if (RV < 0)
RV = (RV + 0x800000) | 0x800000;
if (LV < 0)
LV = (LV + 0x800000) | 0x800000;
output.append24(RV, LV);
crc.append24(RV, LV);
}
} else if (channels == 1) {
if (bitsPerSample == 16) {
output.append((short) X);
crc.append((short) X);
} else if (bitsPerSample == 8) {
byte R = (byte) (X + 128);
output.append(R);
crc.append(R);
} else if (bitsPerSample == 24) {
if (X < 0)
X = (X + 0x800000) | 0x800000;
output.append24(X);
crc.append24(X);
}
}
}
public void unprepareOld(int[] pInputX, int[] pInputY, int nBlocks, WaveFormat pWaveFormatEx, ByteBuffer output, Crc32 crc, int nFileVersion) {
//the CRC that will be figured during decompression
crc.init();
//decompress and convert from (x,y) -> (l,r)
//sort of int and ugly.... sorry
int channels = pWaveFormatEx.nChannels;
int bitsPerSample = pWaveFormatEx.wBitsPerSample;
if (channels == 2) {
//convert the x,y data to raw data
if (bitsPerSample == 16) {
short R;
int pX = 0;
int pY = 0;
for (; pX < nBlocks; pX++, pY++) {
R = (short) (pInputX[pX] - (pInputY[pY] / 2));
output.append(R);
crc.append(R);
R += pInputY[pY];
output.append(R);
crc.append(R);
}
} else if (bitsPerSample == 8) {
byte R;
if (nFileVersion > 3830) {
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
R = (byte) (pInputX[SampleIndex] - (pInputY[SampleIndex] / 2) + 128);
output.append(R);
crc.append(R);
R += pInputY[SampleIndex];
output.append(R);
crc.append(R);
}
} else {
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
R = (byte) (pInputX[SampleIndex] - (pInputY[SampleIndex] / 2));
output.append(R);
crc.append(R);
R += pInputY[SampleIndex];
output.append(R);
crc.append(R);
}
}
} else if (bitsPerSample == 24) {
int RV, LV;
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
RV = pInputX[SampleIndex] - (pInputY[SampleIndex] / 2);
LV = RV + pInputY[SampleIndex];
int nTemp = 0;
if (RV < 0)
nTemp = (RV + 0x800000) | 0x800000;
else
nTemp = RV;
output.append24(nTemp);
crc.append24(nTemp);
nTemp = 0;
if (LV < 0)
nTemp = (LV + 0x800000) | 0x800000;
else
nTemp = LV;
output.append24(nTemp);
crc.append24(nTemp);
}
}
} else if (channels == 1) {
//convert to raw data
if (bitsPerSample == 8) {
byte R;
if (nFileVersion > 3830) {
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
R = (byte) (pInputX[SampleIndex] + 128);
output.append(R);
crc.append(R);
}
} else {
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
R = (byte) (pInputX[SampleIndex]);
output.append(R);
crc.append(R);
}
}
} else if (bitsPerSample == 24) {
int RV;
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
RV = pInputX[SampleIndex];
int nTemp = 0;
if (RV < 0)
nTemp = (RV + 0x800000) | 0x800000;
else
nTemp = RV;
output.append24(nTemp);
crc.append24(nTemp);
}
} else {
short R;
for (int SampleIndex = 0; SampleIndex < nBlocks; SampleIndex++) {
R = (short) (pInputX[SampleIndex]);
output.append(R);
crc.append(R);
}
}
}
crc.prefinalizeCrc();
}
}