/**
*
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*
*/
package org.puredata.android.io;
import java.io.IOException;
import java.util.Arrays;
import org.puredata.core.PdBase;
import android.content.Context;
/**
*
* PdAudio manages an instance of {@link AudioWrapper} that uses Pure Data for audio processing.
*
* @author Peter Brinkmann (peter.brinkmann@gmail.com)
*
*/
public class PdAudio {
private static AudioWrapper audioWrapper = null;
private PdAudio() {
// Do nothing; we just don't want instances of this class.
}
/**
* initialize Pure Data as well as {@link AudioWrapper} instance
*
* @param sampleRate
* @param inChannels number of input channels
* @param outChannels number of output channels
* @param ticksPerBuffer number of Pure Data ticks (i.e., blocks of 64 samples) per buffer; choose 1 for minimal latency,
* or more if performance is a concern
* @param restart flag indicating whether the audio thread should be stopped if it is currently running
* @throws IOException if the audio parameters are not supported by the device
*/
public synchronized static void initAudio(int sampleRate, int inChannels, int outChannels, final int ticksPerBuffer, boolean restart)
throws IOException {
if (isRunning() && !restart) return;
if (!AudioParameters.checkParameters(sampleRate, inChannels, outChannels) || ticksPerBuffer <= 0) {
throw new IOException("bad audio parameters: " + sampleRate + ", " + inChannels + ", " + outChannels + ", " + ticksPerBuffer);
}
stopAudio();
PdBase.openAudio(inChannels, outChannels, sampleRate);
int bufferSizePerChannel = ticksPerBuffer * PdBase.blockSize();
audioWrapper = new AudioWrapper(sampleRate, inChannels, outChannels, bufferSizePerChannel) {
@Override
protected int process(short[] inBuffer, short[] outBuffer) {
Arrays.fill(outBuffer, (short) 0);
return PdBase.process(ticksPerBuffer, inBuffer, outBuffer);
}
};
}
/**
* Start audio wrapper
*
* @param context current application context
*/
public synchronized static void startAudio(Context context) {
if (audioWrapper == null) {
throw new IllegalStateException("audio not initialized");
}
PdBase.computeAudio(true);
audioWrapper.start(context);
}
/**
* Stop audio wrapper
*/
public synchronized static void stopAudio() {
if (!isRunning()) return;
audioWrapper.stop();
}
/**
* @return true if and only if the audio wrapper is running
*/
public synchronized static boolean isRunning() {
return audioWrapper != null && audioWrapper.isRunning();
}
/**
* @return the audio session ID, for Gingerbread and later; will throw an exception on older versions
*/
public synchronized static int getAudioSessionId() {
if (audioWrapper == null) {
throw new IllegalStateException("audio not initialized");
}
return audioWrapper.getAudioSessionId();
}
/**
* Release resources held by audio wrapper
*/
public synchronized static void release() {
if (audioWrapper == null) return;
audioWrapper.release();
audioWrapper = null;
}
}