⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channel.java

📁 Jake2是一个Java 3D游戏引擎.
💻 JAVA
字号:
/* * Created on Jun 19, 2004 *  * Copyright (C) 2003 * * $Id: Channel.java,v 1.8 2005/12/04 20:56:26 cawe Exp $ *//*Copyright (C) 1997-2001 Id Software, Inc.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/package jake2.sound.lwjgl;import jake2.Defines;import jake2.Globals;import jake2.client.CL_ents;import jake2.game.entity_state_t;import jake2.qcommon.Com;import jake2.sound.*;import jake2.util.Lib;import jake2.util.Math3D;import java.nio.*;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import org.lwjgl.openal.AL10;/** * Channel *  * @author dsanders/cwei */public class Channel {	final static int LISTENER = 0;	final static int FIXED = 1;	final static int DYNAMIC = 2;	final static int MAX_CHANNELS = 32;	private final static FloatBuffer NULLVECTOR = Lib.newFloatBuffer(3);		private static Channel[] channels = new Channel[MAX_CHANNELS];	private static IntBuffer sources = Lib.newIntBuffer(MAX_CHANNELS);	// a reference of L:WJGLSoundImpl.buffers 	private static IntBuffer buffers;	private static Map looptable = new Hashtable(MAX_CHANNELS);	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;	private int entchannel;	private int bufferId;	private int sourceId;	private float volume;	private float rolloff;	private float[] origin = {0, 0, 0};	// update flags	private boolean autosound;	private boolean active;	private boolean modified;	private boolean bufferChanged;	private boolean volumeChanged;	private Channel(int sourceId) {		this.sourceId = sourceId;		clear();		volumeChanged = false;		volume = 1.0f;	}	private void clear() {		entnum = entchannel = bufferId = -1;		bufferChanged = false;		rolloff = 0;		autosound = false;		active = false;		modified = false;	}		private static IntBuffer tmp = Lib.newIntBuffer(1);	static int init(IntBuffer buffers) {		Channel.buffers = buffers;	    // create channels		int sourceId;		for (int i = 0; i < MAX_CHANNELS; i++) {						AL10.alGenSources(tmp);			sourceId = tmp.get(0);			            // can't generate more sources 			if (sourceId <= 0) break;						sources.put(i, sourceId);			channels[i] = new Channel(sourceId);			numChannels++;						// set default values for AL sources			AL10.alSourcef (sourceId, AL10.AL_GAIN, 1.0f);			AL10.alSourcef (sourceId, AL10.AL_PITCH, 1.0f);			AL10.alSourcei (sourceId, AL10.AL_SOURCE_ABSOLUTE,  AL10.AL_TRUE);			AL10.nalSourcefv(sourceId, AL10.AL_VELOCITY, NULLVECTOR, 0);			AL10.alSourcei (sourceId, AL10.AL_LOOPING, AL10.AL_FALSE);			AL10.alSourcef (sourceId, AL10.AL_REFERENCE_DISTANCE, 200.0f);			AL10.alSourcef (sourceId, AL10.AL_MIN_GAIN, 0.0005f);			AL10.alSourcef (sourceId, AL10.AL_MAX_GAIN, 1.0f);		}		isInitialized = true;		return numChannels;	}		static void reset() {		for (int i = 0; i < numChannels; i++) {			AL10.alSourceStop(sources.get(i));			AL10.alSourcei(sources.get(i), AL10.AL_BUFFER, 0);			channels[i].clear();		}	}		static void shutdown() {		AL10.alDeleteSources(sources);		numChannels = 0;		isInitialized = false;	}	    static void enableStreaming() {        if (streamingEnabled) return;                // use the last source        numChannels--;        streamingEnabled = true;        streamQueue = 0;        int source = channels[numChannels].sourceId;        AL10.alSourcei (source, AL10.AL_SOURCE_RELATIVE,  AL10.AL_TRUE);        AL10.alSourcef(source, AL10.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;        AL10.alSourcei (source, AL10.AL_SOURCE_ABSOLUTE,  AL10.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        AL10.alSourceStop(source);        int count = AL10.alGetSourcei(source, AL10.AL_BUFFERS_QUEUED);        Com.DPrintf("unqueue " + count + " buffers\n");        while (count-- > 0) {            AL10.alSourceUnqueueBuffers(source, tmp);        }        streamQueue = 0;    }    static void updateStream(ByteBuffer samples, int count, int format, int rate) {        enableStreaming();        int source = channels[numChannels].sourceId;        int processed = AL10.alGetSourcei(source, AL10.AL_BUFFERS_PROCESSED);                boolean playing = (AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE) == AL10.AL_PLAYING);        boolean interupted = !playing && streamQueue > 2;                IntBuffer buffer = tmp;        if (interupted) {            unqueueStreams();            buffer.put(0, buffers.get(Sound.MAX_SFX + streamQueue++));            Com.DPrintf("queue " + (streamQueue - 1) + '\n');        } else if (processed < 2) {            // check queue overrun            if (streamQueue >= Sound.STREAM_QUEUE) return;            buffer.put(0, buffers.get(Sound.MAX_SFX + streamQueue++));            Com.DPrintf("queue " + (streamQueue - 1) + '\n');        } else {            // reuse the buffer            AL10.alSourceUnqueueBuffers(source, buffer);        }        samples.position(0);        samples.limit(count);        AL10.alBufferData(buffer.get(0), format, samples, rate);        AL10.alSourceQueueBuffers(source, buffer);                if (streamQueue > 1 && !playing) {            Com.DPrintf("start sound\n");            AL10.alSourcePlay(source);        }    }    	static void addPlaySounds() {		while (Channel.assign(PlaySound.nextPlayableSound()));	}		private static boolean assign(PlaySound ps) {	    if (ps == null) return false;		Channel ch = null;		int i;		for (i = 0; i < numChannels; i++) {			ch = channels[i];			if (ps.entchannel != 0 && ch.entnum == ps.entnum && ch.entchannel == ps.entchannel) {				// always override sound from same entity				if (ch.bufferId != ps.bufferId) {				    AL10.alSourceStop(ch.sourceId);				}				break;			}			// don't let monster sounds override player sounds			if ((ch.entnum == Globals.cl.playernum+1) && (ps.entnum != Globals.cl.playernum+1) && ch.bufferId != -1)				continue;			// looking for a free AL source			if (!ch.active) {				break;			}		}				if (i == numChannels)		    return false;				ch.type = ps.type;		if (ps.type == Channel.FIXED)		    Math3D.VectorCopy(ps.origin, ch.origin);		ch.entnum = ps.entnum;		ch.entchannel = ps.entchannel;		ch.bufferChanged = (ch.bufferId != ps.bufferId);					ch.bufferId = ps.bufferId;		ch.rolloff = ps.attenuation * 2;		ch.volumeChanged = (ch.volume != ps.volume);		ch.volume = ps.volume;		ch.active = true;		ch.modified = true;		return true;	}		private static Channel pickForLoop(int bufferId, float attenuation) {        Channel ch;        for (int i = 0; i < numChannels; i++) {            ch = channels[i];            // looking for a free AL source            if (!ch.active) {                ch.entnum = 0;                ch.entchannel = 0;        		ch.bufferChanged = (ch.bufferId != bufferId);			                ch.bufferId = bufferId;           		ch.volumeChanged = (ch.volume != 1.0f);           		ch.volume = 1.0f;           	    ch.rolloff = attenuation * 2;                ch.active = true;                ch.modified = true;                return ch;            }        }        return null;    }		private static FloatBuffer sourceOriginBuffer = Lib.newFloatBuffer(3);	//stack variable	private static float[] entityOrigin = {0, 0, 0}; 	static void playAllSounds(FloatBuffer listenerOrigin) {		FloatBuffer sourceOrigin = sourceOriginBuffer;		Channel ch;		int sourceId;		int state;		for (int i = 0; i < numChannels; i++) {			ch = channels[i];			if (ch.active) {				sourceId = ch.sourceId;				switch (ch.type) {					case Channel.LISTENER:					    sourceOrigin.put(0, listenerOrigin.get(0));						sourceOrigin.put(1, listenerOrigin.get(1));						sourceOrigin.put(2, listenerOrigin.get(2));						break;					case Channel.DYNAMIC:						CL_ents.GetEntitySoundOrigin(ch.entnum, entityOrigin);						convertVector(entityOrigin, sourceOrigin);						break;					case Channel.FIXED:						convertVector(ch.origin, sourceOrigin);						break;				}				if (ch.modified) {					if (ch.bufferChanged) {						AL10.alSourcei(sourceId, AL10.AL_BUFFER, ch.bufferId);					}					if (ch.volumeChanged) {						AL10.alSourcef (sourceId, AL10.AL_GAIN, ch.volume);					}					AL10.alSourcef (sourceId, AL10.AL_ROLLOFF_FACTOR, ch.rolloff);					AL10.nalSourcefv(sourceId, AL10.AL_POSITION, sourceOrigin, 0);					AL10.alSourcePlay(sourceId);					ch.modified = false;				} else {					state = AL10.alGetSourcei(sourceId, AL10.AL_SOURCE_STATE);					if (state == AL10.AL_PLAYING) {						AL10.nalSourcefv(sourceId, AL10.AL_POSITION, sourceOrigin, 0);					} else {						ch.clear();					}				}				ch.autosound = false;			}		}	}		/*	 * 	adddLoopSounds	 * 	Entities with a ->sound field will generated looped sounds	 * 	that are automatically started, stopped, and merged together	 * 	as the entities are sent to the client	 */	static void addLoopSounds() {				if ((Globals.cl_paused.value != 0.0f) || (Globals.cls.state != Globals.ca_active) || !Globals.cl.sound_prepped) {			removeUnusedLoopSounds();			return;		}				Channel ch;		sfx_t	sfx;		sfxcache_t sc;		int num;		entity_state_t ent;		Object key;		int sound = 0;		for (int i=0 ; i<Globals.cl.frame.num_entities ; i++) {			num = (Globals.cl.frame.parse_entities + i)&(Defines.MAX_PARSE_ENTITIES-1);			ent = Globals.cl_parse_entities[num];			sound = ent.sound;			if (sound == 0) continue;			key = new Integer(ent.number);			ch = (Channel)looptable.get(key);			if (ch != null) {				// keep on looping				ch.autosound = true;				Math3D.VectorCopy(ent.origin, ch.origin);				continue;			}			sfx = Globals.cl.sound_precache[sound];			if (sfx == null)				continue;		// bad sound effect			sc = sfx.cache;			if (sc == null)				continue;			// allocate a channel			ch = Channel.pickForLoop(buffers.get(sfx.bufferId), 6);			if (ch == null)				break;							ch.type = FIXED;			Math3D.VectorCopy(ent.origin, ch.origin);			ch.autosound = true;						looptable.put(key, ch);			AL10.alSourcei(ch.sourceId, AL10.AL_LOOPING, AL10.AL_TRUE);		}		removeUnusedLoopSounds();	}		private static void removeUnusedLoopSounds() {		Channel ch;		// stop unused loopsounds		for (Iterator iter = looptable.values().iterator(); iter.hasNext();) {			ch = (Channel)iter.next();			if (!ch.autosound) {				AL10.alSourceStop(ch.sourceId);				AL10.alSourcei(ch.sourceId, AL10.AL_LOOPING, AL10.AL_FALSE);				iter.remove();				ch.clear();			}		}	}	static void convertVector(float[] from, FloatBuffer to) {		to.put(0, from[0]);		to.put(1, from[2]);		to.put(2, -from[1]);	}	static void convertOrientation(float[] forward, float[] up, FloatBuffer orientation) {		orientation.put(0, forward[0]);		orientation.put(1, forward[2]);		orientation.put(2, -forward[1]);		orientation.put(3, up[0]);		orientation.put(4, up[2]);		orientation.put(5, -up[1]);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -