aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java')
-rwxr-xr-xsrc/jogl/classes/com/jogamp/audio/windows/waveout/Track.java206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
new file mode 100755
index 000000000..b57bf1dc6
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.audio.windows.waveout;
+
+import java.io.*;
+import java.nio.*;
+
+public class Track {
+ // Default number of samples per buffer
+ private static final int BUFFER_SIZE = 32768;
+ // Number of bytes per sample (FIXME: dependence on audio format)
+ static final int BYTES_PER_SAMPLE = 2;
+ // Whether we need byte swapping (FIXME: dependence on audio format)
+ static final boolean NEEDS_BYTE_SWAP = true;
+
+ // This is the buffer this track is currently playing from
+ private SoundBuffer activeBuffer;
+ // This is the sample position in the active buffer
+ private int samplePosition;
+ // This is the total number of samples in the file
+ private int totalSamples;
+ // This is the total number of samples we have read
+ private int samplesRead;
+ // This is the buffer that the background filler thread may be filling
+ private SoundBuffer fillingBuffer;
+ // If we're playing the file, this is its input stream
+ private InputStream input;
+ // Keep around the file name
+ private File file;
+ // Whether we're playing this sound
+ private boolean playing;
+ // Whether we're looping this sound
+ private boolean looping;
+ // The position of this sound; defaults to being at the origin
+ private volatile Vec3f position = new Vec3f();
+
+ Track(File file) throws IOException {
+ if (!file.getName().endsWith(".rawsound")) {
+ throw new IOException("Unsupported file format (currently supports only raw sounds)");
+ }
+
+ this.file = file;
+ openInput();
+
+ // Allocate the buffers
+ activeBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP);
+ fillingBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP);
+
+ // Fill the first buffer immediately
+ fill();
+ swapBuffers();
+ }
+
+ private void openInput() throws IOException {
+ input = new BufferedInputStream(new FileInputStream(file));
+ totalSamples = (int) file.length() / BYTES_PER_SAMPLE;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public synchronized void play() {
+ if (input == null) {
+ try {
+ openInput();
+ // Fill it immediately
+ fill();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ playing = true;
+ }
+
+ public synchronized boolean isPlaying() {
+ return playing;
+ }
+
+ public synchronized void setLooping(boolean looping) {
+ this.looping = looping;
+ }
+
+ public synchronized boolean isLooping() {
+ return looping;
+ }
+
+ public void setPosition(float x, float y, float z) {
+ position = new Vec3f(x, y, z);
+ }
+
+ synchronized void fill() throws IOException {
+ if (input == null) {
+ return;
+ }
+ SoundBuffer curBuffer = fillingBuffer;
+ if (!curBuffer.empty()) {
+ return;
+ }
+ curBuffer.fill(input);
+ if (curBuffer.empty()) {
+ // End of file
+ InputStream tmp = null;
+ synchronized(this) {
+ tmp = input;
+ input = null;
+ }
+ tmp.close();
+
+ // If looping, re-open
+ if (isLooping()) {
+ openInput();
+ // and fill
+ fill();
+ }
+ }
+ }
+
+ // These are only for use by the Mixer
+ private float leftGain;
+ private float rightGain;
+
+ void setLeftGain(float leftGain) {
+ this.leftGain = leftGain;
+ }
+
+ float getLeftGain() {
+ return leftGain;
+ }
+
+ void setRightGain(float rightGain) {
+ this.rightGain = rightGain;
+ }
+
+ float getRightGain() {
+ return rightGain;
+ }
+
+ Vec3f getPosition() {
+ return position;
+ }
+
+ // This is called by the mixer and must be extremely fast
+ // Note this assumes mono sounds (FIXME)
+ boolean hasNextSample() {
+ return (!activeBuffer.empty() && samplePosition < activeBuffer.numSamples());
+ }
+
+ // This is called by the mixer and must be extremely fast
+ float nextSample() {
+ float res = activeBuffer.getSample(samplePosition++);
+ ++samplesRead;
+ if (!hasNextSample()) {
+ swapBuffers();
+ samplePosition = 0;
+ if (done()) {
+ playing = false;
+ }
+ }
+ return res;
+ }
+
+ synchronized void swapBuffers() {
+ SoundBuffer tmp = activeBuffer;
+ activeBuffer = fillingBuffer;
+ fillingBuffer = tmp;
+ fillingBuffer.empty(true);
+ }
+
+ // This provides a more robust termination condition
+ boolean done() {
+ return (samplesRead == totalSamples) && !looping;
+ }
+}