Just need somekind of input on this tricky bit.
During the "conversion" I was looking at the EAX implementation. It's been some time since I made the initial implementation and comparing to the joal implementation, I went "whaaaat - why is my code *so* bloated compared to the "other" implementation???"
It all came down to this (the technical bit):
Eax has two calls:
ALenum EAXGet(const struct _GUID *propertySetID, ALuint property, ALuint source, ALvoid *value, ALuint size);
ALenum EAXSet(const struct _GUID *propertySetID, ALuint property, ALuint source, ALvoid *value, ALuint size);
*propertySetID - A pointer to the property set GUID of the object being g/set (a listener or a source)
property - The property being g/set
source - The ID of the source to be g/set
*value - A pointer to the value being returned/set
size - The size of the data storage area pointed to by *value
One for reading eax values, and one for writing. The following is an example of reading the 'DSPROPERTY_EAXLISTENER_ENVIRONMENT', that is the environment the listener is positioned in (ie. EAX_ENVIRONMENT_CAVE or EAX_ENVIRONMENT_CITY).
EAXGet(DSPROPSETID_EAX20_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, 0, &MyValue, sizeof(MyValue));
this is all fine and dandy. However the tricky bit is that there is also a property called 'DSPROPERTY_EAXLISTENER_ALLPARAMETERS'.
This property will read ALL the possible EAX values. Thus you would need a structure large enough to hold this, enter: 'EAXLISTENERPROPERTIES'
This struct has all the possible values to be set:
typedef struct _EAXLISTENERPROPERTIES
long lRoom; // room effect level at low frequencies
long lRoomHF; // room effect high-frequency level re. low frequency level
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
float flDecayTime; // reverberation decay time at low frequencies
float flDecayHFRatio; // high-frequency to low-frequency decay time ratio
long lReflections; // early reflections level relative to room effect
float flReflectionsDelay; // initial reflection delay time
long lReverb; // late reverberation level relative to room effect
float flReverbDelay; // late reverberation delay time relative to initial reflection
unsigned long dwEnvironment; // sets all listener properties
float flEnvironmentSize; // environment size in meters
float flEnvironmentDiffusion; // environment diffusion
float flAirAbsorptionHF; // change in level per meter at 5 kHz
unsigned long dwFlags; // modifies the behavior of properties
} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES;
Passing 'DSPROPERTY_EAXLISTENER_ALLPARAMETERS' to EAXGet instead of the environement property (DSPROPERTY_EAXLISTENER_ENVIRONMENT) would result in the instance of the above struct to get filled with all the current values.
So far so good.
So how do we implement this in Java?
Two possible solutions:
The simple solution (JOAL)
Pass a java.nio.Buffer to the eaxGet method. That property will then be written to the start of the Buffer. If you pass 'DSPROPERTY_EAXLISTENER_ALLPARAMETERS' all parameters will be written. Thus you need to be sure that the Buffer supplied is big enough.
I can already hear you all go, yeah - thats a neat solution - whats the problem with that?
This simple solution has one *huge* problem:
Suppose you do pass 'DSPROPERTY_EAXLISTENER_ALLPARAMETERS'. How would you then read the 'dwEnvironment' value?
The only way to do that, is to calculate the offset to it, that is (imaginary method in Java) sizeof(lRoom) + sizeof(lRoomHF) + + + and so forth. Right up untill 'flReverbDelay' at which you'd have the index. Now, as a programmer I would *very* much hate to do that shit every time!
The more advanced solution (LWJGL)
We have created an EAXBufferProperties and an EAXListenerProperties object that manages all of this (well most of it).
These classes have 'getEnvironment()' and 'setEnvironment(int environment)' which neatly calculates all of the offsets for you.
and when it comes time to actually reading/writing a value, you just pass the address of it's internal buffer to the eaxGet method (just like you would with joal). This works beatifully as long as you read and write using the 'ALLPARAMETERS' property EACH TIME. What I discovered today, is that if you do NOT pass the 'ALLPARAMETERS' flag, it will read/and write from the base offset (that is 'lRoom'). Thereby defeating the purpose of all the get/set methods on the EAXBufferProperties object.
So, now that I've got you all confused
, here's the actual question.
I want to fix this - either I do the JOAL method and add some public static int fields that hold the offset in the buffer:
ByteBuffer EAXListener = allocateByteBufferLargeEnough();
ByteBuffer Temp = ((ByteBuffer)EAXListener.position(EAX.POSITION_OF_ENVIRONMENT)).slice();
eaxGet(EAX.LISTENER_GUID, EAX.EAXLISTENER_ENVIRONMENT, source_id, Temp, EAX.SIZE_OF_ENVIRONMENT);
int value = Temp.getInt(0);
I could add (I'd still retain the old eaxG/Set methods, to allow the retrieval of single values using a scratch buffer) a
eaxGet method that took the actual EAXBufferProperties or EAXListenerProperties object, and manipulated that directly. Thus you would do:
(caveat, this could become static...)
EAXListenerProperties EAXListener = new EAXListenerProperties();
eaxGetListenerProperty(EAXListener, EAXListenerProperties.EAXLISTENER_ENVIRONMENT, source_id);
int value = EAXListener.getEnvironment();
Without trying to influence what you guys think, I think the later solution is *much* better, however this (ironically) is very un-LWJGL-like, in that it actually hides some complexity from you
It also implies that we need to have the usual:
- these could ofcourse be method overloaded (eaxGetProperty(Buffer/Listener))
I need/want some input on this before I proceed... I don't expect the huge turnup in this thread, since it is a wee bit technical and specific - but if *anyone* has *any* input I would gladly accept it...
ps. is there a lengthy post award?