One potential bug I am looking into is the fading between left and right speakers only seems to work when the source is really close to the listener. I haven't determined if it is a limitation with my soundcard, or a bug in the code. I am looking into this further. It would be helpful if a few people could run the above applet and see if they experience the same thing. Thanks in advance!
Guide to the SoundManager class
The simplest way to use SoundManager in your jPCT project:
Create the SoundManager object when you initialize things:
soundManager = new SoundManager();
Bind the listener to the Camera after creating one:
soundManager.bindListener( camera );
Create some sound sources:
soundManager.newStreamingSource( "music", "deckthehalls.ogg", true );
soundManager.newSource( "meow", "cat.wav", false );
soundManager.newSource( "purr", "motor.wav", true );
Bind sound sources to Object3D's:
soundManager.bindSource( "meow", my3DCat );
soundManager.bindSource( "purr", my3DCat );
Call tick() in your main game loop:
Play the sounds any time you like:
soundManager.play( "music" );
soundManager.play( "meow" );
Call cleanup() at the end of your project:
ATTENUATION: How a sound "fades" with distance.
If there is no attenuation, a sound will play at constant volume regardless of distance
FADE DISTANCE: The distance at which a sound volume will become completely silent
Used in Linear Attenuation
(works for both mono and stereo sounds)
LINEAR ATTENUATION: A sound's volume is inverse to it's distance
A sound half fade-distance away will play at half volume
LOGRITHMIC ATTENUATION: A sound's volume is a logrithmic function of it's distance
A more realistic attenuation model - uses a rolloff factor
(only works for mono sounds)
ROLLOFF: A value used in logrithmic attenuation.
Smaller values for rolloff fade away at longer distances
If rolloff is 0, then the sound will not fade
STREAMING: Using multiple buffers to break long sound files, (like background music) up
into smaller pieces, so you can start playing immediately, rather than waiting to load.
public int ATTENUATION_NONE = 0; // no attenuation
public int ATTENUATION_ROLLOFF = 1; // logrithmic attenuation
public int ATTENUATION_LINEAR = 2; // linear attenuation
Global Varriables (can be changed to fit your preference):
Package where the sound files are located:
public String SOUNDFILES_LOCATION = "Sounds/";
Attenuation model to use if not specified (one of the references listed above):
public int DEFAULT_ATTENUATION_MODEL = ATTENUATION_ROLLOFF;
Default value to use for rolloff model when value isn't specified:
public float DEFAULT_ROLLOFF_FACTOR = 0.03f;
Default fade distance for linear model if value isn't specified:
public float DEFAULT_FADE_DISTANCE = 500.0f;
Number of bytes to load at a time when streaming:
public int STREAMING_BUFFER_SIZE = 4096*16;
The number of buffers used for each streaming sorce:
public int STREAMING_NUM_BUFFERS = 2;
The approximate size of a normal .ogg file:
private int OGG_NORMAL_SIZE = 1048575;
Easy Interfacing with jPCT
When using these methods, don't forget to call tick() in the main game loop:
bindListener( Camera c )
Listener will automatically follow and align with the Camera object
bindSource( Object3D o )
A source will automatically follow an Object3D
public void cleanUp()
Stops all sounds and clears up any used resources
public boolean bindListener( Camera c )
Orientates the listener to match the Camera orientation
public boolean bindSource( String sourcename, Object3D obj )
Associates a sound source with an Object3D to follow
Releases a source from it's associated Object3D
public void releaseSource( String sourcename )
public void releaseAllSources( Object3D obj )
Releases all sources bound to this Object3D
(Usually called before deleting an Object3D with sources attached to it, but not required)
public void tick()
Re-aligns the listner to the camera, and keeps sources folowing the Object3D's they are bound to
Should be called within the game loop
(only required if you are using bindListener or bindSource)
public boolean load( String filename )
Load the specified file (only used for non-streaming sources).
It is not necessary for you to call this method in your program, but you can if you want to.
(For example, you could load all the sounds at once and show a progress bar)
SoundManager will automatically call this method if necessary when creating a source
If "filename" is a url, it must begin with "http://"
Returns "true" if there were no problems loading the file
public boolean newSource( String sourcename, String filename, boolean toLoop )
public boolean newSource( String sourcename, String filename, boolean toLoop, int attmodel )
public boolean newSource( String sourcename, String filename, boolean toLoop, int attmodel, float distORroll )
public boolean newSource( String sourcename, String filename, boolean toLoop, float x, float y, float z, int attmodel )
public boolean newSource( String sourcename, String filename, boolean toLoop, float x, float y, float z, int attmodel, float distORroll )
public boolean newStreamingSource( String sourcename, String filename, boolean toLoop )
public boolean newStreamingSource( String sourcename, String filename, boolean toLoop, int attmodel )
public boolean newStreamingSource( String sourcename, String filename, boolean toLoop, int attmodel, float distORroll )
public boolean newStreamingSource( String sourcename, String filename, boolean toLoop, float x, float y, float z, int attmodel )
public boolean newStreamingSource( String sourcename, String filename, boolean toLoop, float x, float y, float z, int attmodel, float distORroll )
Create a new normal or streaming source. A streaming source differs from a normal source, in that it has multiple, dynamic buffers.
SoundManager will use default values for any value you don't specify when creating your source.
sourcename: A unique identifier for this source (two sources may not use the same sourcename)
filename: The name of the sound file to play at this source. If "filename" is a url, it must begin with "http://"
(if the sound file has not been loaded yet, then SoundManager will load it for you)
toLoop: Should this source loop, or play the sound only once
(x, y, z): Location in 3D space for this source. Default location is the origin ( 0, 0, 0 )
attmodel: Attenuation model to use. Default is the value in DEFAULT_ATTENUATION_MODEL
distORroll: Either the fading distance or rolloff factor, depending on the value of "attmodel".
public boolean deleteSource( String sourcename )
Deletes the specified source
public boolean setPos( String sourcename, SimpleVector pos )
public boolean setPos( String sourcename, float x, float y, float z )
Moves the named sound to the specified location.
public boolean play( String sourcename )
public boolean stop( String sourcename )
public boolean pause( String sourcename )
public boolean rewind( String sourcename )
Controls for playing, stopping, pausing, and rewinding a source
public boolean playing( String sourcename )
Returns true if the source is playing
public void moveListener( float xStep, float zStep )
public void moveListener( SimpleVector step )
public void moveListener( float xStep, float yStep, float zStep )
Moves the listener, relative to their current position.
public void setListenerPos( float xNew, float zNew )
public void setListenerPos( SimpleVector posNew )
public void setListenerPos( float xNew, float yNew, float zNew )
Positions the listener at the coordinates provided.
public void turnListener( float angle )
Turns the listener counterclockwise by "angle" radians, relative to their current orientation.
public void setListenerOrientation( float angle )
Sets the listener's orientation (counterclockwise rotation in radians along the y-axis)
public void setListenerOrientation( SimpleVector look, SimpleVector up )
public void setListenerOrientation( float lookX, float lookY, float lookZ, float upX, float upY, float upZ )
Sets the listener's orientation based on a look-at point and an up-direction
public void recalculateDistances()
Recalculates the distances between each source and the listener, and recalculates the gain if a
source is using linear attenuation. It is not necessary for you to use this method.
SoundManager will automatically call this method when the listener moves or rotates, or a source moves.