Hello, I am new to JOAL, and I am having a slight problem. I created a class from a book I own, for managing sounds for my program. I seem to be doing something wrong, though, because when I attempt to move the source, the sound output does not change. I would expect that a source moving away from you would get quieter, but the volume remains constant. Here is my code for the sound manager:
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import net.java.games.joal.AL;
import net.java.games.joal.ALException;
import net.java.games.joal.ALFactory;
import net.java.games.joal.util.ALut;
public class JOALSoundMan
{
// where the sound files are stored:
private final static String SOUND_DIR = "Sounds\\";
// Note: currently configured to only load WAV sounds
private final static String FILE_EXT = ".wav";
// Global stores for the sounds:
private HashMap<String, int[]> buffersMap; // (name, buffer) pairs
private HashMap<String, int[]> sourcesMap; // (name, buffer) pairs
private AL al;
private float listenerX, listenerY, listenerZ; // current position
private float[] listenerOrientation; // orientation
private float listenerAngle = 0; // listener's angle (in radians)
public JOALSoundMan()
{
buffersMap = new HashMap<String, int[]>();
sourcesMap = new HashMap<String, int[]>();
initOpenAL();
initListener();
}
private void initOpenAL()
{
try
{
ALut.alutInit(); // creates an OpenAL context
al = ALFactory.getAL(); // used to access OpenAL
al.alGetError();
// System.out.pringln( "JOAL version: " + Version.getVersion());
}
catch( ALException e )
{
e.printStackTrace();
System.exit( 1 );
}
}
// Position and orientate the listener:
private void initListener()
{
listenerX = 0.0f;
listenerY = 0.0f;
listenerZ = 0.0f;
// position the listerner at the origin:
al.alListener3f( AL.AL_POSITION, listenerX, listenerY, listenerZ );
al.alListener3i( AL.AL_VELOCITY, 0, 0, 0 ); // no velocity
// first 3 elements are "look at" point
// second 3 are the "up direction"
listenerOrientation = new float[] {listenerX, listenerY, listenerZ - 1.0f, 0.0f, 1.0f, 0.0f };
al.alListenerfv( AL.AL_ORIENTATION, listenerOrientation, 0);
}
public void cleanUp()
{
Set<String> keys = sourcesMap.keySet();
Iterator<String> iter = keys.iterator();
String nm;
int[] buffer, source;
while( iter.hasNext() )
{
nm = iter.next();
source = sourcesMap.get(nm);
System.out.println( "Stopping " + nm);
al.alSourceStop( source[0] );
al.alDeleteSources( 1, source, 0 );
buffer = buffersMap.get( nm );
al.alDeleteBuffers( 1, buffer, 0 );
}
ALut.alutExit();
}
public boolean load( String nm, boolean toLoop )
{
if( sourcesMap.get( nm ) != null )
{
System.out.println( nm + " already loaded" );
return true;
}
int[] buffer = initBuffer( nm );
if( buffer == null )
return false;
int[] source = initSource( nm, buffer, toLoop );
if( source == null )
{
// no need for the buffer anymore
al.alDeleteBuffers( 1, buffer, 0 );
return false;
}
if( toLoop )
System.out.println( "Looping source created for " + nm );
else
System.out.println( "Source created for " + nm );
buffersMap.put( nm, buffer );
sourcesMap.put( nm, source );
return true;
}
public boolean load( String nm, float x, float y, float z, boolean toLoop )
{
if( load( nm, toLoop ) )
return setPos( nm, x, y, z );
else
return false;
}
// Create arrays for holding various sound files:
private int[] initBuffer( String nm )
{
int[] format = new int[1];
ByteBuffer[] data = new ByteBuffer[1];
int[] size = new int[1];
int[] freq = new int[1];
int[] loop = new int[1];
// load WAV file into the data arrays
String fnm = SOUND_DIR + nm + FILE_EXT;
try
{
ALut.alutLoadWAVFile( fnm, format, data, size, freq, loop );
}
catch( ALException e )
{
System.out.println( "Error loading WAV file: " + fnm );
return null;
}
// System.out.println( "Sound size = " + size[0] );
// System.out.println( "Sound freq = " + freq[0] );
// create an empty buffer to hold the sound data
int[] buffer = new int[1];
al.alGenBuffers( 1, buffer, 0 );
if( al.alGetError() != AL.AL_NO_ERROR )
{
System.out.println( "Could not create a buffer for " + nm );
return null;
}
// store data in the buffer
al.alBufferData( buffer[0], format[0], data[0], size[0], freq[0] );
return buffer;
}
// Create a source (a point in space that makes sound):
private int[] initSource( String nm, int[] buf, boolean toLoop )
{
int[] source = new int[1];
al.alGenSources( 1, source, 0 );
if( al.alGetError() != AL.AL_NO_ERROR )
{
System.out.println( "Error creating source for " + nm );
return null;
}
// configure the source
al.alSourcei( source[0], AL.AL_BUFFER, buf[0] ); // bind buffer
al.alSourcef( source[0], AL.AL_PITCH, 1.0f );
al.alSourcef( source[0], AL.AL_GAIN, 1.0f );
// Position the source at the origin:
al.alSource3f( source[0], AL.AL_POSITION, 0.0f, 0.0f, 0.0f );
al.alSource3f( source[0], AL.AL_VELOCITY, 0, 0, 0 ); // no velocity
if( toLoop )
al.alSourcei( source[0], AL.AL_LOOPING, AL.AL_TRUE ); // looping
else
al.alSourcei( source[0], AL.AL_LOOPING, AL.AL_FALSE ); // play once
if( al.alGetError() != AL.AL_NO_ERROR )
{
System.out.println( "Error configuring source for " + nm );
return null;
}
return source;
}
// Move the nm sound to (x, y, z):
public boolean setPos( String nm, float x, float y, float z )
{
int[] source = (int[]) sourcesMap.get( nm );
if( source == null )
{
System.out.println( "No source found for " + nm );
return false;
}
al.alSource3f( source[0], AL.AL_POSITION, x, y, z );
return true;
}
public boolean play( String nm )
{
int[] source = (int[]) sourcesMap.get( nm );
if( source == null )
{
System.out.println( "No source found for " + nm );
return false;
}
// System.out.println( "Playing " + nm );
al.alSourcePlay( source[0] );
return true;
}
// move the listener by (x, z) step
public void moveListener( float xStep, float zStep )
{
float x = listenerX + xStep;
float z = listenerZ + zStep;
setListenerPos( x, z );
}
// position the listener at (xNew, zNew)
public void setListenerPos( float xNew, float zNew )
{
float xOffset = xNew - listenerX;
float zOffset = zNew - listenerZ;
listenerX = xNew;
listenerZ = zNew;
al.alListener3f( AL.AL_POSITION, listenerX, listenerY, listenerZ );
// keep the listener facing the same direction by
// moving the "look at" point by the (x,z) offset
listenerOrientation[0] += xOffset;
listenerOrientation[2] += zOffset;
// no need to change the y-coord since listener only moves over XZ plane
al.alListenerfv( AL.AL_ORIENTATION, listenerOrientation, 0 );
}
// turn the listener counterclockwise by deg DEGREES
public void turnListener( int deg )
{
setListenerOrientation( (int)Math.toDegrees(listenerAngle) + deg );
}
// turn the listener counterclockwise by rad RADIANS
public void turnListener( float rad )
{
setListenerOrientation( listenerAngle + rad );
}
// set the listener's orientation to be deg DEGREES
// in the counterclockwise direction around the y-axis
public void setListenerOrientation( int deg )
{
listenerAngle = (float)Math.toRadians( deg );
double angle = (double) listenerAngle;
float xLen = -1.0f * (float) Math.sin( angle );
float zLen = -1.0f * (float) Math.cos( angle );
// face in the (xLen, zLen direction by adding the
// values to te listener position
listenerOrientation[0] = listenerX + xLen;
listenerOrientation[2] = listenerZ + zLen;
al.alListenerfv( AL.AL_ORIENTATION, listenerOrientation, 0 );
}
// set the listener's orientation to be rad RADIANS
// in the counterclockwise direction around the y-axis
public void setListenerOrientation( float rad )
{
listenerAngle = rad;
double angle = (double) listenerAngle;
float xLen = -1.0f * (float) Math.sin( angle );
float zLen = -1.0f * (float) Math.cos( angle );
// face in the (xLen, zLen) direction by adding the
// values to te listener position
listenerOrientation[0] = listenerX + xLen;
listenerOrientation[2] = listenerZ + zLen;
al.alListenerfv( AL.AL_ORIENTATION, listenerOrientation, 0 );
}
}
And here is the code for loading, playing, and moving the sound in my program:
String soundName = "tada";
JOALSoundMan soundMan = new JOALSoundMan();
if( !soundMan.load( soundName, true ) )
System.exit( 1 );
// default position for sound is (0,0,0)
soundMan.play( soundName );
// move the sound along the negative z-axis
float step = 0.1f;
// I have tried using a larger number like 100.0f;
float zPos = 0.0f;
for( int i=0; i < 50; i++ )
{
zPos -= step;
soundMan.setPos( soundName, 0, 0, zPos );
try
{
Thread.sleep( 250 ); // sleep for 0.25 secs
}
catch( InterruptedException ex ) {}
}
soundMan.cleanUp();
Anybody have an idea what I am doing wrong?