/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions 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 the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.sound.drivers.joal; import org.openmali.vecmath2.Tuple3f; import org.xith3d.sound.SoundBuffer; import org.xith3d.sound.SoundContainer; import org.xith3d.sound.SoundDriver; import org.xith3d.sound.SoundSource; import org.xith3d.sound.SoundState; import org.xith3d.utility.logging.X3DLog; import net.java.games.joal.AL; /** * JOAL implementation of SoundSource. * * @author David Yazel */ public class SoundSourceImpl implements SoundSource { static int count = 0; int handle; private SoundDriverImpl driver; public SoundSourceImpl( SoundDriverImpl driver ) { this.driver = driver; int[] ret = new int[ 1 ]; int error = driver.getAL().alGetError(); driver.getAL().alGenSources( 1, ret, 0 ); error = driver.getAL().alGetError(); if ( error != AL.AL_NO_ERROR ) throw new Error( "no more sources available : " + driver.decodeSoundError( error ) ); handle = ret[ 0 ]; X3DLog.debug( "Created new source.. handle = ", handle ); setRolloffFactor( 0.5f ); setMaxDistance( 30 ); setReferenceDistance( 5 ); setMinVolume( 0 ); setMaxVolume( 1 ); } public void queueBuffer( SoundBuffer buffer ) { driver.getAL().alSourceQueueBuffers( handle, 1, new int[] { ( (SoundBufferImpl)buffer ).handle }, 0 ); driver.checkError(); } public int[] unqueueProcessedBuffers() { int ret[] = new int[ 1 ]; driver.getAL().alGetSourcei( handle, AL.AL_BUFFERS_PROCESSED, ret, 0 ); int num = ret[ 0 ]; int buffers[] = new int[ num ]; driver.getAL().alSourceUnqueueBuffers( handle, num, buffers, 0 ); driver.checkError(); return ( buffers ); } public void setBuffer( SoundBuffer buffer ) { driver.getAL().alSourcei( handle, AL.AL_BUFFER, ( (SoundBufferImpl)buffer ).handle ); driver.checkError(); } public void setContainer( SoundContainer container ) { SoundBuffer b = container.getData( driver ); if ( b != null ) setBuffer( b ); } public void setVolume( float gain ) { driver.getAL().alSourcef( handle, AL.AL_GAIN, gain ); driver.checkError(); } public void play() { driver.getAL().alSourcePlay( handle ); driver.checkError(); } public void pause() { driver.getAL().alSourcePause( handle ); driver.checkError(); } public void rewind() { driver.getAL().alSourceRewind( handle ); driver.checkError(); } public void stop() { driver.getAL().alSourceStop( handle ); driver.checkError(); } public boolean isPlaying() { return ( getState() == SoundState.PLAYING ); } private float[] pos = new float[ 3 ]; private boolean hasCachedPosition = false; void releaseCachedResources() { hasCachedPosition = false; } public void setPosition( float posX, float posY, float posZ ) { if ( hasCachedPosition ) { if ( ( pos[ 0 ] == posX ) && ( pos[ 1 ] == posY ) && ( pos[ 2 ] == posZ ) ) return; hasCachedPosition = true; } pos[ 0 ] = posX; pos[ 1 ] = posY; pos[ 2 ] = posZ; driver.getAL().alSourcefv( handle, AL.AL_POSITION, pos, 0 ); driver.checkError(); //if (((++count) % 200) == 0) System.out.println( "Position for source" + handle + " is " + position ); } public void setPosition( Tuple3f position ) { setPosition( position.getX(), position.getY(), position.getZ() ); } public void setVelocity( float veloX, float veloY, float veloZ ) { driver.getAL().alSource3f( handle, AL.AL_VELOCITY, veloX, veloY, veloZ ); driver.checkError(); } public void setVelocity( Tuple3f velocity ) { setVelocity( velocity.getX(), velocity.getY(), velocity.getZ() ); } public void setDirection( float dirX, float dirY, float dirZ ) { } public void setDirection( Tuple3f direction ) { } public SoundState getState() { int ret[] = new int[ 1 ]; driver.getAL().alGetSourcei( handle, AL.AL_SOURCE_STATE, ret, 0 ); int state = ret[ 0 ]; switch ( state ) { case AL.AL_PLAYING: return ( SoundState.PLAYING ); case AL.AL_PAUSED: return ( SoundState.PAUSED ); case AL.AL_INITIAL: return ( SoundState.INITIAL ); case AL.AL_STOPPED: return ( SoundState.STOPPED ); default: throw new Error( "Illegal OpenAL state found" ); } } public void setReferenceDistance( float refDistance ) { driver.getAL().alSourcef( handle, AL.AL_REFERENCE_DISTANCE, refDistance ); driver.checkError(); } /** * Set to zero if this is an unattenuated sound, 1 would be normal otherwise * * @param factor */ public void setRolloffFactor( float factor ) { driver.getAL().alSourcef( handle, AL.AL_ROLLOFF_FACTOR, factor ); driver.checkError(); } public void setRelative( boolean relative ) { driver.getAL().alSourcei( handle, AL.AL_SOURCE_RELATIVE, relative ? 1 : 0 ); driver.checkError(); } public void setLoop( boolean loop ) { driver.getAL().alSourcei( handle, AL.AL_LOOPING, loop ? 1 : 0 ); } public void setMaxVolume( float maxVolume ) { driver.getAL().alSourcef( handle, AL.AL_MAX_GAIN, maxVolume ); driver.checkError(); } public void setMinVolume( float minVolume ) { driver.getAL().alSourcef( handle, AL.AL_MIN_GAIN, minVolume ); driver.checkError(); } public void setMaxDistance( float maxDistance ) { driver.getAL().alSourcef( handle, AL.AL_MAX_DISTANCE, maxDistance ); driver.checkError(); } public void setMaxTime( long ms ) { } public SoundDriver getSoundDriver() { return ( driver ); } }