Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - paulscode

Pages: 1 ... 54 55 [56] 57 58
826
Projects / Re: 3D Sound using lwjgl binding of Open AL
« on: March 16, 2008, 02:42:55 am »
New version of SoundManager is out today.
JAR:
http://www.paulscode.com/libs/SoundSystem/15MAR2008/SoundManager.jar

Source:
http://www.paulscode.com/source/SoundSystem/15MAR2008/SoundManagerSource.zip

SoundManager has changed quite a bit, so I decided to write a basic guide:
Code: [Select]
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:
    soundManager.tick();
Play the sounds any time you like:
    soundManager.play( "music" );
    soundManager.play( "meow" );
Call cleanup() at the end of your project:
    soundManager.cleanup();


Common Terms:
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.


Global References:
Attenuation models:
    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



Method Descriptions:

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.

Here's a rough overview of what's new about this version:

1) I moved the SoundManager class from package "Sounds" to a package called "paulscode.sound"

2) Sounds can now be loaded from either the jar, or from a url.  When loading from a url, the filename must begin with "http://" (that is how SoundManager determines wheter to look in the jar or go to a URL to load a file).  I didn't add the ability to load files from a harddrive directory (I figure it is just as easy to load them from the jar).

3) I corrected a math error in the setListenerOrientation( float angle ) method.

4) I added looping for streaming .ogg sources, and corrected a problem where the last block of data was getting cut off.

5) I rewrote the methods for handling streaming threads, to correct an exception I was getting when trying to clear buffer memory on exit.  Buffers are now all being cleared correctly when SoundManager.cleanUp() gets called.

6) I added in two new functions to make using SoundManager with jPCT a breeze.  They are designed to let you focus on the graphics, and not have to wory about sound. The functions are:
    a) bindListener( Camera c )
        Called after creating the camera.  The SoundManager will automatically translate and rotate the listener to match the camera any time the camera's position or orientation changes.  After calling this method, you don't have to even think about translations and rotations to keep the listener and camera in-sinc - SoundManager does it for you.
    b) bindSource( String sourcename, Object3D obj )
        Called after creating a new source and an Object3D.  Similar to bindListener, except it binds a sound source to an Object3D.  You can attach as many sources as you want to an object, and they can be regular, streaming, looping, whatever.  Again, after calling this method, you don't have to worry about moving your source to match the object - SoundManager takes care of it.

The only thing you have to remember when using either of the two "bind" methods, is you have to call SoundManager.tick() from inside your main game loop (that is the method where SoundManager checks if anything has moved).

I created a simple applet to demonstrate the bind features, which you can see at:
LINK NO LONGER EXISTS

Rotate the camera with the left and right arrow keys, and move the gear's depth with the up and down arrow keys.  You can get the source code for this applet at:
LINK NO LONGER EXISTS

One potential bug I am looking into is the fading between left and right speakers only seems to work when the source is 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!

827
Support / Camera position and orientation
« on: March 15, 2008, 12:45:50 am »
Hello, I have another simple question.  I need to be able to access the camera's position, a look-at point, and a point in the up-direction.  Looking through the classes, it looks like the methods I will need to use are:

getPosition()        // World Position
getDirection()       // look-at *direction*
getYAxis()           // up-direction *normalized*

My theory is that to get a look-at point, I would add getDirection() to getPosition(), and to get a point in the up-direction, I would add getYAxis() to getPosition().  Since I will be using this idea in methods which are not related to graphics, it would be difficult for me to test if this theory is correct, so I thought it would be smart to ask the experts first ;D  Thanks!

828
Support / Re: Translation Tipoff
« on: March 15, 2008, 12:33:15 am »
I see, well my goal is not to hear about parent translations from a child object, anyway, that was just a means to the goal.

