4aefa977b4
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@629 ed5b42cb-e716-0410-a449-f6a68f950b19
277 lines
7.7 KiB
Java
277 lines
7.7 KiB
Java
package com.threerings.media.sound;
|
|
|
|
import java.util.Set;
|
|
|
|
import com.google.common.collect.Sets;
|
|
|
|
import com.samskivert.util.Interval;
|
|
import com.samskivert.util.RunQueue;
|
|
|
|
/**
|
|
* Loads, plays and loops sounds.
|
|
*/
|
|
public abstract class SoundPlayer
|
|
{
|
|
/** A pan value indicating that a sound should play from the left only. */
|
|
public static final float PAN_LEFT = -1f;
|
|
|
|
/** A pan value indicating that a sound should play from the right only. */
|
|
public static final float PAN_RIGHT = 1f;
|
|
|
|
/** A pan value indicating that a sound should play from center. */
|
|
public static final float PAN_CENTER = 0f;
|
|
|
|
/**
|
|
* Create instances of this for your application to differentiate
|
|
* between different types of sounds.
|
|
*/
|
|
public static class SoundType
|
|
{
|
|
/**
|
|
* Construct a new SoundType.
|
|
* Which should be a static variable stashed somewhere for the entire application to share.
|
|
*
|
|
* @param strname a short string identifier, preferably without spaces.
|
|
*/
|
|
public SoundType (String strname)
|
|
{
|
|
_strname = strname;
|
|
}
|
|
|
|
@Override
|
|
public String toString ()
|
|
{
|
|
return _strname;
|
|
}
|
|
|
|
protected String _strname;
|
|
}
|
|
|
|
/**
|
|
* A control for sounds.
|
|
*/
|
|
public static interface Frob
|
|
{
|
|
/**
|
|
* Stop playing or looping the sound.
|
|
* At present, the granularity of this command is limited to the buffer size of the
|
|
* line spooler, or about 8k of data. Thus, if playing an 11khz sample, it could take
|
|
* 8/11ths of a second for the sound to actually stop playing.
|
|
*/
|
|
public void stop ();
|
|
|
|
/**
|
|
* Set the volume of the sound.
|
|
*/
|
|
public void setVolume (float vol);
|
|
|
|
/**
|
|
* Get the volume of this sound.
|
|
*/
|
|
public float getVolume ();
|
|
|
|
/**
|
|
* Set the pan value for the sound. Valid values are
|
|
* -1 for left-only, 0 is centered, all the way to +1 for right-only.
|
|
*/
|
|
public void setPan (float pan);
|
|
|
|
/**
|
|
* Get the pan value of this sound.
|
|
*/
|
|
public float getPan ();
|
|
}
|
|
|
|
/** The default sound type. */
|
|
public static final SoundType DEFAULT = new SoundType("default");
|
|
/**
|
|
* Shut the damn thing off.
|
|
*/
|
|
public abstract void shutdown ();
|
|
|
|
/**
|
|
* Returns a string summarizing our volume settings and disabled sound types.
|
|
*/
|
|
public String summarizeState ()
|
|
{
|
|
StringBuilder buf = new StringBuilder();
|
|
buf.append("clipVol=").append(_clipVol);
|
|
buf.append(", disabled=[");
|
|
int ii = 0;
|
|
for (SoundType soundType : _disabledTypes) {
|
|
if (ii++ > 0) {
|
|
buf.append(", ");
|
|
}
|
|
buf.append(soundType);
|
|
}
|
|
return buf.append("]").toString();
|
|
}
|
|
|
|
/**
|
|
* Is the specified soundtype enabled?
|
|
*/
|
|
public boolean isEnabled (SoundType type)
|
|
{
|
|
// by default, types are enabled..
|
|
return (!_disabledTypes.contains(type));
|
|
}
|
|
|
|
/**
|
|
* Is sound on and is the specified soundtype enabled?
|
|
*/
|
|
public boolean shouldPlay (SoundType type)
|
|
{
|
|
if (type == null) {
|
|
type = DEFAULT; // let the lazy kids play too
|
|
}
|
|
|
|
return _clipVol != 0f && isEnabled(type);
|
|
}
|
|
|
|
/**
|
|
* Turns on or off the specified sound type.
|
|
*/
|
|
public void setEnabled (SoundType type, boolean enabled)
|
|
{
|
|
if (enabled) {
|
|
_disabledTypes.remove(type);
|
|
} else {
|
|
_disabledTypes.add(type);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the volume for all sound clips.
|
|
*
|
|
* @param vol a volume parameter between 0f and 1f, inclusive.
|
|
*/
|
|
public void setClipVolume (float vol)
|
|
{
|
|
_clipVol = Math.max(0f, Math.min(1f, vol));
|
|
}
|
|
|
|
/**
|
|
* Get the volume for all sound clips.
|
|
*/
|
|
public float getClipVolume ()
|
|
{
|
|
return _clipVol;
|
|
}
|
|
|
|
/**
|
|
* Optionally lock each of these keys prior to playing, to guarantee that it will be quickly
|
|
* available for playing.
|
|
*/
|
|
public abstract void lock (String pkgPath, String... keys);
|
|
|
|
/**
|
|
*Unlock the specified sounds so that its resources can be freed.
|
|
*/
|
|
public abstract void unlock (String pkgPath, String... keys);
|
|
|
|
/**
|
|
* Play the specified sound as the specified type of sound, immediately. Note that a sound
|
|
* need not be locked prior to playing.
|
|
*
|
|
* @return true if the sound actually played, or false if its sound type was disabled or if
|
|
* sound is off altogether.
|
|
*/
|
|
public boolean play (SoundType type, String pkgPath, String key)
|
|
{
|
|
return play(type, pkgPath, key, 0, PAN_CENTER);
|
|
}
|
|
|
|
/**
|
|
* Play the specified sound as the specified type of sound, immediately, with the specified
|
|
* pan value. Note that a sound need not be locked prior to playing.
|
|
*
|
|
* @param pan a value from -1f (all left) to +1f (all right).
|
|
* @return true if the sound actually played, or false if its sound type was disabled or if
|
|
* sound is off altogether.
|
|
*/
|
|
public boolean play (SoundType type, String pkgPath, String key, float pan)
|
|
{
|
|
return play(type, pkgPath, key, 0, pan);
|
|
}
|
|
|
|
/**
|
|
* Play the specified sound after the specified delay.
|
|
* @param delay the delay in milliseconds.
|
|
* @return true if the sound actually played, or false if its sound type was disabled or if
|
|
* sound is off altogether.
|
|
*/
|
|
public boolean play (SoundType type, String pkgPath, String key, int delay)
|
|
{
|
|
return play(type, pkgPath, key, delay, PAN_CENTER);
|
|
}
|
|
|
|
/**
|
|
* Play the specified sound after the specified delay.
|
|
* @param delay the delay in milliseconds.
|
|
* @param pan a value from -1f (all left) to +1f (all right).
|
|
* @return true if the sound actually played, or false if its sound type was disabled or if
|
|
* sound is off altogether.
|
|
*/
|
|
public boolean play (SoundType type, final String pkgPath, final String key, int delay,
|
|
final float pan)
|
|
{
|
|
if (!shouldPlay(type)) {
|
|
return false;
|
|
}
|
|
|
|
if (delay > 0) {
|
|
new Interval(getSoundQueue()) {
|
|
@Override
|
|
public void expired () {
|
|
play(pkgPath, key, pan);
|
|
}
|
|
}.schedule(delay);
|
|
} else {
|
|
play(pkgPath, key, pan);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Play the specified sound after the specified delay.
|
|
* @param pan a value from -1f (all left) to +1f (all right).
|
|
*/
|
|
protected abstract void play (String pkgPath, String key, float pan);
|
|
|
|
/**
|
|
* Loop the specified sound, stopping as quickly as possible when stop is called.
|
|
*/
|
|
public Frob loop (SoundType type, String pkgPath, String key)
|
|
{
|
|
return loop(type, pkgPath, key, PAN_CENTER);
|
|
}
|
|
|
|
/**
|
|
* Loop the specified sound, stopping as quickly as possible when stop is called.
|
|
*/
|
|
public Frob loop (SoundType type, String pkgPath, String key, float pan)
|
|
{
|
|
if (!shouldPlay(type)) {
|
|
return null;
|
|
}
|
|
return loop(pkgPath, key, pan);
|
|
}
|
|
|
|
/**
|
|
* Loop the specified sound, stopping as quickly as possible when stop is called.
|
|
*/
|
|
protected abstract Frob loop (String pkgPath, String key, float pan);
|
|
|
|
/**
|
|
* Gets the run queue on which sound should be played. It defaults to {@link RunQueue#AWT}.
|
|
*/
|
|
protected abstract RunQueue getSoundQueue ();
|
|
|
|
/** Volume level for sound clips. */
|
|
protected float _clipVol = 1f;
|
|
|
|
/** A set of soundTypes for which sound is enabled. */
|
|
protected Set<SoundType> _disabledTypes = Sets.newHashSet();
|
|
|
|
}
|