/*
* Copyright 2007 Sun Microsystems, Inc.
*
* This file is part of jVoiceBridge.
*
* jVoiceBridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation and distributed hereunder
* to you.
*
* jVoiceBridge 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, see <http://www.gnu.org/licenses/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied this
* code.
*/
package com.sun.voip;
import org.xiph.speex.*;
public class SpeexDecoder {
private org.xiph.speex.SpeexDecoder speexDecoder;
private int sampleRate;
private int channels;
private int decodes;
private long decodeTime;
private boolean bigEndian = true;
public SpeexDecoder(int sampleRate, int channels) throws SpeexException {
this.sampleRate = sampleRate;
this.channels = channels;
speexDecoder = new org.xiph.speex.SpeexDecoder();
int mode = 0;
String s = " Narrow Band";
if (sampleRate > 8000) {
s = " Wide Band";
mode++; // wide band
}
if (sampleRate > 16000) {
s = " Ultra-Wide Band";
mode++; // ultra wide band
}
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Initializing Speex Decoder using "
+ sampleRate + "/" + channels);
}
if (speexDecoder.init(mode, sampleRate, channels, true) == false) {
throw new SpeexException(
"Speex decoder initialization failed!");
}
try {
speexDecoder.setBigEndian(true);
} catch (Exception e) {
bigEndian = false;
}
}
/*
* Decode speex data starting at offset for length bytes.
* Return the length of the decoded data.
*/
boolean debug = false;
public int[] decodeToIntArray(byte[] data, int offset, int length)
throws SpeexException {
byte[] byteData = decodeToByteArray(data, offset, length);
return AudioConversion.bytesToInts(byteData);
}
public byte[] decodeToByteArray(byte[] data, int offset, int length)
throws SpeexException {
if (Logger.logLevel >= Logger.LOG_MOREDETAIL) {
Util.dump("decode input: offset " + offset
+ " length " + length, data, 0, offset + length);
}
long start = CurrentTime.getTime();
try {
speexDecoder.processData(data, offset, length);
} catch (java.io.StreamCorruptedException e) {
throw new SpeexException(e.getMessage());
}
int decodedLength = speexDecoder.getProcessedDataByteSize();
if (decodedLength <= 0) {
Logger.println("Speex decode data length is " + decodedLength);
throw new SpeexException("Decoded length negative");
}
byte[] byteData = new byte[decodedLength];
speexDecoder.getProcessedData(byteData, 0);
if (bigEndian == false) {
/*
* The latest version of Speex only understands little endian
*/
for (int i = 0; i < byteData.length; i += 2) {
byte b = byteData[i];
byteData[i] = byteData[i + 1];
byteData[i + 1] = b;
}
}
decodes++;
decodeTime += (CurrentTime.getTime() - start);
return byteData;
}
public int getDecodes() {
return decodes;
}
public long getDecodeTime() {
return decodeTime;
}
public void resetStatistics() {
decodes = 0;
decodeTime = 0;
}
}