My goal is simply to be tipped of when an object gets translated so I can check what that translation is.  From your response, extending Object3D and overriding the "translate" methods would not help me anyway, because if my object were to be a child of another object which gets translated, My object would not know about it.  (Besides, doing an extension of Object3D would not be practical for what I am doing, anyway - this is related to creating a method for binding a sound source to an Object3D.  It is for a library that will be used by multiple users and different applications ).

So to achieve my goal, I will have to approach this problem from a different angle.  I think I will create a method that gets called from the main game loop, which calls "getTransformedCenter()" on the object in question to determine if a translation has taken place and what that translation is.

Thanks for the advice!

829
Support / Translation Tipoff
« on: March 14, 2008, 10:55:59 pm »
Hey, I was wondering if there is a method in Object3D that gets called from a child object when it's parent gets translated.

I want to bind to an object to know when it gets moved.  The way I was thinking of doing this, is to create a class that extends Object3D and registering it as a child to the object in question.  Then, I would just need a way to be tipped of that a translation has taken place, and then figure out what that translation is ( I could use getTranslation() for the later, right? )

830
Projects / Re: 3D Sound using lwjgl binding of Open AL
« on: March 14, 2008, 09:47:40 pm »
Does the sound file need to be added to the jar?  I haven't tried it yet, just asking beforehand.  To tell the truth I have no experience with jar files at all other than putting them in a classpath.
Yes, for now they need to be in the jar.  You can either put them in a package called "Sounds/", or you can change the global varriable:
SoundManager.SOUNDFILES_LOCATION
It needs to be a String containing the "/" separated path to the package containing your sound files, and must end with "/".

I am adding two more ways to load files - from a URL and from an external path.  I should hopefully be finished with this and a few other things I am working on, in the next couple of days.

831
Projects / Re: 3D Sound using lwjgl binding of Open AL
« on: March 12, 2008, 04:55:17 am »
New version of SoundManager is out today.

JAR:
http://www.paulscode.com/libs/SoundSystem/11MAR2008/SoundManager.jar

Source:
http://www.paulscode.com/source/SoundSystem/11MAR2008/SoundManagerSource.zip

Here's what's new about this version:

1) SoundManager now supports attenuation (how a sound "fades" with distance).  Available types:
    No Attenuation: The sound will play at constant volume regardless of distance
    Linear Attenuation: lets you specify a distance at which a sound volume
                              will become completely silent.
                              (works for both mono and stereo sounds!)
     Logrithmic Attenuation (or Rolloff): More realistic - uses a rolloff factor
                                                    Smaller values for rolloff fade at
                                                    longer distances.  If rolloff is 0,
                                                    then the sound will not fade.
                                                    (only works for mono sounds)
     There are also a few varriables you can change to redefine the default attenuation settings.  Or you can just leave them alone and let SoundManager use the default settings:
         SoundManager.DEFAULT_ATTENUATION_MODEL
         SoundManager.DEFAULT_ROLLOFF_FACTOR
         SoundManager.DEFAULT_FADE_DISTANCE
2) You can now create multiple sources from the same sound file.  The method for creating a source is "newSource".  It is no longer necessary to call the "load" method.  SoundManager will automatically call "load" before creating a source if the sound file hasn't been loaded yet.  There are several ways to call "newSource", depending on how much information you want to supply.  SoundManager will use default values for any value you don't specify when creating your source.
    The least amount of information required to create a source is:
    newSource( sourcename, filename, toLoop );
          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 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         
    Optional information you can specify when creating a new source:
    newSource( sourcename, filename, toLoop, x, y, z, attmodel, distORroll );
          (x, y, z):  Location in 3D space for this source.
                      Default location is the origin ( 0, 0, 0 )
          attmodel:   Attenuation model to use.  Possible values are
                              SoundManager.ATTENUATION_NONE
                              SoundManager.ATTENUATION_ROLLOFF
                              SoundManager.ATTENUATION_LINEAR
          distORroll: Either the fading distance or rolloff factor,
                      depending on the value of "attmodel".
