- add generic AudioSource to abstract audio system away from AudioNode
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10416 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
df5afb1524
commit
22eb83fd9a
@ -60,7 +60,7 @@ import java.util.logging.Logger;
|
|||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
* @author Kirill Vainer
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public class AudioNode extends Node {
|
public class AudioNode extends Node implements AudioSource {
|
||||||
|
|
||||||
//Version #1 : AudioKey is now stored into "audio_key" instead of "key"
|
//Version #1 : AudioKey is now stored into "audio_key" instead of "key"
|
||||||
public static final int SAVABLE_VERSION = 1;
|
public static final int SAVABLE_VERSION = 1;
|
||||||
@ -71,7 +71,7 @@ public class AudioNode extends Node {
|
|||||||
protected Filter dryFilter;
|
protected Filter dryFilter;
|
||||||
protected AudioKey audioKey;
|
protected AudioKey audioKey;
|
||||||
protected transient AudioData data = null;
|
protected transient AudioData data = null;
|
||||||
protected transient volatile Status status = Status.Stopped;
|
protected transient volatile AudioSource.Status status = AudioSource.Status.Stopped;
|
||||||
protected transient volatile int channel = -1;
|
protected transient volatile int channel = -1;
|
||||||
protected Vector3f velocity = new Vector3f();
|
protected Vector3f velocity = new Vector3f();
|
||||||
protected boolean reverbEnabled = true;
|
protected boolean reverbEnabled = true;
|
||||||
@ -86,7 +86,9 @@ public class AudioNode extends Node {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>Status</code> indicates the current status of the audio node.
|
* <code>Status</code> indicates the current status of the audio node.
|
||||||
|
* @deprecated - use AudioSource.Status instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public enum Status {
|
public enum Status {
|
||||||
/**
|
/**
|
||||||
* The audio node is currently playing. This will be set if
|
* The audio node is currently playing. This will be set if
|
||||||
@ -223,7 +225,7 @@ public class AudioNode extends Node {
|
|||||||
* Do not use.
|
* Do not use.
|
||||||
*/
|
*/
|
||||||
public final void setChannel(int channel) {
|
public final void setChannel(int channel) {
|
||||||
if (status != Status.Stopped) {
|
if (status != AudioSource.Status.Stopped) {
|
||||||
throw new IllegalStateException("Can only set source id when stopped");
|
throw new IllegalStateException("Can only set source id when stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,14 +296,14 @@ public class AudioNode extends Node {
|
|||||||
* The status will be changed when either the {@link AudioNode#play() }
|
* The status will be changed when either the {@link AudioNode#play() }
|
||||||
* or {@link AudioNode#stop() } methods are called.
|
* or {@link AudioNode#stop() } methods are called.
|
||||||
*/
|
*/
|
||||||
public Status getStatus() {
|
public AudioSource.Status getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not use.
|
* Do not use.
|
||||||
*/
|
*/
|
||||||
public final void setStatus(Status status) {
|
public final void setStatus(AudioSource.Status status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,12 +401,16 @@ public class AudioNode extends Node {
|
|||||||
this.timeOffset = timeOffset;
|
this.timeOffset = timeOffset;
|
||||||
if (data instanceof AudioStream) {
|
if (data instanceof AudioStream) {
|
||||||
((AudioStream) data).setTime(timeOffset);
|
((AudioStream) data).setTime(timeOffset);
|
||||||
}else if(status == Status.Playing){
|
}else if(status == AudioSource.Status.Playing){
|
||||||
stop();
|
stop();
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3f getPosition() {
|
||||||
|
return getWorldTranslation();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The velocity of the audio node.
|
* @return The velocity of the audio node.
|
||||||
*
|
*
|
||||||
|
@ -47,17 +47,17 @@ public interface AudioRenderer {
|
|||||||
/**
|
/**
|
||||||
* Sets the environment, used for reverb effects.
|
* Sets the environment, used for reverb effects.
|
||||||
*
|
*
|
||||||
* @see AudioNode#setReverbEnabled(boolean)
|
* @see AudioSource#setReverbEnabled(boolean)
|
||||||
* @param env The environment to set.
|
* @param env The environment to set.
|
||||||
*/
|
*/
|
||||||
public void setEnvironment(Environment env);
|
public void setEnvironment(Environment env);
|
||||||
|
|
||||||
public void playSourceInstance(AudioNode src);
|
public void playSourceInstance(AudioSource src);
|
||||||
public void playSource(AudioNode src);
|
public void playSource(AudioSource src);
|
||||||
public void pauseSource(AudioNode src);
|
public void pauseSource(AudioSource src);
|
||||||
public void stopSource(AudioNode src);
|
public void stopSource(AudioSource src);
|
||||||
|
|
||||||
public void updateSourceParam(AudioNode src, AudioParam param);
|
public void updateSourceParam(AudioSource src, AudioParam param);
|
||||||
public void updateListenerParam(Listener listener, ListenerParam param);
|
public void updateListenerParam(Listener listener, ListenerParam param);
|
||||||
|
|
||||||
public void deleteFilter(Filter filter);
|
public void deleteFilter(Filter filter);
|
||||||
|
189
engine/src/core/com/jme3/audio/AudioSource.java
Normal file
189
engine/src/core/com/jme3/audio/AudioSource.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package com.jme3.audio;
|
||||||
|
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author normenhansen
|
||||||
|
*/
|
||||||
|
public interface AudioSource {
|
||||||
|
/**
|
||||||
|
* <code>Status</code> indicates the current status of the audio source.
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
/**
|
||||||
|
* The audio source is currently playing. This will be set if
|
||||||
|
* {@link AudioSource#play() } is called.
|
||||||
|
*/
|
||||||
|
Playing,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The audio source is currently paused.
|
||||||
|
*/
|
||||||
|
Paused,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The audio source is currently stopped.
|
||||||
|
* This will be set if {@link AudioSource#stop() } is called
|
||||||
|
* or the audio has reached the end of the file.
|
||||||
|
*/
|
||||||
|
Stopped,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use.
|
||||||
|
*/
|
||||||
|
public void setChannel(int channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use.
|
||||||
|
*/
|
||||||
|
public int getChannel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing the audio.
|
||||||
|
*/
|
||||||
|
public void play();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing an instance of this audio. This method can be used
|
||||||
|
* to play the same <code>AudioSource</code> multiple times. Note
|
||||||
|
* that changes to the parameters of this AudioSource will not effect the
|
||||||
|
* instances already playing.
|
||||||
|
*/
|
||||||
|
public void playInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The {#link Filter dry filter} that is set.
|
||||||
|
* @see AudioSource#setDryFilter(com.jme3.audio.Filter)
|
||||||
|
*/
|
||||||
|
public Filter getDryFilter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The {@link AudioData} set previously with
|
||||||
|
* {@link AudioSource#setAudioData(com.jme3.audio.AudioData, com.jme3.audio.AudioKey) }
|
||||||
|
* or any of the constructors that initialize the audio data.
|
||||||
|
*/
|
||||||
|
public AudioData getAudioData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not use.
|
||||||
|
*/
|
||||||
|
public void setStatus(Status status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The {@link Status} of the audio source.
|
||||||
|
* The status will be changed when either the {@link AudioSource#play() }
|
||||||
|
* or {@link AudioSource#stop() } methods are called.
|
||||||
|
*/
|
||||||
|
public Status getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if the audio will keep looping after it is done playing,
|
||||||
|
* otherwise, false.
|
||||||
|
* @see AudioSource#setLooping(boolean)
|
||||||
|
*/
|
||||||
|
public boolean isLooping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The pitch of the audio, also the speed of playback.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setPitch(float)
|
||||||
|
*/
|
||||||
|
public float getPitch();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The volume of this audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setVolume(float)
|
||||||
|
*/
|
||||||
|
public float getVolume();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the time offset in the sound sample when to start playing.
|
||||||
|
*/
|
||||||
|
public float getTimeOffset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The velocity of the audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setVelocity(com.jme3.math.Vector3f)
|
||||||
|
*/
|
||||||
|
public Vector3f getPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The velocity of the audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setVelocity(com.jme3.math.Vector3f)
|
||||||
|
*/
|
||||||
|
public Vector3f getVelocity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if reverb is enabled, otherwise false.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setReverbEnabled(boolean)
|
||||||
|
*/
|
||||||
|
public boolean isReverbEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Filter for the reverberations of this audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setReverbFilter(com.jme3.audio.Filter)
|
||||||
|
*/
|
||||||
|
public Filter getReverbFilter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Max distance for this audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setMaxDistance(float)
|
||||||
|
*/
|
||||||
|
public float getMaxDistance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The reference playing distance for the audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setRefDistance(float)
|
||||||
|
*/
|
||||||
|
public float getRefDistance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if the audio source is directional
|
||||||
|
*
|
||||||
|
* @see AudioSource#setDirectional(boolean)
|
||||||
|
*/
|
||||||
|
public boolean isDirectional();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The direction of this audio source.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setDirection(com.jme3.math.Vector3f)
|
||||||
|
*/
|
||||||
|
public Vector3f getDirection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The directional audio source, cone inner angle.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setInnerAngle(float)
|
||||||
|
*/
|
||||||
|
public float getInnerAngle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The directional audio source, cone outer angle.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setOuterAngle(float)
|
||||||
|
*/
|
||||||
|
public float getOuterAngle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if the audio source is positional.
|
||||||
|
*
|
||||||
|
* @see AudioSource#setPositional(boolean)
|
||||||
|
*/
|
||||||
|
public boolean isPositional();
|
||||||
|
|
||||||
|
}
|
@ -31,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.audio.joal;
|
package com.jme3.audio.joal;
|
||||||
|
|
||||||
import com.jme3.audio.AudioNode.Status;
|
import com.jme3.audio.AudioSource.Status;
|
||||||
import com.jme3.audio.*;
|
import com.jme3.audio.*;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
@ -61,7 +61,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);
|
private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);
|
||||||
private final byte[] arrayBuf = new byte[BUFFER_SIZE];
|
private final byte[] arrayBuf = new byte[BUFFER_SIZE];
|
||||||
private int[] channels;
|
private int[] channels;
|
||||||
private AudioNode[] chanSrcs;
|
private AudioSource[] chanSrcs;
|
||||||
private int nextChan = 0;
|
private int nextChan = 0;
|
||||||
private ArrayList<Integer> freeChans = new ArrayList<Integer>();
|
private ArrayList<Integer> freeChans = new ArrayList<Integer>();
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
@ -194,7 +194,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ib = BufferUtils.createIntBuffer(channels.length);
|
ib = BufferUtils.createIntBuffer(channels.length);
|
||||||
chanSrcs = new AudioNode[channels.length];
|
chanSrcs = new AudioSource[channels.length];
|
||||||
|
|
||||||
logger.log(Level.FINE, "AudioRenderer supports {0} channels", channels.length);
|
logger.log(Level.FINE, "AudioRenderer supports {0} channels", channels.length);
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
f.clearUpdateNeeded();
|
f.clearUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSourceParam(AudioNode src, AudioParam param) {
|
public void updateSourceParam(AudioSource src, AudioParam param) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -321,10 +321,10 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is a race condition in AudioNode that can
|
// There is a race condition in AudioSource that can
|
||||||
// cause this to be called for a node that has been
|
// cause this to be called for a node that has been
|
||||||
// detached from its channel. For example, setVolume()
|
// detached from its channel. For example, setVolume()
|
||||||
// called from the render thread may see that that AudioNode
|
// called from the render thread may see that that AudioSource
|
||||||
// still has a channel value but the audio thread may
|
// still has a channel value but the audio thread may
|
||||||
// clear that channel before setVolume() gets to call
|
// clear that channel before setVolume() gets to call
|
||||||
// updateSourceParam() (because the audio stopped playing
|
// updateSourceParam() (because the audio stopped playing
|
||||||
@ -343,7 +343,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f pos = src.getWorldTranslation();
|
Vector3f pos = src.getPosition();
|
||||||
al.alSource3f(id, ALConstants.AL_POSITION, pos.x, pos.y, pos.z);
|
al.alSource3f(id, ALConstants.AL_POSITION, pos.x, pos.y, pos.z);
|
||||||
break;
|
break;
|
||||||
case Velocity:
|
case Velocity:
|
||||||
@ -482,9 +482,9 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSourceParams(int id, AudioNode src, boolean forceNonLoop) {
|
private void setSourceParams(int id, AudioSource src, boolean forceNonLoop) {
|
||||||
if (src.isPositional()) {
|
if (src.isPositional()) {
|
||||||
Vector3f pos = src.getWorldTranslation();
|
Vector3f pos = src.getPosition();
|
||||||
Vector3f vel = src.getVelocity();
|
Vector3f vel = src.getVelocity();
|
||||||
al.alSource3f(id, ALConstants.AL_POSITION, pos.x, pos.y, pos.z);
|
al.alSource3f(id, ALConstants.AL_POSITION, pos.x, pos.y, pos.z);
|
||||||
al.alSource3f(id, ALConstants.AL_VELOCITY, vel.x, vel.y, vel.z);
|
al.alSource3f(id, ALConstants.AL_VELOCITY, vel.x, vel.y, vel.z);
|
||||||
@ -731,7 +731,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
private void clearChannel(int index) {
|
private void clearChannel(int index) {
|
||||||
// make room at this channel
|
// make room at this channel
|
||||||
if (chanSrcs[index] != null) {
|
if (chanSrcs[index] != null) {
|
||||||
AudioNode src = chanSrcs[index];
|
AudioSource src = chanSrcs[index];
|
||||||
|
|
||||||
int sourceId = channels[index];
|
int sourceId = channels[index];
|
||||||
al.alSourceStop(sourceId);
|
al.alSourceStop(sourceId);
|
||||||
@ -750,7 +750,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
al.alSourcei(sourceId, AL.AL_DIRECT_FILTER, AL.AL_FILTER_NULL);
|
al.alSourcei(sourceId, AL.AL_DIRECT_FILTER, AL.AL_FILTER_NULL);
|
||||||
}
|
}
|
||||||
if (src.isPositional()) {
|
if (src.isPositional()) {
|
||||||
AudioNode pas = (AudioNode) src;
|
AudioSource pas = (AudioSource) src;
|
||||||
if (pas.isReverbEnabled() && supportEfx) {
|
if (pas.isReverbEnabled() && supportEfx) {
|
||||||
al.alSource3i(sourceId, AL.AL_AUXILIARY_SEND_FILTER, 0, 0, AL.AL_FILTER_NULL);
|
al.alSource3i(sourceId, AL.AL_AUXILIARY_SEND_FILTER, 0, 0, AL.AL_FILTER_NULL);
|
||||||
}
|
}
|
||||||
@ -770,7 +770,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < channels.length; i++) {
|
for (int i = 0; i < channels.length; i++) {
|
||||||
AudioNode src = chanSrcs[i];
|
AudioSource src = chanSrcs[i];
|
||||||
if (src == null) {
|
if (src == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -790,7 +790,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
ib.position(0).limit(1);
|
ib.position(0).limit(1);
|
||||||
al.alGetSourcei(sourceId, AL.AL_SOURCE_STATE, ib);
|
al.alGetSourcei(sourceId, AL.AL_SOURCE_STATE, ib);
|
||||||
int state = ib.get(0);
|
int state = ib.get(0);
|
||||||
boolean wantPlaying = src.getStatus() == AudioNode.Status.Playing;
|
boolean wantPlaying = src.getStatus() == AudioSource.Status.Playing;
|
||||||
boolean stopped = state == ALConstants.AL_STOPPED;
|
boolean stopped = state == ALConstants.AL_STOPPED;
|
||||||
|
|
||||||
if (streaming && wantPlaying) {
|
if (streaming && wantPlaying) {
|
||||||
@ -803,7 +803,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
} else {
|
} else {
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
// became inactive
|
// became inactive
|
||||||
src.setStatus(AudioNode.Status.Stopped);
|
src.setStatus(AudioSource.Status.Stopped);
|
||||||
src.setChannel(-1);
|
src.setChannel(-1);
|
||||||
clearChannel(i);
|
clearChannel(i);
|
||||||
freeChannel(i);
|
freeChannel(i);
|
||||||
@ -817,11 +817,11 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
boolean paused = state == ALConstants.AL_PAUSED;
|
boolean paused = state == ALConstants.AL_PAUSED;
|
||||||
|
|
||||||
// make sure OAL pause state & source state coincide
|
// make sure OAL pause state & source state coincide
|
||||||
assert (src.getStatus() == AudioNode.Status.Paused && paused) || (!paused);
|
assert (src.getStatus() == AudioSource.Status.Paused && paused) || (!paused);
|
||||||
|
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
if (boundSource) {
|
if (boundSource) {
|
||||||
src.setStatus(AudioNode.Status.Stopped);
|
src.setStatus(AudioSource.Status.Stopped);
|
||||||
src.setChannel(-1);
|
src.setChannel(-1);
|
||||||
}
|
}
|
||||||
clearChannel(i);
|
clearChannel(i);
|
||||||
@ -859,7 +859,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playSourceInstance(AudioNode src) {
|
public void playSourceInstance(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -902,7 +902,7 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playSource(AudioNode src) {
|
public void playSource(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -917,9 +917,9 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
|
|
||||||
//assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
|
//assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
|
||||||
|
|
||||||
if (src.getStatus() == AudioNode.Status.Playing) {
|
if (src.getStatus() == AudioSource.Status.Playing) {
|
||||||
return;
|
return;
|
||||||
} else if (src.getStatus() == AudioNode.Status.Stopped) {
|
} else if (src.getStatus() == AudioSource.Status.Stopped) {
|
||||||
|
|
||||||
// allocate channel to this source
|
// allocate channel to this source
|
||||||
int index = newChannel();
|
int index = newChannel();
|
||||||
@ -941,11 +941,11 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
al.alSourcePlay(channels[src.getChannel()]);
|
al.alSourcePlay(channels[src.getChannel()]);
|
||||||
src.setStatus(AudioNode.Status.Playing);
|
src.setStatus(AudioSource.Status.Playing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pauseSource(AudioNode src) {
|
public void pauseSource(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -958,16 +958,16 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.getStatus() == AudioNode.Status.Playing) {
|
if (src.getStatus() == AudioSource.Status.Playing) {
|
||||||
assert src.getChannel() != -1;
|
assert src.getChannel() != -1;
|
||||||
|
|
||||||
al.alSourcePause(channels[src.getChannel()]);
|
al.alSourcePause(channels[src.getChannel()]);
|
||||||
src.setStatus(AudioNode.Status.Paused);
|
src.setStatus(AudioSource.Status.Paused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopSource(AudioNode src) {
|
public void stopSource(AudioSource src) {
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
try {
|
try {
|
||||||
@ -979,11 +979,11 @@ public class JoalAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.getStatus() != AudioNode.Status.Stopped) {
|
if (src.getStatus() != AudioSource.Status.Stopped) {
|
||||||
int chan = src.getChannel();
|
int chan = src.getChannel();
|
||||||
assert chan != -1; // if it's not stopped, must have id
|
assert chan != -1; // if it's not stopped, must have id
|
||||||
|
|
||||||
src.setStatus(AudioNode.Status.Stopped);
|
src.setStatus(AudioSource.Status.Stopped);
|
||||||
src.setChannel(-1);
|
src.setChannel(-1);
|
||||||
clearChannel(chan);
|
clearChannel(chan);
|
||||||
freeChannel(chan);
|
freeChannel(chan);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.audio.lwjgl;
|
package com.jme3.audio.lwjgl;
|
||||||
|
|
||||||
import com.jme3.audio.AudioNode.Status;
|
import com.jme3.audio.AudioSource.Status;
|
||||||
import com.jme3.audio.*;
|
import com.jme3.audio.*;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.util.BufferUtils;
|
import com.jme3.util.BufferUtils;
|
||||||
@ -61,7 +61,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);
|
private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);
|
||||||
private final byte[] arrayBuf = new byte[BUFFER_SIZE];
|
private final byte[] arrayBuf = new byte[BUFFER_SIZE];
|
||||||
private int[] channels;
|
private int[] channels;
|
||||||
private AudioNode[] chanSrcs;
|
private AudioSource[] chanSrcs;
|
||||||
private int nextChan = 0;
|
private int nextChan = 0;
|
||||||
private ArrayList<Integer> freeChans = new ArrayList<Integer>();
|
private ArrayList<Integer> freeChans = new ArrayList<Integer>();
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
@ -156,10 +156,10 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
ALCdevice device = AL.getDevice();
|
ALCdevice device = AL.getDevice();
|
||||||
String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER);
|
String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER);
|
||||||
|
|
||||||
logger.log(Level.FINER, "Audio Device: {0}", deviceName);
|
logger.log(Level.INFO, "Audio Device: {0}", deviceName);
|
||||||
logger.log(Level.FINER, "Audio Vendor: {0}", alGetString(AL_VENDOR));
|
logger.log(Level.INFO, "Audio Vendor: {0}", alGetString(AL_VENDOR));
|
||||||
logger.log(Level.FINER, "Audio Renderer: {0}", alGetString(AL_RENDERER));
|
logger.log(Level.INFO, "Audio Renderer: {0}", alGetString(AL_RENDERER));
|
||||||
logger.log(Level.FINER, "Audio Version: {0}", alGetString(AL_VERSION));
|
logger.log(Level.INFO, "Audio Version: {0}", alGetString(AL_VERSION));
|
||||||
|
|
||||||
// Find maximum # of sources supported by this implementation
|
// Find maximum # of sources supported by this implementation
|
||||||
ArrayList<Integer> channelList = new ArrayList<Integer>();
|
ArrayList<Integer> channelList = new ArrayList<Integer>();
|
||||||
@ -178,9 +178,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ib = BufferUtils.createIntBuffer(channels.length);
|
ib = BufferUtils.createIntBuffer(channels.length);
|
||||||
chanSrcs = new AudioNode[channels.length];
|
chanSrcs = new AudioSource[channels.length];
|
||||||
|
|
||||||
logger.log(Level.FINE, "AudioRenderer supports {0} channels", channels.length);
|
logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length);
|
||||||
|
|
||||||
supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX");
|
supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX");
|
||||||
if (supportEfx) {
|
if (supportEfx) {
|
||||||
@ -190,11 +190,11 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
ib.position(0).limit(1);
|
ib.position(0).limit(1);
|
||||||
ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib);
|
ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib);
|
||||||
int minor = ib.get(0);
|
int minor = ib.get(0);
|
||||||
logger.log(Level.FINE, "Audio effect extension version: {0}.{1}", new Object[]{major, minor});
|
logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor});
|
||||||
|
|
||||||
ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib);
|
ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib);
|
||||||
auxSends = ib.get(0);
|
auxSends = ib.get(0);
|
||||||
logger.log(Level.FINE, "Audio max auxilary sends: {0}", auxSends);
|
logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends);
|
||||||
|
|
||||||
// create slot
|
// create slot
|
||||||
ib.position(0).limit(1);
|
ib.position(0).limit(1);
|
||||||
@ -282,7 +282,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
f.clearUpdateNeeded();
|
f.clearUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSourceParam(AudioNode src, AudioParam param) {
|
public void updateSourceParam(AudioSource src, AudioParam param) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -295,10 +295,10 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is a race condition in AudioNode that can
|
// There is a race condition in AudioSource that can
|
||||||
// cause this to be called for a node that has been
|
// cause this to be called for a node that has been
|
||||||
// detached from its channel. For example, setVolume()
|
// detached from its channel. For example, setVolume()
|
||||||
// called from the render thread may see that that AudioNode
|
// called from the render thread may see that that AudioSource
|
||||||
// still has a channel value but the audio thread may
|
// still has a channel value but the audio thread may
|
||||||
// clear that channel before setVolume() gets to call
|
// clear that channel before setVolume() gets to call
|
||||||
// updateSourceParam() (because the audio stopped playing
|
// updateSourceParam() (because the audio stopped playing
|
||||||
@ -317,7 +317,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f pos = src.getWorldTranslation();
|
Vector3f pos = src.getPosition();
|
||||||
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
|
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
|
||||||
break;
|
break;
|
||||||
case Velocity:
|
case Velocity:
|
||||||
@ -456,9 +456,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSourceParams(int id, AudioNode src, boolean forceNonLoop) {
|
private void setSourceParams(int id, AudioSource src, boolean forceNonLoop) {
|
||||||
if (src.isPositional()) {
|
if (src.isPositional()) {
|
||||||
Vector3f pos = src.getWorldTranslation();
|
Vector3f pos = src.getPosition();
|
||||||
Vector3f vel = src.getVelocity();
|
Vector3f vel = src.getVelocity();
|
||||||
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
|
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
|
||||||
alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);
|
alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);
|
||||||
@ -704,7 +704,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
private void clearChannel(int index) {
|
private void clearChannel(int index) {
|
||||||
// make room at this channel
|
// make room at this channel
|
||||||
if (chanSrcs[index] != null) {
|
if (chanSrcs[index] != null) {
|
||||||
AudioNode src = chanSrcs[index];
|
AudioSource src = chanSrcs[index];
|
||||||
|
|
||||||
int sourceId = channels[index];
|
int sourceId = channels[index];
|
||||||
alSourceStop(sourceId);
|
alSourceStop(sourceId);
|
||||||
@ -723,7 +723,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL);
|
alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL);
|
||||||
}
|
}
|
||||||
if (src.isPositional()) {
|
if (src.isPositional()) {
|
||||||
AudioNode pas = (AudioNode) src;
|
AudioSource pas = (AudioSource) src;
|
||||||
if (pas.isReverbEnabled() && supportEfx) {
|
if (pas.isReverbEnabled() && supportEfx) {
|
||||||
AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);
|
AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);
|
||||||
}
|
}
|
||||||
@ -743,7 +743,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < channels.length; i++) {
|
for (int i = 0; i < channels.length; i++) {
|
||||||
AudioNode src = chanSrcs[i];
|
AudioSource src = chanSrcs[i];
|
||||||
if (src == null) {
|
if (src == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -830,7 +830,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playSourceInstance(AudioNode src) {
|
public void playSourceInstance(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -873,7 +873,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playSource(AudioNode src) {
|
public void playSource(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -916,7 +916,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pauseSource(AudioNode src) {
|
public void pauseSource(AudioSource src) {
|
||||||
checkDead();
|
checkDead();
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
@ -938,7 +938,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopSource(AudioNode src) {
|
public void stopSource(AudioSource src) {
|
||||||
synchronized (threadLock) {
|
synchronized (threadLock) {
|
||||||
while (!threadLock.get()) {
|
while (!threadLock.get()) {
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user