188 lines
6.3 KiB
Java
188 lines
6.3 KiB
Java
package old;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
|
|
import javazoom.jl.decoder.Bitstream;
|
|
import javazoom.jl.decoder.BitstreamException;
|
|
import sound.util.Utils;
|
|
import base.exception.worker.ActivateException;
|
|
import base.exception.worker.DeactivateException;
|
|
import base.work.Work;
|
|
|
|
import com.Ostermiller.util.CircularByteBuffer;
|
|
|
|
public class Converter extends Work {
|
|
public static final String COMMAND = "lame --mp3input --cbr %s - - --quiet";
|
|
public static final int BYTES = 4096; // bytes
|
|
public static final int BUFFER = 30000; // milliseconds
|
|
public static final int BUFFERING = 1000; // milliseconds
|
|
|
|
protected int targetRate;
|
|
protected int rate;
|
|
protected int buffer;
|
|
protected boolean convert;
|
|
|
|
protected Process process;
|
|
protected InputStream sourceInputStream, processInputStream, inputStream;
|
|
protected OutputStream processOutputStream;
|
|
protected CircularByteBuffer circularByteBuffer;
|
|
protected BufferWorker bufferWorker;
|
|
|
|
public Converter(InputStream inputStream) {
|
|
this(inputStream, -1);
|
|
}
|
|
|
|
public Converter(InputStream inputStream, int targetRate) {
|
|
super();
|
|
this.sourceInputStream = inputStream;
|
|
this.targetRate = targetRate;
|
|
bufferWorker = new BufferWorker();
|
|
convert = false;
|
|
}
|
|
|
|
public void exit() {
|
|
super.exit();
|
|
bufferWorker.exit();
|
|
}
|
|
|
|
public synchronized void activate() throws ActivateException {
|
|
/* Read bitrate */
|
|
BufferedInputStream bufferedInputStream = new BufferedInputStream(sourceInputStream);
|
|
Bitstream bitStream = new Bitstream(bufferedInputStream);
|
|
try {
|
|
rate = bitStream.readFrame().bitrate() / 1000;
|
|
buffer = BUFFER * rate / 8;
|
|
} catch (BitstreamException e) {
|
|
logger.error("", e);
|
|
throw new ActivateException();
|
|
}
|
|
|
|
/* Check for need to convert */
|
|
if (targetRate < 0 || rate == targetRate) {
|
|
logger.debug("No conversion required");
|
|
inputStream = sourceInputStream;
|
|
} else {
|
|
logger.debug("Converting from " + rate + "kbps to " + targetRate + "kbps");
|
|
try {
|
|
String command = String.format(COMMAND, rate > targetRate ? "-B " + targetRate : "-F -b " + targetRate);
|
|
logger.debug("Starting process: " + command);
|
|
process = Runtime.getRuntime().exec(command);
|
|
processInputStream = process.getInputStream();
|
|
processOutputStream = process.getOutputStream();
|
|
|
|
/* Buffer output */
|
|
circularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
|
|
inputStream = circularByteBuffer.getInputStream();
|
|
bufferWorker.start();
|
|
convert = true;
|
|
} catch (IOException e) {
|
|
logger.error("", e);
|
|
throw new ActivateException();
|
|
}
|
|
}
|
|
super.activate();
|
|
notifyAll();
|
|
}
|
|
|
|
public void deactivate() throws DeactivateException {
|
|
super.deactivate();
|
|
try {
|
|
sourceInputStream.close();
|
|
bufferWorker.stop();
|
|
if (convert) {
|
|
circularByteBuffer.clear();
|
|
convert = false;
|
|
}
|
|
inputStream.close();
|
|
} catch (IOException e) {
|
|
logger.error("", e);
|
|
throw new DeactivateException();
|
|
}
|
|
}
|
|
|
|
public void work() {
|
|
if (!convert) {
|
|
try {
|
|
synchronized (this) {
|
|
wait();
|
|
}
|
|
} catch (InterruptedException e) {
|
|
logger.error("", e);
|
|
}
|
|
return;
|
|
}
|
|
byte[] bytes = new byte[BYTES];
|
|
int read = 0;
|
|
try {
|
|
logger.debug("Writing input to process");
|
|
// Should be interrupted by stop()/exit()
|
|
while ((read = sourceInputStream.read(bytes)) > 0) {
|
|
/* Limit buffer size */
|
|
while (inputStream.available() > buffer) {
|
|
int progress = (int) ((1 - (inputStream.available() - buffer) / (float) buffer) * 100);
|
|
logger.trace("Waiting for buffer to empty: " + progress + "%");
|
|
sleep(BUFFERING);
|
|
}
|
|
processOutputStream.write(bytes, 0, read);
|
|
}
|
|
processOutputStream.close();
|
|
logger.debug("Stopped writing input to process");
|
|
process.waitFor();
|
|
logger.debug("Process finished");
|
|
} catch (IOException e) {
|
|
} catch (InterruptedException e) {
|
|
logger.error("", e);
|
|
}
|
|
stop();
|
|
}
|
|
|
|
public synchronized InputStream getInputStream() {
|
|
if (!active()) {
|
|
start();
|
|
try {
|
|
wait();
|
|
} catch (InterruptedException e) {
|
|
logger.error("", e);
|
|
}
|
|
}
|
|
return inputStream;
|
|
}
|
|
|
|
public synchronized void setInputStream(InputStream inputStream) {
|
|
this.inputStream = inputStream;
|
|
}
|
|
|
|
class BufferWorker extends Work {
|
|
public void work() {
|
|
byte[] bytes = new byte[BYTES];
|
|
int read = 0;
|
|
try {
|
|
OutputStream bufferOutputStream = circularByteBuffer.getOutputStream();
|
|
logger.debug("Start buffering process output");
|
|
while ((read = processInputStream.read(bytes, 0, BYTES)) > 0) {
|
|
bufferOutputStream.write(bytes, 0, read);
|
|
}
|
|
logger.debug("Finished buffering process output");
|
|
bufferOutputStream.close();
|
|
} catch (IOException e) {}
|
|
stop();
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
Mp3 mp3 = new Mp3(new File("stream.mp3"), 128);
|
|
InputStream inputStream = mp3.getInputStream();
|
|
|
|
/* Play */
|
|
//Utils.play(inputStream);
|
|
|
|
/* Write to file */
|
|
Utils.write(inputStream, new File("output.mp3"));
|
|
mp3.exit();
|
|
}
|
|
}
|