package com.jssrc.resample;
import vavi.sound.pcm.resampling.ssrc.SSRC;
import vavi.util.I0Bessel;
import vavi.util.SplitRadixFft;
import javax.sound.sampled.AudioFormat;
import java.io.*;
/**
* @version 1.0 3/25/11 2:38 PM
* @author: Maksim Khadkevich
*/
public class JSSRCResampler extends InputStream {
protected AudioFormat inAudioFormat;
protected AudioFormat outAudioFormat;
protected InputStream ssrcInputStream;
protected DataOutputStream dataOutputStream;
protected DataInputStream dataInputStream;
protected PipedInputStream pipedInputStream;
protected PipedOutputStream pipedOutputStream;
protected Runnable resamplingRunnable;
protected Thread resamplingThread;
protected ByteArrayInputStream byteArrayInputStream;
public JSSRCResampler(AudioFormat inAudioFormat, AudioFormat outAudioFormat, InputStream inputStream) {
this.inAudioFormat = inAudioFormat;
this.outAudioFormat = outAudioFormat;
this.ssrcInputStream = inputStream;
initialize();
}
protected void initialize() {
if (outAudioFormat.getSampleRate() == inAudioFormat.getSampleRate()) {
System.out.println("No sample rate conversion is needed");
return;
}
initializeClasses();
try {
pipedInputStream = new PipedInputStream();
dataInputStream = new DataInputStream(new BufferedInputStream(pipedInputStream));
pipedOutputStream = new PipedOutputStream(pipedInputStream);
dataOutputStream = new DataOutputStream(pipedOutputStream);
ssrcInputStream = new BufferedInputStream(ssrcInputStream);
resamplingRunnable = new Runnable() {
public void run() {
try {
new SSRC(ssrcInputStream, dataOutputStream, (int) inAudioFormat.getSampleRate(), (int) outAudioFormat.getSampleRate(),
inAudioFormat.getFrameSize() / inAudioFormat.getChannels(),
inAudioFormat.getFrameSize() / inAudioFormat.getChannels(),
inAudioFormat.getChannels(), Integer.MAX_VALUE, 0, 0, true);
} catch (IOException e) {
e.printStackTrace();
}
}
};
resamplingThread = new Thread(resamplingRunnable);
resamplingThread.start();
this.byteArrayInputStream = new ByteArrayInputStream(new byte[0]);
} catch (IOException e) {
e.printStackTrace();
}
}
private void initializeClasses(){
try {
Class.forName(SSRC.class.getName());
Class.forName(I0Bessel.class.getName());
Class.forName(SplitRadixFft.class.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public int read() throws IOException {
if (byteArrayInputStream.available() <= 0) {
fillByteArrayInputStream();
}
return byteArrayInputStream.read();
}
protected int fillByteArrayInputStream() throws IOException {
int bytesRead;
byte[] newData = new byte[65536];
if (resamplingThread.isAlive()) {
bytesRead = dataInputStream.read(newData);
} else {
return -1;
}
if (bytesRead <= 0) {
return -1;
} else {
byteArrayInputStream = new ByteArrayInputStream(newData, 0, bytesRead);
return bytesRead;
}
}
public void close() throws IOException {
if (resamplingThread.isAlive()) {
resamplingThread.stop();
}
pipedInputStream.close();
pipedOutputStream.close();
}
@Override
public int available() throws IOException {
if (byteArrayInputStream.available() > 0) {
return byteArrayInputStream.available();
}
int filledBytes = fillByteArrayInputStream();
if (filledBytes > 0) {
return filledBytes;
} else {
return -1;
}
}
}