diff options
-rw-r--r-- | src/jake2/sound/joal/Channel.java | 97 | ||||
-rw-r--r-- | src/jake2/sound/joal/JOALSoundImpl.java | 80 |
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++; } |