blob: cfae3f9f05b10d735dc08ced14dfb2bd2a8824cb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Daisuke SATO - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.ai.audio.io.impl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import org.eclipse.actf.ai.audio.io.AudioIOException;
import org.eclipse.actf.ai.audio.io.AudioPipeListener;
import org.eclipse.actf.ai.audio.io.AudioUtil;
import org.eclipse.actf.ai.audio.io.IAudioPipe;
import org.eclipse.actf.ai.audio.io.IAudioReader;
import org.eclipse.actf.ai.audio.io.IAudioWriter;
public class AudioPipe implements IAudioPipe {
private IAudioReader reader;
private IAudioWriter writer;
private AudioFormat format;
private Thread thread;
private Runnable runner;
private byte[] buffer;
private int bufferSize;
private int interval = 100;
private int priority = Thread.NORM_PRIORITY;
private int bufferSizeInMs = 1000;
private boolean active;
private boolean waiting;
private boolean stopFlag = false;
private boolean stopFlag2 = false;
private ArrayList<AudioPipeListener> listeners = new ArrayList<AudioPipeListener>();
public AudioPipe(IAudioReader reader, IAudioWriter writer) {
this.reader = reader;
this.writer = writer;
runner = new ReaderWriterRunner();
}
public void addAudioPipeListener(AudioPipeListener listener) {
listeners.add(listener);
}
class ReaderWriterRunner implements Runnable {
private void fadeout(byte[] buffer, int nBytesRead) {
int bps = AudioUtil.getBytesPerSample(format);
ByteBuffer bb = ByteBuffer.wrap(buffer);
ShortBuffer sb = null;
if (format.isBigEndian())
bb.order(ByteOrder.BIG_ENDIAN);
else
bb.order(ByteOrder.LITTLE_ENDIAN);
if (bps == 2)
sb = bb.asShortBuffer();
int len = nBytesRead / bps;
for (int i = 0; i < len; i++) {
double k = (double) (len - i) / (double) len;
if (bps == 1)
bb.put(i, (byte) (bb.get(i) * k));
else
sb.put(i, (short) (sb.get(i) * k));
}
}
public void run() {
try {
while (true) {
if (reader.isClosed())
break;
int nBytesRead = reader.read(buffer, 0, buffer.length);
int nBytesWritten = 0;
do {
if (writer.isClosed()) {
active = false;
fireStopped();
return;
}
if (stopFlag) {
fadeout(buffer, nBytesRead);
stopFlag = false;
stopFlag2 = true;
}
int temp = writer.write(buffer, nBytesWritten,
nBytesRead);
nBytesWritten += temp;
nBytesRead -= temp;
sleep();
} while (nBytesRead > 0);
if (stopFlag2) {
stopFlag2 = false;
writer.close();
}
}
writer.close();
} catch (AudioIOException e) {
writer.close();
} catch (Exception e) {
e.printStackTrace();
writer.close();
}
active = false;
fireFinished();
}
}
private void fireFinished() {
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).finished(this);
}
}
private void fireStopped() {
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).stopped(this);
}
}
synchronized public void setInterval(int interval) {
this.interval = interval;
}
synchronized public void setPriority(int priority) {
this.priority = priority;
if (thread != null)
thread.setPriority(priority);
}
public void prepare() {
try {
reader.open();
format = reader.getAudioFormat();
writer.open(format);
} catch (AudioIOException e) {
e.printStackTrace();
return;
}
}
public void start() {
start(0);
}
public void start(final int delay) {
if (active || waiting)
return;
waiting = true;
thread = new Thread(new Runnable() {
public void run() {
long s = (new Date()).getTime();
while (true) {
long n = (new Date()).getTime();
if (stopFlag) {
waiting = false;
stopFlag = false;
active = false;
fireStopped();
return;
}
if (s + delay <= n) {
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
while (active) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
prepare();
int Bps = AudioUtil.getBytesPerSampleLR(format);
bufferSize = AudioUtil.getBytesPerSecondLR(format)
* bufferSizeInMs / 1000 / Bps * Bps;
buffer = new byte[bufferSize];
active = true;
waiting = false;
runner.run();
}
});
thread.setPriority(priority);
thread.setName(reader.getName() + "<->" + writer.getName());
thread.start();
}
synchronized private void sleep() {
try {
Thread.sleep(interval);
Thread.yield();
} catch (InterruptedException e) {
}
}
public boolean isActive() {
return active;
}
public void stop() {
if (active || waiting)
stopFlag = true;
}
public void join() {
if (thread == null)
return;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setBufferSize(int miliSeconds) {
bufferSizeInMs = miliSeconds;
}
}