summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/demos/devmaster/lesson8/OggStreamer.java99
-rw-r--r--www/devmaster/lesson8.html47
2 files changed, 121 insertions, 25 deletions
diff --git a/src/java/demos/devmaster/lesson8/OggStreamer.java b/src/java/demos/devmaster/lesson8/OggStreamer.java
index 1f52973..a7b9b45 100644
--- a/src/java/demos/devmaster/lesson8/OggStreamer.java
+++ b/src/java/demos/devmaster/lesson8/OggStreamer.java
@@ -68,13 +68,23 @@ public class OggStreamer {
}
}
+ private static boolean debug = false;
+ private static int totalBytes = 0;
+
+ private static void debugMsg(String str) {
+ if (debug) System.err.println(str);
+ }
+
private OggDecoder oggDecoder;
// The size of a chunk from the stream that we want to read for each update.
- private static int BUFFER_SIZE = 4096*8;
+ private static int BUFFER_SIZE = 4096*16;
+
+ // The number of buffers used in the audio pipeline
+ private static int NUM_BUFFERS = 2;
- // Buffers hold sound data. There are two of them (front/back)
- private int[] buffers = new int[2];
+ // Buffers hold sound data. There are two of them by default (front/back)
+ private int[] buffers = new int[NUM_BUFFERS];
// Sources are points emitting sound.
private int[] source = new int[1];
@@ -89,6 +99,8 @@ public class OggStreamer {
private URL url;
+ private long sleepTime = 0;
+
/** Creates a new instance of OggStreamer */
public OggStreamer(URL url) {
this.url = url;
@@ -106,20 +118,35 @@ public class OggStreamer {
return false;
}
- if (oggDecoder.numChannels() == 1)
+ int numChannels = oggDecoder.numChannels();
+ int numBytesPerSample = 2;
+
+ if (numChannels == 1)
format = AL.AL_FORMAT_MONO16;
else
format = AL.AL_FORMAT_STEREO16;
rate = oggDecoder.sampleRate();
- System.err.println("format = 0x" + Integer.toString(format, 16));
+ // A rough estimation of how much time in milliseconds we can sleep
+ // before checking to see if the queued buffers have been played
+ // (so that we dont peg the CPU by doing an active wait). We divide
+ // by 10 at the end to be safe...
+ // round it off to the nearest multiple of 10.
+ sleepTime = (long)(1000.0 * BUFFER_SIZE /
+ numBytesPerSample / numChannels / rate / 10.0);
+ sleepTime = (sleepTime + 10)/10 * 10;
+
+ System.err.println("#Buffers: " + NUM_BUFFERS);
+ System.err.println("Buffer size: " + BUFFER_SIZE);
+ System.err.println("Format: 0x" + Integer.toString(format, 16));
+ System.err.println("Sleep time: " + sleepTime);
// TODO: I am not if this is the right way to fix the endian
// problems I am having... but this seems to fix it on Linux
oggDecoder.setSwap(true);
- al.alGenBuffers(2, buffers, 0); check();
+ al.alGenBuffers(NUM_BUFFERS, buffers, 0); check();
al.alGenSources(1, source, 0); check();
al.alSourcefv(source[0], AL.AL_POSITION , sourcePos, 0);
@@ -142,8 +169,9 @@ public class OggStreamer {
al.alSourceStop(source[0]);
empty();
- al.alDeleteSources(1, source, 0); check();
- al.alDeleteBuffers(2, buffers, 0); check();
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ al.alDeleteSources(i, source, 0); check();
+ }
}
/**
@@ -153,13 +181,14 @@ public class OggStreamer {
if (playing())
return true;
- if (!stream(buffers[0]))
- return false;
-
- if(!stream(buffers[1]))
- return false;
+ debugMsg("playback(): stream all buffers");
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ if (!stream(buffers[i]))
+ return false;
+ }
- al.alSourceQueueBuffers(source[0], 2, buffers, 0);
+ debugMsg("playback(): queue all buffers & play source");
+ al.alSourceQueueBuffers(source[0], NUM_BUFFERS, buffers, 0);
al.alSourcePlay(source[0]);
return true;
@@ -183,6 +212,7 @@ public class OggStreamer {
int[] processed = new int[1];
boolean active = true;
+ debugMsg("update()");
al.alGetSourcei(source[0], AL.AL_BUFFERS_PROCESSED, processed, 0);
while (processed[0] > 0)
@@ -190,9 +220,11 @@ public class OggStreamer {
int[] buffer = new int[1];
al.alSourceUnqueueBuffers(source[0], 1, buffer, 0); check();
+ debugMsg("update(): buffer unqueued => " + buffer[0]);
active = stream(buffer[0]);
+ debugMsg("update(): buffer queued => " + buffer[0]);
al.alSourceQueueBuffers(source[0], 1, buffer, 0); check();
processed[0]--;
@@ -216,6 +248,9 @@ public class OggStreamer {
return false;
}
+ totalBytes += size;
+ debugMsg("stream(): buffer data => " + buffer + " totalBytes:" + totalBytes);
+
ByteBuffer data = ByteBuffer.wrap(pcm, 0, size);
al.alBufferData(buffer, format, data, size, rate);
check();
@@ -265,6 +300,14 @@ public class OggStreamer {
return false;
while (update()) {
+ // We will try sleeping for sometime so that we dont
+ // peg the CPU...
+ try {
+ Thread.sleep(sleepTime);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
if (playing()) continue;
if (!playback())
@@ -284,12 +327,23 @@ public class OggStreamer {
URL url;
try {
- if (args.length == 0) {
- url = OggStreamer.class.getClassLoader().getResource("demos/data/broken_glass.ogg");
- (new OggStreamer(url)).playstream();
- }
-
+ boolean played = false;
for (int i = 0; i < args.length; i++) {
+ if ("-bs".equals(args[i])) {
+ BUFFER_SIZE = Integer.valueOf(args[++i]).intValue();
+ continue;
+ }
+
+ if ("-nb".equals(args[i])) {
+ NUM_BUFFERS = Integer.valueOf(args[++i]).intValue();
+ continue;
+ }
+
+ if ("-d".equals(args[i])) {
+ debug = true;
+ continue;
+ }
+
System.err.println("Playing Ogg stream : " + args[i]);
url = ((new File(args[i])).exists()) ?
@@ -297,8 +351,15 @@ public class OggStreamer {
if ((new OggStreamer(url)).playstream()) continue;
+ played = true;
System.err.println("ERROR!!");
}
+
+ if (!played) {
+ url = OggStreamer.class.getClassLoader().getResource("demos/data/broken_glass.ogg");
+ (new OggStreamer(url)).playstream();
+ }
+
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/www/devmaster/lesson8.html b/www/devmaster/lesson8.html
index 4d68908..a091df1 100644
--- a/www/devmaster/lesson8.html
+++ b/www/devmaster/lesson8.html
@@ -135,7 +135,13 @@ tutorial. <var>OggStreamer</var> which is the main class doing most of the worki
</p>
-<pre class="code"> // The size of a chunk from the stream that we want to read for each update.<br> private static int BUFFER_SIZE = 4096*8;<br></pre>
+<pre class="code">
+ // The size of a chunk from the stream that we want to read for each update.
+ private static int BUFFER_SIZE = 4096*8;
+
+ // The number of buffers used in the audio pipeline
+ private static int NUM_BUFFERS = 2;
+</pre>
@@ -170,8 +176,13 @@ just yet. I believe my comments should give you an idea of what they're for.</p>
-<pre class="code"> // Buffers hold sound data. There are two of them (front/back)<br> private int[] buffers = new int[2];<br> <br> // Sources are points emitting sound.<br> private int[] source = new int[1];<br> <br> private int format; // OpenAL data format<br> private int rate; // sample rate<br></pre>
-
+<pre class="code">
+ // Buffers hold sound data. There are two of them by default (front/back)
+ private int[] buffers = new int[NUM_BUFFERS];
+
+ // Sources are points emitting sound.
+ private int[] source = new int[1];
+</pre>
<p>First thing that I want to point out is that we have 2 buffers dedicated to
@@ -197,7 +208,7 @@ enumerator based on how many channels are in the Ogg and then make a not of the
-<pre class="code"> public boolean open() {<br> ...<br><br> al.alGenBuffers(2, buffers, 0); check();<br> al.alGenSources(1, source, 0); check();<br><br> al.alSourcefv(source[0], AL.AL_POSITION , sourcePos, 0);<br> al.alSourcefv(source[0], AL.AL_VELOCITY , sourceVel, 0);<br> al.alSourcefv(source[0], AL.AL_DIRECTION, sourceDir, 0);<br> <br> al.alSourcef(source[0], AL.AL_ROLLOFF_FACTOR, 0.0f );<br> al.alSourcei(source[0], AL.AL_SOURCE_RELATIVE, AL.AL_TRUE);<br><br> ...<br> }<br></pre>
+<pre class="code"> public boolean open() {<br> ...<br><br> al.alGenBuffers(NUM_BUFFERS, buffers, 0); check();<br> al.alGenSources(1, source, 0); check();<br><br> al.alSourcefv(source[0], AL.AL_POSITION , sourcePos, 0);<br> al.alSourcefv(source[0], AL.AL_VELOCITY , sourceVel, 0);<br> al.alSourcefv(source[0], AL.AL_DIRECTION, sourceDir, 0);<br> <br> al.alSourcef(source[0], AL.AL_ROLLOFF_FACTOR, 0.0f );<br> al.alSourcei(source[0], AL.AL_SOURCE_RELATIVE, AL.AL_TRUE);<br><br> ...<br> }<br></pre>
@@ -211,7 +222,16 @@ will still hear it. The same idea applies to source relativity.</p>
-<pre class="code"> public void release() {<br> al.alSourceStop(source[0]);<br> empty();<br><br> al.alDeleteSources(1, source, 0); check();<br> al.alDeleteBuffers(2, buffers, 0); check();<br> }<br></pre>
+<pre class="code">
+ public void release() {
+ al.alSourceStop(source[0]);
+ empty();
+
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ al.alDeleteSources(i, source, 0); check();
+ }
+ }
+</pre>
<p>We can clean up after ourselves using this. We stop the source, empty out any
@@ -219,7 +239,22 @@ buffers that are still in the queue, and destroy our objects.
</p>
-<pre class="code"> public boolean playback() {<br> if (playing())<br> return true;<br> <br> if (!stream(buffers[0]))<br> return false;<br> <br> if(!stream(buffers[1]))<br> return false;<br> <br> al.alSourceQueueBuffers(source[0], 2, buffers, 0);<br> al.alSourcePlay(source[0]);<br> <br> return true;<br> }<br></pre>
+<pre class="code">
+ public boolean playback() {
+ if (playing())
+ return true;
+
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ if (!stream(buffers[i]))
+ return false;
+ }
+
+ al.alSourceQueueBuffers(source[0], NUM_BUFFERS, buffers, 0);
+ al.alSourcePlay(source[0]);
+
+ return true;
+ }
+</pre>