Added an AudioContext to hold the thread local audio

renderer as set by the application update().  a) this
ensures that the audio node must be updated on the render
thread like everything else, b) it means that audio node
doesn't need to juggle its own reference to AudioRenderer
since from the right thread it can always get at it.


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7873 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
PSp..om 14 years ago
parent 27265b1149
commit 287bc0167c
  1. 5
      engine/src/core/com/jme3/app/Application.java
  2. 51
      engine/src/core/com/jme3/audio/AudioContext.java
  3. 114
      engine/src/core/com/jme3/audio/AudioNode.java

@ -41,6 +41,7 @@ import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.Renderer;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioContext;
import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Listener;
import com.jme3.input.InputManager;
@ -543,6 +544,10 @@ public class Application implements SystemListener {
* Callback from ContextListener.
*/
public void update(){
// Make sure the audio renderer is available to callables
AudioContext.setAudioRenderer(audioRenderer);
AppTask<?> task = taskQueue.poll();
toploop: do {
if (task == null) break;

@ -0,0 +1,51 @@
/*
* Copyright (c) 2009-2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.audio;
/**
* Holds render thread specific audio context information.
*
* @author Paul Speed
*/
public class AudioContext {
private static ThreadLocal<AudioRenderer> audioRenderer = new ThreadLocal<AudioRenderer>();
public static void setAudioRenderer( AudioRenderer ar ) {
audioRenderer.set(ar);
}
public static AudioRenderer getAudioRenderer() {
return audioRenderer.get();
}
}

@ -59,8 +59,6 @@ import java.io.IOException;
*/
public class AudioNode extends Node {
protected AudioRenderer renderer;
protected boolean loop = false;
protected float volume = 1;
protected float pitch = 1;
@ -105,7 +103,7 @@ public class AudioNode extends Node {
}
/**
* Serialization only. Do not use.
* Creates a new <code>AudioNode</code> without any audio data set.
*/
public AudioNode() {
}
@ -114,12 +112,10 @@ public class AudioNode extends Node {
* Creates a new <code>AudioNode</code> without any audio data set.
*
* @param audioRenderer The audio renderer to use for playing. Cannot be null.
*
* @deprecated AudioRenderer parameter is ignored.
*/
public AudioNode(AudioRenderer audioRenderer) {
if (audioRenderer == null)
throw new IllegalArgumentException("audioRenderer cannot be null");
this.renderer = audioRenderer;
}
/**
@ -128,9 +124,20 @@ public class AudioNode extends Node {
* @param audioRenderer The audio renderer to use for playing. Cannot be null.
* @param audioData The audio data contains the audio track to play.
* @param key The audio key that was used to load the AudioData
*
* @deprecated AudioRenderer parameter is ignored.
*/
public AudioNode(AudioRenderer audioRenderer, AudioData audioData, AudioKey key) {
this(audioRenderer);
setAudioData(audioData, key);
}
/**
* Creates a new <code>AudioNode</code> with the given data and key.
*
* @param audioData The audio data contains the audio track to play.
* @param key The audio key that was used to load the AudioData
*/
public AudioNode(AudioData audioData, AudioKey key) {
setAudioData(audioData, key);
}
@ -146,9 +153,27 @@ public class AudioNode extends Node {
* the stream cache is used. When enabled, the audio stream will
* be read entirely but not decoded, allowing features such as
* seeking, looping and determining duration.
*
* @deprecated AudioRenderer parameter is ignored.
*/
public AudioNode(AudioRenderer audioRenderer, AssetManager assetManager, String name, boolean stream, boolean streamCache) {
this(audioRenderer);
this.key = new AudioKey(name, stream, streamCache);
this.data = (AudioData) assetManager.loadAsset(key);
}
/**
* Creates a new <code>AudioNode</code> with the given audio file.
*
* @param assetManager The asset manager to use to load the audio file
* @param name The filename of the audio file
* @param stream If true, the audio will be streamed gradually from disk,
* otherwise, it will be buffered.
* @param streamCache If stream is also true, then this specifies if
* the stream cache is used. When enabled, the audio stream will
* be read entirely but not decoded, allowing features such as
* seeking, looping and determining duration.
*/
public AudioNode(AssetManager assetManager, String name, boolean stream, boolean streamCache) {
this.key = new AudioKey(name, stream, streamCache);
this.data = (AudioData) assetManager.loadAsset(key);
}
@ -161,11 +186,27 @@ public class AudioNode extends Node {
* @param name The filename of the audio file
* @param stream If true, the audio will be streamed gradually from disk,
* otherwise, it will be buffered.
*
* @deprecated AudioRenderer parameter is ignored.
*/
public AudioNode(AudioRenderer audioRenderer, AssetManager assetManager, String name, boolean stream) {
this(audioRenderer, assetManager, name, stream, false);
}
/**
* Creates a new <code>AudioNode</code> with the given audio file.
*
* @param assetManager The asset manager to use to load the audio file
* @param name The filename of the audio file
* @param stream If true, the audio will be streamed gradually from disk,
* otherwise, it will be buffered.
*
* @deprecated AudioRenderer parameter is ignored.
*/
public AudioNode(AssetManager assetManager, String name, boolean stream) {
this(assetManager, name, stream, false);
}
/**
* Creates a new <code>AudioNode</code> with the given audio file.
*
@ -174,14 +215,31 @@ public class AudioNode extends Node {
* @param name The filename of the audio file
*/
public AudioNode(AudioRenderer audioRenderer, AssetManager assetManager, String name) {
this(audioRenderer, assetManager, name, false);
this(assetManager, name, false);
}
/**
* Creates a new <code>AudioNode</code> with the given audio file.
*
* @param assetManager The asset manager to use to load the audio file
* @param name The filename of the audio file
*/
public AudioNode(AssetManager assetManager, String name) {
this(assetManager, name, false);
}
protected AudioRenderer getRenderer() {
AudioRenderer result = AudioContext.getAudioRenderer();
if( result == null )
throw new IllegalStateException( "No audio renderer available, make sure call is being performed on render thread." );
return result;
}
/**
* Start playing the audio.
*/
public void play(){
renderer.playSource(this);
getRenderer().playSource(this);
}
/**
@ -191,14 +249,14 @@ public class AudioNode extends Node {
* instances already playing.
*/
public void playInstance(){
renderer.playSourceInstance(this);
getRenderer().playSourceInstance(this);
}
/**
* Stop playing the audio that was started with {@link AudioNode#play() }.
*/
public void stop(){
renderer.stopSource(this);
getRenderer().stopSource(this);
}
/**
@ -242,7 +300,7 @@ public class AudioNode extends Node {
public void setDryFilter(Filter dryFilter) {
this.dryFilter = dryFilter;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.DryFilter);
getRenderer().updateSourceParam(this, AudioParam.DryFilter);
}
/**
@ -304,7 +362,7 @@ public class AudioNode extends Node {
public void setLooping(boolean loop) {
this.loop = loop;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.Looping);
getRenderer().updateSourceParam(this, AudioParam.Looping);
}
/**
@ -330,7 +388,7 @@ public class AudioNode extends Node {
this.pitch = pitch;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.Pitch);
getRenderer().updateSourceParam(this, AudioParam.Pitch);
}
/**
@ -357,7 +415,7 @@ public class AudioNode extends Node {
this.volume = volume;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.Volume);
getRenderer().updateSourceParam(this, AudioParam.Volume);
}
/**
@ -400,7 +458,7 @@ public class AudioNode extends Node {
public void setVelocity(Vector3f velocity) {
this.velocity.set(velocity);
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.Velocity);
getRenderer().updateSourceParam(this, AudioParam.Velocity);
}
/**
@ -425,7 +483,7 @@ public class AudioNode extends Node {
public void setReverbEnabled(boolean reverbEnabled) {
this.reverbEnabled = reverbEnabled;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.ReverbEnabled);
getRenderer().updateSourceParam(this, AudioParam.ReverbEnabled);
}
/**
@ -450,7 +508,7 @@ public class AudioNode extends Node {
public void setReverbFilter(Filter reverbFilter) {
this.reverbFilter = reverbFilter;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.ReverbFilter);
getRenderer().updateSourceParam(this, AudioParam.ReverbFilter);
}
/**
@ -484,7 +542,7 @@ public class AudioNode extends Node {
this.maxDistance = maxDistance;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.MaxDistance);
getRenderer().updateSourceParam(this, AudioParam.MaxDistance);
}
/**
@ -513,7 +571,7 @@ public class AudioNode extends Node {
this.refDistance = refDistance;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.RefDistance);
getRenderer().updateSourceParam(this, AudioParam.RefDistance);
}
/**
@ -538,7 +596,7 @@ public class AudioNode extends Node {
public void setDirectional(boolean directional) {
this.directional = directional;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.IsDirectional);
getRenderer().updateSourceParam(this, AudioParam.IsDirectional);
}
/**
@ -560,7 +618,7 @@ public class AudioNode extends Node {
public void setDirection(Vector3f direction) {
this.direction = direction;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.Direction);
getRenderer().updateSourceParam(this, AudioParam.Direction);
}
/**
@ -581,7 +639,7 @@ public class AudioNode extends Node {
public void setInnerAngle(float innerAngle) {
this.innerAngle = innerAngle;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.InnerAngle);
getRenderer().updateSourceParam(this, AudioParam.InnerAngle);
}
/**
@ -602,7 +660,7 @@ public class AudioNode extends Node {
public void setOuterAngle(float outerAngle) {
this.outerAngle = outerAngle;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.OuterAngle);
getRenderer().updateSourceParam(this, AudioParam.OuterAngle);
}
/**
@ -625,7 +683,7 @@ public class AudioNode extends Node {
public void setPositional(boolean positional) {
this.positional = positional;
if (channel >= 0)
renderer.updateSourceParam(this, AudioParam.IsPositional);
getRenderer().updateSourceParam(this, AudioParam.IsPositional);
}
@Override
@ -638,7 +696,7 @@ public class AudioNode extends Node {
super.updateGeometricState();
if (updatePos && channel >= 0)
renderer.updateSourceParam(this, AudioParam.Position);
getRenderer().updateSourceParam(this, AudioParam.Position);
}
@Override

Loading…
Cancel
Save