3) .ogg files are supported.  They can be either streamed or played normally.  There are some varriables you can change to redefine how streaming is handled.  Or you can just leave them alone and let SoundManager use the default settings:
    SoundManager.STREAMING_BUFFER_SIZE   (size of each data "block")
    SoundManager.STREAMING_NUM_BUFFERS   (number of buffers to use when streaming)
4) There is also a method called "newStreamingSource".  A streaming source differs from a normal source, in that it has multiple, dynamic buffers.  Use newStreamingSource to create a source that will be streaming a sound.  newStreamingSource takes the same parameters as newSource.

To have support for .ogg files, the above jar is compiled with the source code from the j-ogg library, located at http://www.j-ogg.de.  If you want to alter the SoundManager class, you will need need to include that library before you will be able to compile.  The source files for the j-ogg library are also inside the zip file refrenced above.

832
Projects / Re: 3D Sound System
« on: March 11, 2008, 03:26:24 am »
Project Overview:

This project began as a problem in the Support section, about OpenAL being extremely complicated, and that there needs to be a 3D sound library that is easy to understand and use.  I decided to create a class that does all the tedious stuff and simplifies OpenAL.  I have since added the ability to switch between OpenAL and JavaSound, using a common interface.  I also added automatic compatibility checking, to make life even easier for the programmer.  And of course, I extended the base library to make a version that is easily compatible with jPCT.

Now as you know, jPCT uses the Lightweight Java Game Library (lwjgl) for hardware rendering (http://www.lwjgl.org), so chances are, your projects are already loading those libraries.  Cool thing is, lwjgl has a binding to OpenAL too, so that is what SoundSystem uses to interface with OpenAL.

This project was originally called "Sound Manager", and the thread title was "3D Sound using lwjgl binding of Open AL".  Somewhere along the way the library name changed to "Sound System", and I also decided to change the thread name.  Just thought I would point that out in case anyone decides to read through the old posts, so you won't be confused.

For a while I was regularly updating an extension of the SoundSystem class called "SoundManager", which used two different source management models for dealing intelligently with cases where more than 32 sources were playing at once.  It has since been discontinued, since there there doesn't seem to be any interest in it.  The way SoundSystem manages too many simultaneously playing sources is quite sufficient for most projects.

If anyone has any ideas for improving the library, let me know!

833
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 11, 2008, 02:41:55 am »
Maybe you should add your code as a project in the projects area. That way visitors to the site can see there are some sound classes specifically for jpct.  ::)

