Skip to content

Commit b102aba

Browse files
authored
Merge branch 'jMonkeyEngine:master' into capdevon-ALAudioRenderer
2 parents a0d7b49 + 6995e22 commit b102aba

File tree

8 files changed

+657
-153
lines changed

8 files changed

+657
-153
lines changed

jme3-core/src/main/java/com/jme3/audio/Environment.java

Lines changed: 153 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2012 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -34,49 +34,80 @@
3434
import com.jme3.math.FastMath;
3535

3636
/**
37-
* Audio environment, for reverb effects.
37+
* Represents an audio environment, primarily used to define reverb effects.
38+
* This class provides parameters that correspond to the properties controllable
39+
* through the OpenAL EFX (Environmental Effects Extension) library.
40+
* By adjusting these parameters, developers can simulate various acoustic spaces
41+
* like rooms, caves, and concert halls, adding depth and realism to the audio experience.
42+
*
3843
* @author Kirill
3944
*/
4045
public class Environment {
4146

42-
private float airAbsorbGainHf = 0.99426f;
47+
/** High-frequency air absorption gain (0.0f to 1.0f). */
48+
private float airAbsorbGainHf = 0.99426f;
49+
/** Factor controlling room effect rolloff with distance. */
4350
private float roomRolloffFactor = 0;
44-
45-
private float decayTime = 1.49f;
46-
private float decayHFRatio = 0.54f;
47-
48-
private float density = 1.0f;
49-
private float diffusion = 0.3f;
50-
51-
private float gain = 0.316f;
52-
private float gainHf = 0.022f;
53-
54-
private float lateReverbDelay = 0.088f;
55-
private float lateReverbGain = 0.768f;
56-
57-
private float reflectDelay = 0.162f;
58-
private float reflectGain = 0.052f;
59-
60-
private boolean decayHfLimit = true;
61-
62-
public static final Environment Garage, Dungeon, Cavern, AcousticLab, Closet;
63-
64-
static {
65-
Garage = new Environment(1, 1, 1, 1, .9f, .5f, .751f, .0039f, .661f, .0137f);
66-
Dungeon = new Environment(.75f, 1, 1, .75f, 1.6f, 1, 0.95f, 0.0026f, 0.93f, 0.0103f);
67-
Cavern = new Environment(.5f, 1, 1, .5f, 2.25f, 1, .908f, .0103f, .93f, .041f);
68-
AcousticLab = new Environment(.5f, 1, 1, 1, .28f, 1, .87f, .002f, .81f, .008f);
69-
Closet = new Environment(1, 1, 1, 1, .15f, 1, .6f, .0025f, .5f, .0006f);
70-
}
71-
51+
/** Overall decay time of the reverberation (in seconds). */
52+
private float decayTime = 1.49f;
53+
/** Ratio of high-frequency decay time to overall decay time (0.0f to 1.0f). */
54+
private float decayHFRatio = 0.54f;
55+
/** Density of the medium affecting reverb smoothness (0.0f to 1.0f). */
56+
private float density = 1.0f;
57+
/** Diffusion of reflections affecting echo distinctness (0.0f to 1.0f). */
58+
private float diffusion = 0.3f;
59+
/** Overall gain of the environment effect (linear scale). */
60+
private float gain = 0.316f;
61+
/** High-frequency gain of the environment effect (linear scale). */
62+
private float gainHf = 0.022f;
63+
/** Delay time for late reverberation relative to early reflections (in seconds). */
64+
private float lateReverbDelay = 0.088f;
65+
/** Gain of the late reverberation (linear scale). */
66+
private float lateReverbGain = 0.768f;
67+
/** Delay time for the initial reflections (in seconds). */
68+
private float reflectDelay = 0.162f;
69+
/** Gain of the initial reflections (linear scale). */
70+
private float reflectGain = 0.052f;
71+
/** Flag limiting high-frequency decay by the overall decay time. */
72+
private boolean decayHfLimit = true;
73+
74+
public static final Environment Garage = new Environment(
75+
1, 1, 1, 1, .9f, .5f, .751f, .0039f, .661f, .0137f);
76+
public static final Environment Dungeon = new Environment(
77+
.75f, 1, 1, .75f, 1.6f, 1, 0.95f, 0.0026f, 0.93f, 0.0103f);
78+
public static final Environment Cavern = new Environment(
79+
.5f, 1, 1, .5f, 2.25f, 1, .908f, .0103f, .93f, .041f);
80+
public static final Environment AcousticLab = new Environment(
81+
.5f, 1, 1, 1, .28f, 1, .87f, .002f, .81f, .008f);
82+
public static final Environment Closet = new Environment(
83+
1, 1, 1, 1, .15f, 1, .6f, .0025f, .5f, .0006f);
84+
85+
/**
86+
* Utility method to convert an EAX decibel value to an amplitude factor.
87+
* EAX often expresses gain and attenuation in decibels scaled by 1000.
88+
* This method performs the reverse of that conversion to obtain a linear
89+
* amplitude value suitable for OpenAL.
90+
*
91+
* @param eaxDb The EAX decibel value (scaled by 1000).
92+
* @return The corresponding amplitude factor.
93+
*/
7294
private static float eaxDbToAmp(float eaxDb) {
7395
float dB = eaxDb / 2000f;
7496
return FastMath.pow(10f, dB);
7597
}
7698

99+
/**
100+
* Constructs a new, default {@code Environment}. The default values are
101+
* typically chosen to represent a neutral or common acoustic space.
102+
*/
77103
public Environment() {
78104
}
79105

106+
/**
107+
* Creates a new {@code Environment} as a copy of the provided {@code Environment}.
108+
*
109+
* @param source The {@code Environment} to copy the settings from.
110+
*/
80111
public Environment(Environment source) {
81112
this.airAbsorbGainHf = source.airAbsorbGainHf;
82113
this.roomRolloffFactor = source.roomRolloffFactor;
@@ -93,9 +124,24 @@ public Environment(Environment source) {
93124
this.decayHfLimit = source.decayHfLimit;
94125
}
95126

127+
/**
128+
* Creates a new {@code Environment} with the specified parameters. These parameters
129+
* directly influence the properties of the reverb effect as managed by OpenAL EFX.
130+
*
131+
* @param density The density of the medium.
132+
* @param diffusion The diffusion of the reflections.
133+
* @param gain Overall gain applied to the environment effect.
134+
* @param gainHf High-frequency gain applied to the environment effect.
135+
* @param decayTime The overall decay time of the reflected sound.
136+
* @param decayHf Ratio of high-frequency decay time to the overall decay time.
137+
* @param reflectGain Gain applied to the initial reflections.
138+
* @param reflectDelay Delay time for the initial reflections.
139+
* @param lateGain Gain applied to the late reverberation.
140+
* @param lateDelay Delay time for the late reverberation.
141+
*/
96142
public Environment(float density, float diffusion, float gain, float gainHf,
97-
float decayTime, float decayHf, float reflectGain,
98-
float reflectDelay, float lateGain, float lateDelay) {
143+
float decayTime, float decayHf, float reflectGain, float reflectDelay,
144+
float lateGain, float lateDelay) {
99145
this.decayTime = decayTime;
100146
this.decayHFRatio = decayHf;
101147
this.density = density;
@@ -108,6 +154,16 @@ public Environment(float density, float diffusion, float gain, float gainHf,
108154
this.reflectGain = reflectGain;
109155
}
110156

157+
/**
158+
* Creates a new {@code Environment} by interpreting an array of 28 float values
159+
* as an EAX preset. This constructor attempts to map the EAX preset values to
160+
* the corresponding OpenAL EFX parameters. Note that not all EAX parameters
161+
* have a direct equivalent in standard OpenAL EFX, so some values might be
162+
* approximated or ignored.
163+
*
164+
* @param e An array of 28 float values representing an EAX preset.
165+
* @throws IllegalArgumentException If the provided array does not have a length of 28.
166+
*/
111167
public Environment(float[] e) {
112168
if (e.length != 28)
113169
throw new IllegalArgumentException("Not an EAX preset");
@@ -254,27 +310,71 @@ public void setRoomRolloffFactor(float roomRolloffFactor) {
254310
}
255311

256312
@Override
257-
public boolean equals(Object env2) {
258-
if (env2 == null)
313+
public boolean equals(Object obj) {
314+
315+
if (!(obj instanceof Environment))
259316
return false;
260-
if (env2 == this)
317+
318+
if (obj == this)
261319
return true;
262-
if (!(env2 instanceof Environment))
263-
return false;
264320

265-
Environment e2 = (Environment) env2;
266-
return (e2.airAbsorbGainHf == airAbsorbGainHf
267-
&& e2.decayHFRatio == decayHFRatio
268-
&& e2.decayHfLimit == decayHfLimit
269-
&& e2.decayTime == decayTime
270-
&& e2.density == density
271-
&& e2.diffusion == diffusion
272-
&& e2.gain == gain
273-
&& e2.gainHf == gainHf
274-
&& e2.lateReverbDelay == lateReverbDelay
275-
&& e2.lateReverbGain == lateReverbGain
276-
&& e2.reflectDelay == reflectDelay
277-
&& e2.reflectGain == reflectGain
278-
&& e2.roomRolloffFactor == roomRolloffFactor);
279-
}
321+
Environment other = (Environment) obj;
322+
float epsilon = 1e-6f;
323+
324+
float[] thisFloats = {
325+
this.airAbsorbGainHf,
326+
this.decayHFRatio,
327+
this.decayTime,
328+
this.density,
329+
this.diffusion,
330+
this.gain,
331+
this.gainHf,
332+
this.lateReverbDelay,
333+
this.lateReverbGain,
334+
this.reflectDelay,
335+
this.reflectGain,
336+
this.roomRolloffFactor
337+
};
338+
339+
float[] otherFloats = {
340+
other.airAbsorbGainHf,
341+
other.decayHFRatio,
342+
other.decayTime,
343+
other.density,
344+
other.diffusion,
345+
other.gain,
346+
other.gainHf,
347+
other.lateReverbDelay,
348+
other.lateReverbGain,
349+
other.reflectDelay,
350+
other.reflectGain,
351+
other.roomRolloffFactor
352+
};
353+
354+
for (int i = 0; i < thisFloats.length; i++) {
355+
if (Math.abs(thisFloats[i] - otherFloats[i]) >= epsilon) {
356+
return false;
357+
}
358+
}
359+
360+
return this.decayHfLimit == other.decayHfLimit;
361+
}
362+
363+
@Override
364+
public int hashCode() {
365+
int result = (airAbsorbGainHf != +0.0f ? Float.floatToIntBits(airAbsorbGainHf) : 0);
366+
result = 31 * result + (roomRolloffFactor != +0.0f ? Float.floatToIntBits(roomRolloffFactor) : 0);
367+
result = 31 * result + (decayTime != +0.0f ? Float.floatToIntBits(decayTime) : 0);
368+
result = 31 * result + (decayHFRatio != +0.0f ? Float.floatToIntBits(decayHFRatio) : 0);
369+
result = 31 * result + (density != +0.0f ? Float.floatToIntBits(density) : 0);
370+
result = 31 * result + (diffusion != +0.0f ? Float.floatToIntBits(diffusion) : 0);
371+
result = 31 * result + (gain != +0.0f ? Float.floatToIntBits(gain) : 0);
372+
result = 31 * result + (gainHf != +0.0f ? Float.floatToIntBits(gainHf) : 0);
373+
result = 31 * result + (lateReverbDelay != +0.0f ? Float.floatToIntBits(lateReverbDelay) : 0);
374+
result = 31 * result + (lateReverbGain != +0.0f ? Float.floatToIntBits(lateReverbGain) : 0);
375+
result = 31 * result + (reflectDelay != +0.0f ? Float.floatToIntBits(reflectDelay) : 0);
376+
result = 31 * result + (reflectGain != +0.0f ? Float.floatToIntBits(reflectGain) : 0);
377+
result = 31 * result + (decayHfLimit ? 1 : 0);
378+
return result;
379+
}
280380
}

jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.vert

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void main(){
7676
texCoord2 = inTexCoord2;
7777
#endif
7878

79-
wPosition = (g_WorldMatrix * vec4(inPosition, 1.0)).xyz;
79+
wPosition = TransformWorld(modelSpacePos).xyz;
8080
wNormal = TransformWorldNormal(modelSpaceNorm);
8181

8282
wTangent = vec4(TransformWorldNormal(modelSpaceTan),inTangent.w);
Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -39,50 +39,70 @@
3939
import com.jme3.math.ColorRGBA;
4040
import com.jme3.math.Vector3f;
4141
import com.jme3.scene.Geometry;
42-
import com.jme3.scene.shape.Box;
42+
import com.jme3.scene.Mesh;
43+
import com.jme3.scene.debug.Grid;
44+
import com.jme3.scene.shape.Sphere;
4345

4446
public class TestAmbient extends SimpleApplication {
4547

46-
public static void main(String[] args) {
47-
TestAmbient test = new TestAmbient();
48-
test.start();
49-
}
48+
public static void main(String[] args) {
49+
TestAmbient test = new TestAmbient();
50+
test.start();
51+
}
5052

51-
@Override
52-
public void simpleInitApp() {
53-
float[] eax = new float[]{15, 38.0f, 0.300f, -1000, -3300, 0,
54-
1.49f, 0.54f, 1.00f, -2560, 0.162f, 0.00f, 0.00f,
55-
0.00f, -229, 0.088f, 0.00f, 0.00f, 0.00f, 0.125f, 1.000f,
56-
0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f};
57-
Environment env = new Environment(eax);
58-
audioRenderer.setEnvironment(env);
53+
private final float[] eax = {
54+
15, 38.0f, 0.300f, -1000, -3300, 0,
55+
1.49f, 0.54f, 1.00f, -2560, 0.162f, 0.00f, 0.00f,
56+
0.00f, -229, 0.088f, 0.00f, 0.00f, 0.00f, 0.125f, 1.000f,
57+
0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f
58+
};
5959

60-
AudioNode waves = new AudioNode(assetManager,
61-
"Sound/Environment/Ocean Waves.ogg", DataType.Buffer);
62-
waves.setPositional(true);
63-
waves.setLocalTranslation(new Vector3f(0, 0,0));
64-
waves.setMaxDistance(100);
65-
waves.setRefDistance(5);
60+
@Override
61+
public void simpleInitApp() {
62+
configureCamera();
6663

67-
AudioNode nature = new AudioNode(assetManager,
68-
"Sound/Environment/Nature.ogg", DataType.Stream);
69-
nature.setPositional(false);
70-
nature.setVolume(3);
71-
72-
waves.playInstance();
73-
nature.play();
74-
75-
// just a blue box to mark the spot
76-
Box box1 = new Box(.5f, .5f, .5f);
77-
Geometry player = new Geometry("Player", box1);
78-
Material mat1 = new Material(assetManager,
79-
"Common/MatDefs/Misc/Unshaded.j3md");
80-
mat1.setColor("Color", ColorRGBA.Blue);
81-
player.setMaterial(mat1);
82-
rootNode.attachChild(player);
83-
}
64+
Environment env = new Environment(eax);
65+
audioRenderer.setEnvironment(env);
8466

85-
@Override
86-
public void simpleUpdate(float tpf) {
87-
}
67+
AudioNode waves = new AudioNode(assetManager,
68+
"Sound/Environment/Ocean Waves.ogg", DataType.Buffer);
69+
waves.setPositional(true);
70+
waves.setLooping(true);
71+
waves.setReverbEnabled(true);
72+
rootNode.attachChild(waves);
73+
74+
AudioNode nature = new AudioNode(assetManager,
75+
"Sound/Environment/Nature.ogg", DataType.Stream);
76+
nature.setPositional(false);
77+
nature.setLooping(true);
78+
nature.setVolume(3);
79+
rootNode.attachChild(nature);
80+
81+
waves.play();
82+
nature.play();
83+
84+
// just a blue sphere to mark the spot
85+
Geometry marker = makeShape("Marker", new Sphere(16, 16, 1f), ColorRGBA.Blue);
86+
waves.attachChild(marker);
87+
88+
Geometry grid = makeShape("DebugGrid", new Grid(21, 21, 2), ColorRGBA.Gray);
89+
grid.center().move(0, 0, 0);
90+
rootNode.attachChild(grid);
91+
}
92+
93+
private void configureCamera() {
94+
flyCam.setMoveSpeed(25f);
95+
flyCam.setDragToRotate(true);
96+
97+
cam.setLocation(Vector3f.UNIT_XYZ.mult(5f));
98+
cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
99+
}
100+
101+
private Geometry makeShape(String name, Mesh mesh, ColorRGBA color) {
102+
Geometry geo = new Geometry(name, mesh);
103+
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
104+
mat.setColor("Color", color);
105+
geo.setMaterial(mat);
106+
return geo;
107+
}
88108
}

0 commit comments

Comments
 (0)