Added support for observing sound resolution; type-safetified.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4021 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2006-04-14 18:34:08 +00:00
parent 3c6ac7ac67
commit 79be7ebd1b
2 changed files with 55 additions and 17 deletions
+36 -6
View File
@@ -32,6 +32,14 @@ import org.lwjgl.openal.AL10;
*/ */
public class Sound public class Sound
{ {
/** Used to await notification of the starting of a sound which may be
* delayed in loading. */
public interface StartObserver
{
/** Called when the specified sound has started playing. */
public void soundStarted (Sound sound);
}
/** /**
* Returns the buffer of audio data associated with this sound. * Returns the buffer of audio data associated with this sound.
*/ */
@@ -109,7 +117,7 @@ public class Sound
*/ */
public boolean play (boolean allowDefer) public boolean play (boolean allowDefer)
{ {
return play(allowDefer, false); return play(allowDefer, false, null);
} }
/** /**
@@ -122,7 +130,18 @@ public class Sound
*/ */
public boolean loop (boolean allowDefer) public boolean loop (boolean allowDefer)
{ {
return play(allowDefer, true); return play(allowDefer, true, null);
}
/**
* Plays this sound from the beginning, notifying the supplied observer
* when the audio starts.
*
* @param loop whether or not to loop the sampe until {@link #stop}ped.
*/
public void play (StartObserver obs, boolean loop)
{
play(true, loop, obs);
} }
/** /**
@@ -154,7 +173,8 @@ public class Sound
_buffer = buffer; _buffer = buffer;
} }
protected boolean play (boolean allowDefer, boolean loop) protected boolean play (
boolean allowDefer, final boolean loop, final StartObserver obs)
{ {
// if we're not ready to go... // if we're not ready to go...
if (!_buffer.isPlayable()) { if (!_buffer.isPlayable()) {
@@ -163,19 +183,29 @@ public class Sound
// resolved // resolved
_buffer.resolve(new ClipBuffer.Observer() { _buffer.resolve(new ClipBuffer.Observer() {
public void clipLoaded (ClipBuffer buffer) { public void clipLoaded (ClipBuffer buffer) {
play(false); play(false, loop, obs);
} }
public void clipFailed (ClipBuffer buffer) { public void clipFailed (ClipBuffer buffer) {
// ugh. nothing to do here but be sad // well, let's pretend like the sound started so that
// the observer isn't left hanging
if (obs != null) {
obs.soundStarted(Sound.this);
}
} }
}); });
return true;
} else { } else {
// sorry charlie... // sorry charlie...
return false; return false;
} }
} }
// let the observer know that (as far as they're concerned), we're
// started
if (obs != null) {
obs.soundStarted(this);
}
// if we do not already have a source, obtain one // if we do not already have a source, obtain one
if (_sourceId == -1) { if (_sourceId == -1) {
_sourceId = _group.acquireSource(this); _sourceId = _group.acquireSource(this);
@@ -129,9 +129,12 @@ public class SoundManager
} }
// configure our LRU map with a removal observer // configure our LRU map with a removal observer
_clips.setRemovalObserver(new LRUHashMap.RemovalObserver() { _clips.setRemovalObserver(
public void removedFromMap (LRUHashMap map, Object item) { new LRUHashMap.RemovalObserver<Comparable,ClipBuffer>() {
((ClipBuffer)item).dispose(); public void removedFromMap (LRUHashMap<Comparable,ClipBuffer> map,
ClipBuffer item) {
Log.debug("Flushing " + item.getKey());
item.dispose();
} }
}); });
@@ -152,10 +155,10 @@ public class SoundManager
protected ClipBuffer getClip (ClipProvider provider, String path) protected ClipBuffer getClip (ClipProvider provider, String path)
{ {
Comparable ckey = ClipBuffer.makeKey(provider, path); Comparable ckey = ClipBuffer.makeKey(provider, path);
ClipBuffer buffer = (ClipBuffer)_clips.get(ckey); ClipBuffer buffer = _clips.get(ckey);
if (buffer == null) { if (buffer == null) {
// check to see if this clip is currently loading // check to see if this clip is currently loading
buffer = (ClipBuffer)_loading.get(ckey); buffer = _loading.get(ckey);
if (buffer == null) { if (buffer == null) {
buffer = new ClipBuffer(this, provider, path); buffer = new ClipBuffer(this, provider, path);
_loading.put(ckey, buffer); _loading.put(ckey, buffer);
@@ -197,10 +200,12 @@ public class SoundManager
while (true) { while (true) {
final ClipBuffer buffer = (ClipBuffer)_toLoad.get(); final ClipBuffer buffer = (ClipBuffer)_toLoad.get();
try { try {
Log.debug("Loading " + buffer.getKey() + ".");
final Clip clip = buffer.load(); final Clip clip = buffer.load();
_rqueue.postRunnable(new Runnable() { _rqueue.postRunnable(new Runnable() {
public void run () { public void run () {
Comparable ckey = buffer.getKey(); Comparable ckey = buffer.getKey();
Log.debug("Loaded " + ckey + ".");
_loading.remove(ckey); _loading.remove(ckey);
if (buffer.bind(clip)) { if (buffer.bind(clip)) {
_clips.put(ckey, buffer); _clips.put(ckey, buffer);
@@ -228,10 +233,12 @@ public class SoundManager
protected RunQueue _rqueue; protected RunQueue _rqueue;
/** Contains a mapping of all currently-loading clips. */ /** Contains a mapping of all currently-loading clips. */
protected HashMap _loading = new HashMap(); protected HashMap<Comparable,ClipBuffer> _loading =
new HashMap<Comparable,ClipBuffer>();
/** Contains a mapping of all loaded clips. */ /** Contains a mapping of all loaded clips. */
protected LRUHashMap _clips = new LRUHashMap(DEFAULT_CACHE_SIZE, _sizer); protected LRUHashMap<Comparable,ClipBuffer> _clips =
new LRUHashMap<Comparable,ClipBuffer>(DEFAULT_CACHE_SIZE, _sizer);
/** Contains a queue of clip buffers waiting to be loaded. */ /** Contains a queue of clip buffers waiting to be loaded. */
protected Queue _toLoad; protected Queue _toLoad;
@@ -241,12 +248,13 @@ public class SoundManager
protected static SoundManager _soundmgr; protected static SoundManager _soundmgr;
/** Used to compute the in-memory size of sound samples. */ /** Used to compute the in-memory size of sound samples. */
protected static LRUHashMap.ItemSizer _sizer = new LRUHashMap.ItemSizer() { protected static LRUHashMap.ItemSizer<ClipBuffer> _sizer =
public int computeSize (Object item) { new LRUHashMap.ItemSizer<ClipBuffer>() {
return ((ClipBuffer)item).getSize(); public int computeSize (ClipBuffer item) {
return item.getSize();
} }
}; };
/** Default to a cache size of one megabyte. */ /** Default to a cache size of one megabyte. */
protected static final int DEFAULT_CACHE_SIZE = 1024 * 1024; protected static final int DEFAULT_CACHE_SIZE = 8 * 1024 * 1024;
} }