aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2
diff options
context:
space:
mode:
Diffstat (limited to 'src/jake2')
-rw-r--r--src/jake2/sound/joal/Channel.java97
-rw-r--r--src/jake2/sound/joal/JOALSoundImpl.java80
2 files changed, 141 insertions, 36 deletions
diff --git a/src/jake2/sound/joal/Channel.java b/src/jake2/sound/joal/Channel.java
index 596a838..8a26587 100644
--- a/src/jake2/sound/joal/Channel.java
+++ b/src/jake2/sound/joal/Channel.java
@@ -3,7 +3,7 @@
*
* Copyright (C) 2003
*
- * $Id: Channel.java,v 1.4 2005-05-08 13:37:28 cawe Exp $
+ * $Id: Channel.java,v 1.5 2005-12-04 17:28:48 cawe Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.
@@ -30,13 +30,12 @@ import jake2.Defines;
import jake2.Globals;
import jake2.client.CL_ents;
import jake2.game.entity_state_t;
-import jake2.sound.sfx_t;
-import jake2.sound.sfxcache_t;
+import jake2.qcommon.Com;
+import jake2.sound.*;
import jake2.util.Math3D;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
+import java.nio.ByteBuffer;
+import java.util.*;
import net.java.games.joal.AL;
@@ -62,7 +61,11 @@ public class Channel {
private static boolean isInitialized = false;
private static int numChannels;
-
+
+ // stream handling
+ private static boolean streamingEnabled = false;
+ private static int streamQueue = 0;
+
// sound attributes
private int type;
private int entnum;
@@ -95,14 +98,14 @@ public class Channel {
active = false;
modified = false;
}
+
+ private static int[] tmp = new int[1];
- static int init(AL al, int[] buffers) {
+ static int init(AL al, int[] buffers) {
Channel.al = al;
Channel.buffers = buffers;
// create channels
int sourceId;
- int[] tmp = {0};
- int error;
for (int i = 0; i < MAX_CHANNELS; i++) {
al.alGenSources(1, tmp);
@@ -142,6 +145,80 @@ public class Channel {
numChannels = 0;
isInitialized = false;
}
+
+ static void enableStreaming() {
+ if (streamingEnabled) return;
+
+ // use the last source
+ numChannels--;
+ streamingEnabled = true;
+ streamQueue = 0;
+
+ int source = channels[numChannels].sourceId;
+ al.alSourcei (source, AL.AL_SOURCE_RELATIVE, AL.AL_TRUE);
+ al.alSourcef(source, AL.AL_GAIN, 1.0f);
+ channels[numChannels].volumeChanged = true;
+
+ Com.DPrintf("streaming enabled\n");
+ }
+
+ static void disableStreaming() {
+ if (!streamingEnabled) return;
+ unqueueStreams();
+ int source = channels[numChannels].sourceId;
+ al.alSourcei (source, AL.AL_SOURCE_ABSOLUTE, AL.AL_TRUE);
+
+ // free the last source
+ numChannels++;
+ streamingEnabled = false;
+ Com.DPrintf("streaming disabled\n");
+ }
+
+ static void unqueueStreams() {
+ if (!streamingEnabled) return;
+ int source = channels[numChannels].sourceId;
+
+ // stop streaming
+ al.alSourceStop(source);
+ int count = al.alGetSourcei(source, AL.AL_BUFFERS_QUEUED);
+ Com.DPrintf("unqueue " + count + " buffers\n");
+ while (count-- > 0) {
+ al.alSourceUnqueueBuffers(source, 1, tmp);
+ }
+ streamQueue = 0;
+ }
+
+ static void updateStream(ByteBuffer samples, int count, int format, int rate) {
+ enableStreaming();
+ int[] buffer = tmp;
+ int source = channels[numChannels].sourceId;
+ int processed = al.alGetSourcei(source, AL.AL_BUFFERS_PROCESSED);
+
+ boolean playing = (al.alGetSourcei(source, AL.AL_SOURCE_STATE) == AL.AL_PLAYING);
+ boolean interupted = !playing && streamQueue > 2;
+
+ if (interupted) {
+ unqueueStreams();
+ buffer[0] = buffers[Sound.MAX_SFX + streamQueue++];
+ Com.DPrintf("queue " + (streamQueue - 1) + '\n');
+ } else if (processed < 2) {
+ buffer[0] = buffers[Sound.MAX_SFX + streamQueue++];
+ Com.DPrintf("queue " + (streamQueue - 1) + '\n');
+ } else {
+ // reuse the buffer
+ al.alSourceUnqueueBuffers(source, 1, buffer);
+ }
+
+ samples.position(0);
+ samples.limit(count);
+ al.alBufferData(buffer[0], format, samples, count, rate);
+ al.alSourceQueueBuffers(source, 1, buffer);
+
+ if (streamQueue > 1 && !playing) {
+ Com.DPrintf("start sound\n");
+ al.alSourcePlay(source);
+ }
+ }
static void addPlaySounds() {
while (Channel.assign(PlaySound.nextPlayableSound()));
diff --git a/src/jake2/sound/joal/JOALSoundImpl.java b/src/jake2/sound/joal/JOALSoundImpl.java
index 1b6f722..0dff7ca 100644
--- a/src/jake2/sound/joal/JOALSoundImpl.java
+++ b/src/jake2/sound/joal/JOALSoundImpl.java
@@ -2,7 +2,7 @@
* JOALSoundImpl.java
* Copyright (C) 2004
*
- * $Id: JOALSoundImpl.java,v 1.13 2005-04-27 12:39:23 cawe Exp $
+ * $Id: JOALSoundImpl.java,v 1.14 2005-12-04 17:28:48 cawe Exp $
*/
package jake2.sound.joal;
@@ -14,9 +14,8 @@ import jake2.sound.*;
import jake2.util.Lib;
import jake2.util.Vargs;
-import java.awt.image.SampleModel;
import java.io.*;
-import java.nio.IntBuffer;
+import java.nio.*;
import net.java.games.joal.*;
import net.java.games.joal.eax.EAX;
@@ -37,8 +36,7 @@ public final class JOALSoundImpl implements Sound {
cvar_t s_volume;
- private static final int MAX_SFX = Defines.MAX_SOUNDS * 2;
- private int[] buffers = new int[MAX_SFX];
+ private int[] buffers = new int[MAX_SFX + STREAM_QUEUE];
// singleton
private JOALSoundImpl() {
@@ -154,7 +152,7 @@ public final class JOALSoundImpl implements Sound {
}
}
- private void initOpenALExtensions() throws OpenALException {
+ private void initOpenALExtensions() {
if (al.alIsExtensionPresent("EAX2.0")) {
Com.Printf("... using EAX2.0\n");
eax = EAXFactory.getEAX();
@@ -176,13 +174,19 @@ public final class JOALSoundImpl implements Sound {
alc.alcCloseDevice(curDevice);
}
- /* (non-Javadoc)
- * @see jake2.sound.SoundImpl#RegisterSound(jake2.sound.sfx_t)
- */
- private void initBuffer(byte[] samples, int bufferId, int freq) {
- al.alBufferData(buffers[bufferId], AL.AL_FORMAT_MONO16, samples,
- samples.length, freq);
- }
+ // TODO check the sfx direct buffer size
+ // 2MB sfx buffer
+ private ByteBuffer sfxDataBuffer = Lib.newByteBuffer(2 * 1024 * 1024);
+
+ /* (non-Javadoc)
+ * @see jake2.sound.SoundImpl#RegisterSound(jake2.sound.sfx_t)
+ */
+ private void initBuffer(byte[] samples, int bufferId, int freq) {
+ ByteBuffer data = sfxDataBuffer.slice();
+ data.put(samples).flip();
+ al.alBufferData(buffers[bufferId], AL.AL_FORMAT_MONO16,
+ data, data.limit(), freq);
+ }
private void checkError() {
Com.DPrintf("AL Error: " + alErrorString() +'\n');
@@ -344,7 +348,6 @@ public final class JOALSoundImpl implements Sound {
public void EndRegistration() {
int i;
sfx_t sfx;
- int size;
// free any sounds not from this registration sequence
for (i = 0; i < num_sfx; i++) {
@@ -531,12 +534,40 @@ public final class JOALSoundImpl implements Sound {
StartSound(null, Globals.cl.playernum + 1, 0, sfx, 1, 1, 0.0f);
}
- /* (non-Javadoc)
- * @see jake2.sound.Sound#RawSamples(int, int, int, int, byte[])
- */
- public void RawSamples(int samples, int rate, int width, int channels, byte[] data) {
- // TODO implement RawSamples
- }
+ private ShortBuffer streamBuffer = sfxDataBuffer.slice().order(ByteOrder.BIG_ENDIAN).asShortBuffer();
+
+ /* (non-Javadoc)
+ * @see jake2.sound.Sound#RawSamples(int, int, int, int, byte[])
+ */
+ public void RawSamples(int samples, int rate, int width, int channels, ByteBuffer data) {
+ int format;
+ if (channels == 2) {
+ format = (width == 2) ? AL.AL_FORMAT_STEREO16
+ : AL.AL_FORMAT_STEREO8;
+ } else {
+ format = (width == 2) ? AL.AL_FORMAT_MONO16
+ : AL.AL_FORMAT_MONO8;
+ }
+
+ // convert to signed 16 bit samples
+ if (format == AL.AL_FORMAT_MONO8) {
+ ShortBuffer sampleData = streamBuffer;
+ int value;
+ for (int i = 0; i < samples; i++) {
+ value = (data.get(i) & 0xFF) - 128;
+ sampleData.put(i, (short) value);
+ }
+ format = AL.AL_FORMAT_MONO16;
+ width = 2;
+ data = sfxDataBuffer.slice();
+ }
+
+ Channel.updateStream(data, samples * channels * width, format, rate);
+ }
+
+ public void disableStreaming() {
+ Channel.disableStreaming();
+ }
/*
===============================================================================
@@ -547,17 +578,14 @@ public final class JOALSoundImpl implements Sound {
*/
void Play() {
- int i;
- String name;
- sfx_t sfx;
-
- i = 1;
+ int i = 1;
+ String name;
while (i < Cmd.Argc()) {
name = new String(Cmd.Argv(i));
if (name.indexOf('.') == -1)
name += ".wav";
- sfx = RegisterSound(name);
+ RegisterSound(name);
StartLocalSound(name);
i++;
}