That is a good idea.  From now on, progress on SoundManager will be located in the projects area, under the post titled "3D Sound using lwjgl binding of Open AL" (http://www.jpct.net/forum2/index.php/topic,1057.0.html).

834
Projects / 3D Sound System
« on: March 11, 2008, 02:38:51 am »
-- This slot is reserved for the most recent working releases --

Downloads:

Sound System  Version date:  October 23, 2010
The core SoundSystem library, independent from 3rd-party libraries.  It is stripped down to the bare essentials, and designed to be easily customizable with various sound library and codec plug-ins.  If memory is a concern (such as in an applet) this may be a good option, because it allows you to choose as many or as few plug-ins as you require for your project.  NOTE: The core SoundSystem library without any plug-ins is only capable of playing MIDI files.  Additional plug-ins should be added for more capabilities.  The source code and license are included in the .zip file.

Sound System jPCT  Version date:  October 23, 2010
The jPCT-friendly 3D sound library.  The SoundSystemJPCT class overrides the core SoundSystem libray, and provides a number of methods to make adding 3D sound to any jPCT project easy.  It includes methods for binding Listener to Camera and Sources to Object3Ds, as well as using SimpleVector parameters.  SoundSystemJPCT utilizes the LWJGL binding of OpenAL (with JavaSound as a backup option), and the J-Ogg library for .ogg support.  NOTE: The core SoundSystem library, source code, and all relevant licenses are included in the .zip file.

SoundSystem Utils  Version date:  August 8, 2009
Includes a SoundSystem loader, and an example XML file.


Plug-ins:

JavaSound library plug-in  Version date:  October 23, 2010
Interface to the Java Sound API.  More compatable than OpenAL, but not as high quality and fewer features.  This plug-in utilizes JavaSound's panning and volume control methods to simulate an reasonable-quality 3D sound system.  Known bug: quickPlaying sounds will begin playing them at full volume for a split second, before switching to the correct volume.  This is a bug with the Java Sound API itself, and therefore beyond my control to correct.  An easy workaround is to add 0.02 seconds of silence to the beginning of each sound effect (the free Audacity sound editor works well for this).

LWJGL OpenAL library plug-in  Version date:  August 24, 2010
Interface to the LWJGL binding of OpenAL.  The LWJGL library (http://www.lwjgl.org) is required for this plug-in to work.  This library sounds much better than Java Sound, but is not as compatable.  I recommend using the JavaSound library plug-in as a backup option.  NOTE: Please read the included LWJGL license.

JOAL library plug-in  Version date:  August 29, 2011
Interface to the JOAL binding of OpenAL.  The JOAL library (http://jogamp.org) is required for this plug-in to work.  As mentioned previously, this library sounds much better than Java Sound, but is not as compatable.  I recommend using the JavaSound library plug-in as a backup option.  NOTE: Please read the included JOAL license.

WAV codec plug-in  Version date:  October 23, 2010
Adds support for .wav files.

JOgg codec plug-in  Version date:  August 24, 2010
Adds support for .ogg files using the J-Ogg library.  This codec is less compatible than the JOrbis codec, but the license is less restrictive.  Sometimes running incompatable .ogg files through a converter will make them compatable.  NOTE: Please read the included JOgg license.

JOrbis codec plug-in  Version date:  November 23, 2010
Adds support for .ogg files using the JOrbis library.  More compatible than the JOgg codec, but reads data more slowly (it may not be possible to stream more than one file simultaneously when using this codec).  This plug-in is licensed by the LGPL.  NOTE: Please read the included LGPL document.

IBXM codec plug-in  Version date:  August 24, 2010
Adds support for Protracker, Fast Tracker 2, and Scream Tracker 3 (.s2m, .mod, and .xm) files using the IBXM library.  File sizes for these formats tend to be quite small, so this may be a good option for background music.  This plug-in is based on or using the IBXM library, which is bound by the BSD License.  NOTE: Please read the included license document.

JSpeex codec plug-in  Version date:  August 24, 2010
Adds support for .ogg or .wav files encoded with Speex (a compression optimized for human voice).  See http://www.speex.org/ for more information.


Documentation:

JavaDoc  Version date:  October 23, 2010
Also includes the JavaDocs for SoundSystemJPCT and all library and codec plug-ins, and the utils library.

3D Sound with SoundSystem  PDF (download the example programs)
A tutorial-style guide to using the core SoundSystem library (last updated: April 14, 2009).

Guide to SoundSystemJPCT  PDF (download the example programs)
Another tutorial-style guide to using SoundSystemJPCT. (last updated: April 14, 2009).


Demos:
(last updated: August 21, 2010)

Sound Effects Player  (download the Source Code)
Demonstrates library switching on the fly, streaming background music, playing MIDI, and playing multiple sources simultaneously.

Bullet / Target Collision  (download the Source Code)
Demonstrates the LibraryJavaSound plug-in.

Holy Bouncing Helicopter Balls!  (download the Source Code)
Currently uses the SoundSystem core -- I'm currently working on a version for SoundSystemJPCT, which will be much simpler.  Demonstrates moving through a world with multiple sources.


What's new?

- Fixed JOAL package name from the old net.java.games.joal to the new com.jogamp.openal
- Updated CodecWav link to current version
- Improved LibraryJavaSound performance slightly in non-Sun Java versions
- Handled rare pan-control exception
- Fixed fadeOutIn bug which caused fade-in effect to be silent
- Fixed a bug where certain types of .ogg files created in versions of Audacity were cut off just before the end of the sample

835
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 11, 2008, 01:56:06 am »
How can I change the fading distance. I want each sound to have a different fading distance. With parameter should I change? Were is the distance applied? I need it to be changed on the play or on the load method.

The parameter that deals with distance fading (a.k.a "Attenuation"), is "AL_ROLLOFF_FACTOR" (set when creating a source).  I am adding this functionality into the SoundManager now, but if you are interested in doing it yourself (so you won't loose the other changes you have made), the method you'll need to alter is "initSource".  "initSource" is called from "load", so you should change "load" so it takes another parameter (a fade distance), then pass this on to initSource.
 
Now here is the tricky part.  Rolloff factor is a float that ranges from 0.0 to virtual infinity (I believe 1.0 is default, so you will be using rolloffs that are less than that).  The closer to 0.0 you set the rolloff factor, the greater the fading distance will be.  Higher rolloffs fade faster.

So in other words you have to do some math to convert your fade distaince into a rolloff factor.  Unfortunately, there is no way to say "I want this source to fade and become quiet at distance X" (unless you write a formula to manually set the sound's gain - I am working on this).  The problem is, if you have your speakers turned up louder, or if you are playing a louder sound file, fading will happen at a larger distance (and quieter sounds or lower volume on your speakers will fade away faster).

For now, what I did to overcome this problem, is approximation, trial and error.  I picked an avarage sound with speakers set at an average volume, and messed around with distances and rolloff factors.  I put together a data set and calculated the following Logrithmic Regression:

-- EDIT: :o Wow, I just realized I was using "moveListener" instead of "setListenerPos" when in calculated this!
DONT USE THE FORMULA I HAD HERE. IT IS WAY OFF!

836
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 09, 2008, 04:38:02 pm »
Does this work for ogg?
??? Never used ogg before.  That's a codec / sound format, right?  The above class is written for lwjgl's binding of OpenAL, and it currently only opens .wav sound files.  I could look into what other sound formats can be used with lwjgl, if that would be helpful.

-- EDIT:  I did a little more research on the subject, and I found a tutorial on streaming ogg in Open AL.  The original tutorial is written in c++, but I also found a translation of the tutorial written for JOAL.  I will see if I can re-write it in lwjgl.  I'll keep you posted.

--UPDATE:  I have finished porting the .ogg streamer over to lwjgl, and I can now play .ogg files normally, or "stream" them (that's where you use multiple buffers to break really long files like background music up into smaller pieces, so you can begin playing them immediately).  I will now implement all this in the Sound Manager and repost the code when I am finished.  I am really glad I found this, because now I know how to do multi-buffer streaming of sounds, so thanks for the question, fireside! ;D

837
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 09, 2008, 02:11:53 am »
 :o Oh!  The SoundManager uses lwjgl now instead of JOAL.

Realistically, though, both lwjgl and JOAL are merely thin layers of Java over the underlying OpenAL, so I seriously doubt there is any performance difference between the two libraries.

What kind of problem were you having with the fading effect?  Like I was talking about in my last post, OpenAL fades the sound away really fast (it becomes silent at something small like "distance = 10").  I can make that distance larger if you need it to be.  Just tell me what is a good distance for the volume to fade away.

Also, if your sound does not seem to be fading at all, you are probably using a "stereo" sound.  Fading only works for "mono" sounds.

I could write you a distance fader if you need one for using stereo sounds.  I actually already wrote one (before I figured out that I was supposed to be using mono sounds instead of stereo ones).  The only reason I took that code out of the SoundManager, is that it affects the overall volume of the sound coming out of BOTH speakers -- it isn't true 3D sound, because it doesn't fade between the left and right speakers depending on where the sound is in relation to the listener.  The OpenAL functionality that I am now using in the SoundManager class does a much better job, and it is true 3D sound.  I'll do my best to get it working for you, so you'll have really good sound for your project.

838
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 08, 2008, 05:09:32 am »
Ok, I've worked out all the kinks.  Only thing to remember, is you have to use "mono" .wav files for the 3D effects to work.  "Stereo" files will just play at normal volume without any fading between speakers (this is a "feature" of OpenAL).

8) Here is the Sound Manager:
Code: [Select]
package Sounds;

import java.io.InputStream;

import java.nio.IntBuffer;
import java.nio.FloatBuffer;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.util.WaveData;

public class SoundManager
{   
    // Global stores for the sounds:
    private HashMap<String, IntBuffer> buffersMap;  // (name, buffer) pairs
    private HashMap<String, IntBuffer> sourcesMap;  // (name, buffer) pairs
   
    private FloatBuffer listenerPosition;  // Listener's position
    private FloatBuffer listenerOrientation;  // Listener's orientation
    private FloatBuffer listenerVelocity;  // Listener's velocity
   
    private float listenerAngle = 0;  // listener's angle (in radians)
   
    public SoundManager()
    {
        buffersMap = new HashMap<String, IntBuffer>();
        sourcesMap = new HashMap<String, IntBuffer>();
       
        initOpenAL();
        initListener();
    }
    private void initOpenAL()
    {
        try
        {
            AL.create();
        }
        catch( LWJGLException e )
        {
            e.printStackTrace();
            return;
        }
        AL10.alGetError();
    }   
   
    // Position and orientate the listener:
    private void initListener()
    {
        // Set the listener's initial position:
        listenerPosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerPosition.flip();
       
        // Set the listener's initial orientation:
        // The first 3 elements are the "look at" point
        // The second 3 elements are the "up direction"
        listenerOrientation = BufferUtils.createFloatBuffer( 6 ).put (
            new float[] { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } );
        listenerOrientation.flip();
       
        // Set the listener's initial velocity:
        listenerVelocity = BufferUtils.createFloatBuffer( 3 ).put (
            new float[] { 0.0f, 0.0f, 0.0f } );
        listenerVelocity.flip();
       
        AL10.alListener( AL10.AL_POSITION, listenerPosition );
        AL10.alListener( AL10.AL_VELOCITY, listenerVelocity );
        AL10.alListener( AL10.AL_ORIENTATION, listenerOrientation );
    }
   
    public void cleanUp()
    {
        Set<String> keys = sourcesMap.keySet();
        Iterator<String> iter = keys.iterator();
       
        String name;
        IntBuffer buffer, source;
        while( iter.hasNext() )
        {
            name = iter.next();
           
            source = sourcesMap.get( name );
            System.out.println( "Stopping " + name );
            AL10.alSourceStop( source );
            AL10.alDeleteSources( source );
           
            buffer = buffersMap.get( name );           
            AL10.alDeleteBuffers( buffer );
        }
    }
   
    public boolean load( String name, boolean toLoop )
    {
        if( sourcesMap.get( name ) != null )
        {
            System.out.println( name + " already loaded" );
            return true;
        }
       
        IntBuffer buffer = initBuffer( name );
        if( buffer == null )
            return false;
       
        IntBuffer source = initSource( name, buffer, toLoop );
       
        if( source == null )
        {
            // no need for the buffer anymore
            AL10.alDeleteBuffers( buffer );
            return false;
        }
       
        if( toLoop )
            System.out.println( "Looping source created for " + name );
        else
            System.out.println( "Source created for " + name );
       
        buffersMap.put( name, buffer );
        sourcesMap.put( name, source );
       
        return true;
    }
       
    public boolean load( String name, float x, float y, float z, boolean toLoop )
    {
        if( load( name, toLoop ) )
            return setPos( name, x, y, z );
        else
            return false;
    }
   
    // return a handle to the given resource
    private InputStream getResource( String resourceName )
    {
        return getClass().getClassLoader().getResourceAsStream( resourceName );
    }
   
    // Load a file, and create a buffer for it:
    private IntBuffer initBuffer( String filename )
    {
        WaveData waveFile = WaveData.create( getResource( "Sounds/" + filename ) );
       
        IntBuffer buffer = BufferUtils.createIntBuffer( 1 );
        AL10.alGenBuffers( buffer );
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.out.println( "Error loading file: " + filename );
            return null;
        }
        AL10.alBufferData( buffer.get( 0 ), waveFile.format, waveFile.data, waveFile.samplerate );
        return buffer;
    }
   
    // Create a source (a point in space that makes sound):
    private IntBuffer initSource( String name, IntBuffer buffer, boolean toLoop )
    {
        IntBuffer source = BufferUtils.createIntBuffer( 1 );
        AL10.alGenSources( source );
       
        // Check for errors:
        if( AL10.alGetError() != AL10.AL_NO_ERROR )
        {
            System.out.println( "Error creating a source for: " + name );
            return null;
        }       
       
        // Position the source at the origin:
        FloatBuffer sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        sourcePosition.flip();
       
        // The source has no initial velocity:
        FloatBuffer sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { 0.0f, 0.0f, 0.0f } );
        sourceVelocity.flip();

        AL10.alSourcei( source.get( 0 ), AL10.AL_BUFFER, buffer.get(0) );
        AL10.alSourcef( source.get( 0 ), AL10.AL_PITCH, 1.0f );
        AL10.alSourcef( source.get( 0 ), AL10.AL_GAIN, 1.0f );
        AL10.alSource( source.get( 0 ), AL10.AL_POSITION, sourcePosition );
        AL10.alSource( source.get( 0 ), AL10.AL_VELOCITY, sourceVelocity );
       
        if( toLoop )
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_TRUE );  // looping
        else
            AL10.alSourcei( source.get( 0 ), AL10.AL_LOOPING, AL10.AL_FALSE );  // looping
       
        return source;
    }
   
    // Move the named sound to (x, y, z):
    public boolean setPos( String name, float x, float y, float z )
    {
        IntBuffer source = sourcesMap.get( name );
        if( source == null )
        {
            System.out.println( "No source found for " + name );
            return false;
        }
       
        // Create a FloatBuffer with the given coordinates:
        FloatBuffer sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
            new float[] { x, y, z } );
        sourcePosition.flip();
       
        AL10.alSource( source.get( 0 ), AL10.AL_POSITION, sourcePosition );
        return true;
    }
   
    public boolean play( String name )
    {
        IntBuffer source = sourcesMap.get( name );
        if( source == null )
        {
            System.out.println( "No source found for " + name );
            return false;
        }
       
        AL10.alSourcePlay( source.get( 0 ) );
        return true;
    }
   
    // move the listener by (x, z) step
    public void moveListener( float xStep, float zStep )
    {
        float x = listenerPosition.get( 0 ) + xStep;
        float z = listenerPosition.get( 2 ) + zStep;
        setListenerPos( x, z );
    }
   
    // position the listener at (xNew, zNew)
    public void setListenerPos( float xNew, float zNew )
    {
        float xOffset = xNew - listenerPosition.get( 0 );
        float zOffset = zNew - listenerPosition.get( 2 );
       
        // We are not changing the y-coord:
        // ( Listener only moves over XZ plane )
        listenerPosition.put( new float[] {xNew, 0.0f, zNew} );
        listenerPosition.flip();
       
        AL10.alListener( AL10.AL_POSITION, listenerPosition );  // update the listener's position
       
        // Keep the listener facing the same direction by
        // moving the "look at" point by the offset values:
        listenerOrientation.put( 0, listenerOrientation.get( 0 ) + xOffset );
        listenerOrientation.put( 2, listenerOrientation.get( 2 ) + zOffset );
       
        AL10.alListener( AL10.AL_ORIENTATION, listenerOrientation );  // update the listener's orientation
    }
   
    // turn the listener counterclockwise by "angle" radians
    public void turnListener( float angle )
    {
        setListenerOrientation( listenerAngle + angle );
    }
   
    // set the listener's orientation to be "angle" radians
    // in the counterclockwise direction around the y-axis
    public void setListenerOrientation( float angle )
    {
        listenerAngle = angle;
       
        float xOffset = -1.0f * (float) Math.sin( angle );
        float zOffset = -1.0f * (float) Math.cos( angle );
       
        // face in the (xLen, zLen) direction by adding the
        // offset values to the listener's "look at" point:
        listenerOrientation.put( 0, listenerOrientation.get( 0 ) + xOffset );
        listenerOrientation.put( 2, listenerOrientation.get( 2 ) + zOffset );
       
        AL10.alListener( AL10.AL_ORIENTATION, listenerOrientation );  // update the listener's orientation
    }
}

All you need to know to use this class:
Code: [Select]
SoundManager soundManager = new SoundManager();  // Create the Sound Manager

soundManager.load( soundName, true );  // load a sound (true = looping, false = play once)

soundManager.play( soundName );  // play the sound

/*** You can move the sound source ***/
soundManager.setPos( soundName, x, y, z );

/*** You can move the listener ***/
moveListener( xStep, zStep );  // move relative to current position
setListenerPos( x, z );  // move to the specified location

/*** And you can rotate the listener ***/
turnListener( angle );  // turn relative to current orientation
setListenerOrientation( float angle );  // look in the specified direction

soundManager.cleanUp();  // stop playing sounds and delete all buffers

Now that it actually works, I'll be happy to help you tweak it to your preference.  Some things that I could potentially change are:

1)  The fading distance.  Right now it is pretty short, but that is easy to change (It'll just require me to stick in a scalar value and some simple multiplication).  Just let me know what is a good distance for sounds to fade away.

2)  A method for playing a sound from more than one source location.  This would also be fairly straight-forward, if it's a feature you'll need for your program.  It would just require a call to another method to specify a unique name for each source.

3)  The ability to change the listener's Y coordinate.  This is totally doable, it would just require a little bit fancier math on my part.

4)  The listener's ability to "look" up or down (rotate around the X axis).  This is doable, but it might be difficult to come up with a user-friendly interface (You'd have to supply a "look-at point" and an "up direction".  Actually, it might not really be too bad, come to think of it).

5)  Different ways to load sound files (right now the sounds must be part of the jar).  Also easy to do, if this is something you require for your program.

Let me know if you need any of these capabilities in your program, or anything else I didn't think of, and I will make the necessary changes.  I will probably end up needing to do some of this stuff eventually anyway, when I am ready to start putting sound in the project I'm working on.

-- EDIT:  Oh, and one more thing:  currently, all sounds need to be compiled into the JAR, and located in the package "Sounds/".  If you want to stick them somewhere else, just change the Sound Manager's "initBuffer" method.

839
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 07, 2008, 02:18:32 am »
Today I switched the sound manager code over to the lwjgl binding of OpenAL (since jPCT uses lwjgl this seems more logical than using JOAL).  The two bindings are actually quite similar, so I had no trouble switching over.  I am even having the exact same problem I had with the JOAL version (sounds not getting quieter when they move further away).  I am getting help on the lwjgl forums, so I will post the working code when we get all the kinks worked out.  ;D

840
Support / Re: Any java 3d sound api instead of OpenAL
« on: March 06, 2008, 02:20:28 am »
Hey, I hadn't done a lot of testing on the SoundManager code I mentioned above (I have been only using it for 2D and not using the full functionality).  Since I got this code from a professional-looking book, I just assumed there weren't any problems.  Further tests show that sounds are not getting quieter when they move further from the listener.  It is probably related to a typo on my part - I am looking into it.  I did find a couple of minor typos in the code, but I haven't yet found the source of the problem.

-- EDIT:  Previously posted code contained errors, so I removed it. --

Pages: 1 ... 54 55 [56] 57 58