From 6d901ddfe52f88644296985d1bbde27b748a7fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 29 Jul 2014 00:12:23 +0200 Subject: [PATCH] Fixed some audio issues, refactoring --- .../gamecore/audio/AudioModule.java | 99 +++++++++---------- .../gamecore/audio/DeferredAudio.java | 24 ++--- src/mightypork/gamecore/audio/IAudio.java | 77 ++++++++------- .../gamecore/audio/SoundRegistry.java | 37 +++---- ...{BaseAudioPlayer.java => AudioPlayer.java} | 81 ++++++++------- .../gamecore/audio/players/EffectPlayer.java | 56 ++++++----- .../gamecore/audio/players/LoopPlayer.java | 95 +++++++++--------- .../gamecore/graphics/GraphicsModule.java | 4 +- .../graphics/textures/TextureRegistry.java | 2 +- 9 files changed, 250 insertions(+), 225 deletions(-) rename src/mightypork/gamecore/audio/players/{BaseAudioPlayer.java => AudioPlayer.java} (67%) diff --git a/src/mightypork/gamecore/audio/AudioModule.java b/src/mightypork/gamecore/audio/AudioModule.java index eb0f3e6..54e4165 100644 --- a/src/mightypork/gamecore/audio/AudioModule.java +++ b/src/mightypork/gamecore/audio/AudioModule.java @@ -19,50 +19,50 @@ import mightypork.utils.math.constraints.vect.Vect; * @author Ondřej Hruška (MightyPork) */ public abstract class AudioModule extends BackendModule implements Updateable { - + /** * Set listener position * * @param pos listener position */ public abstract void setListenerPos(Vect pos); - - + + /** * Get current listener position * * @return listener position */ public abstract Vect getListenerPos(); - + // -- instance -- - + private final Volume masterVolume = new Volume(1D); private final Volume effectsVolume = new JointVolume(masterVolume); private final Volume loopsVolume = new JointVolume(masterVolume); - + private final List loopPlayers = new ArrayList<>(); private final List resources = new ArrayList<>(); - - + + @Override public void destroy() { for (final DeferredAudio r : resources) { r.destroy(); } - + deinitSoundSystem(); } - - + + /** * Deinitialize the soud system, release resources etc.
* Audio resources are already destroyed. */ protected abstract void deinitSoundSystem(); - - + + @Override public void update(double delta) { @@ -70,67 +70,64 @@ public abstract class AudioModule extends BackendModule implements Updateable { lp.update(delta); } } - - + + /** * Create effect resource * * @param resource resource path - * @param pitch default pitch (1 = unchanged) - * @param gain default gain (0-1) * @return player */ - public EffectPlayer createEffect(String resource, double pitch, double gain) + public EffectPlayer createEffect(String resource) { - return new EffectPlayer(createAudio(resource), pitch, gain, effectsVolume); + return new EffectPlayer(createAudioResource(resource), effectsVolume); } - - + + /** * Register loop resource (music / effect loop) * * @param resource resource path - * @param pitch default pitch (1 = unchanged) - * @param gain default gain (0-1) - * @param fadeIn default time for fadeIn - * @param fadeOut default time for fadeOut * @return player */ - public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut) + public LoopPlayer createLoop(String resource) { - final LoopPlayer p = new LoopPlayer(createAudio(resource), pitch, gain, loopsVolume); - p.setFadeTimes(fadeIn, fadeOut); + final LoopPlayer p = new LoopPlayer(createAudioResource(resource), loopsVolume); loopPlayers.add(p); return p; } - - + + /** * Create {@link DeferredAudio} for a resource, request deferred load and - * add to the resources list. + * add to the resources list.
+ * The method is accessed only from within this class, since the sound + * registry holds players, not the resources themselves. * * @param res a resource name * @return the resource * @throws IllegalArgumentException if resource is already registered */ - protected DeferredAudio createAudio(String res) + protected final DeferredAudio createAudioResource(String res) { final DeferredAudio a = doCreateResource(res); App.bus().send(new ResourceLoadRequest(a)); resources.add(a); return a; } - - + + /** - * Create a backend-specific deferred audio resource + * Create a backend-specific deferred audio resource.
+ * The actual resource instance should be created here. Registering, loading + * etc. is handled higher. * * @param res resource path * @return Deferred Audio */ protected abstract DeferredAudio doCreateResource(String res); - - + + /** * Fade out all loops (= fade out the currently playing loops) */ @@ -140,8 +137,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { p.fadeOut(); } } - - + + /** * Pause all loops (leave volume unchanged) */ @@ -151,8 +148,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { p.pause(); } } - - + + /** * Set level of master volume (volume multiplier) * @@ -162,8 +159,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { { masterVolume.set(volume); } - - + + /** * Set level of effects volume (volume multiplier) * @@ -173,8 +170,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { { effectsVolume.set(volume); } - - + + /** * Set level of loops volume (volume multiplier) * @@ -184,8 +181,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { { loopsVolume.set(volume); } - - + + /** * Get level of master volume (volume multiplier) * @@ -195,8 +192,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { { return masterVolume.get(); } - - + + /** * Get level of effects volume (volume multiplier) * @@ -206,8 +203,8 @@ public abstract class AudioModule extends BackendModule implements Updateable { { return effectsVolume.get(); } - - + + /** * Get level of loops volume (volume multiplier) * diff --git a/src/mightypork/gamecore/audio/DeferredAudio.java b/src/mightypork/gamecore/audio/DeferredAudio.java index c33f30f..c24c9bf 100644 --- a/src/mightypork/gamecore/audio/DeferredAudio.java +++ b/src/mightypork/gamecore/audio/DeferredAudio.java @@ -24,25 +24,25 @@ public abstract class DeferredAudio extends BaseDeferredResource implements IAud { super(resourceName); } - - + + @Override - public void play(double pitch, double gain, boolean loop) + public void play(double gain, double pitch, boolean loop) { - play(pitch, gain, loop, App.audio().getListenerPos()); + play(gain, pitch, loop, App.audio().getListenerPos()); } - - + + @Override - public void play(double pitch, double gain, boolean loop, double x, double y) + public void play(double gain, double pitch, boolean loop, double x, double y) { - play(pitch, gain, loop, x, y, App.audio().getListenerPos().z()); + play(gain, pitch, loop, x, y, App.audio().getListenerPos().z()); } - - + + @Override - public void play(double pitch, double gain, boolean loop, Vect pos) + public void play(double gain, double pitch, boolean loop, Vect pos) { - play(pitch, gain, loop, pos.x(), pos.y(), pos.z()); + play(gain, pitch, loop, pos.x(), pos.y(), pos.z()); } } diff --git a/src/mightypork/gamecore/audio/IAudio.java b/src/mightypork/gamecore/audio/IAudio.java index f4533fd..bf5e862 100644 --- a/src/mightypork/gamecore/audio/IAudio.java +++ b/src/mightypork/gamecore/audio/IAudio.java @@ -11,19 +11,19 @@ import mightypork.utils.math.constraints.vect.Vect; * @author Ondřej Hruška (MightyPork) */ public interface IAudio extends Destroyable { - + /** * Pause loop (remember position and stop playing) - if was looping */ void pauseLoop(); - - + + /** * Resume loop (if was paused) */ void resumeLoop(); - - + + /** * Adjust gain for the currently playing effect (can be used for fading * music) @@ -31,20 +31,20 @@ public interface IAudio extends Destroyable { * @param gain gain to set 0..1 */ void adjustGain(double gain); - - + + /** - * Stop audio playback + * Stop audio playback, free source. */ void stop(); - - + + /** * @return true if the audio is playing */ boolean isPlaying(); - - + + /** * @return trie if the audio is paused */ @@ -54,46 +54,55 @@ public interface IAudio extends Destroyable { /** * Play as sound effect at listener position * - * @param pitch pitch (1 = default) - * @param gain gain (0-1) + * @param gain gain + * @param pitch pitch * @param loop looping */ - void play(double pitch, double gain, boolean loop); - - + void play(double gain, double pitch, boolean loop); + + /** - * Play as sound effect at given X-Y position + * Play as sound effect at given position * - * @param pitch pitch (1 = default) - * @param gain gain (0-1) + * @param gain gain + * @param pitch pitch * @param loop looping * @param x * @param y + * @param z */ - void play(double pitch, double gain, boolean loop, double x, double y); - - + void play(double gain, double pitch, boolean loop, double x, double y, double z); + + /** - * Play as sound effect at given position + * Play as sound effect at given X-Y position * - * @param pitch pitch (1 = default) - * @param gain gain (0-1) + * @param gain gain + * @param pitch pitch * @param loop looping * @param x * @param y - * @param z */ - void play(double pitch, double gain, boolean loop, double x, double y, double z); - - + void play(double gain, double pitch, boolean loop, double x, double y); + + /** * Play as sound effect at given position * - * @param pitch pitch (1 = default) - * @param gain gain (0-1) + * @param gain gain + * @param pitch pitch * @param loop looping * @param pos coord */ - void play(double pitch, double gain, boolean loop, Vect pos); - + void play(double gain, double pitch, boolean loop, Vect pos); + + + /** + * Check if this audio is currently active (ie. playing or paused, not + * stopped) + * + * @return is active + */ + boolean isActive(); + } diff --git a/src/mightypork/gamecore/audio/SoundRegistry.java b/src/mightypork/gamecore/audio/SoundRegistry.java index cdaa153..898f5d3 100644 --- a/src/mightypork/gamecore/audio/SoundRegistry.java +++ b/src/mightypork/gamecore/audio/SoundRegistry.java @@ -6,7 +6,6 @@ import java.util.Map; import mightypork.gamecore.audio.players.EffectPlayer; import mightypork.gamecore.audio.players.LoopPlayer; -import mightypork.gamecore.core.App; /** @@ -15,41 +14,35 @@ import mightypork.gamecore.core.App; * @author Ondřej Hruška (MightyPork) */ public class SoundRegistry { - + private final Map effects = new HashMap<>(); private final Map loops = new HashMap<>(); - - + + /** * Register effect resource * * @param key sound key - * @param resource resource path - * @param pitch default pitch (1 = unchanged) - * @param gain default gain (0-1) + * @param effect the effect to add (Obtained from audio module) */ - public void addEffect(String key, String resource, double pitch, double gain) + public void addEffect(String key, EffectPlayer effect) { - effects.put(key, App.audio().createEffect(resource, pitch, gain)); + effects.put(key, effect); } - - + + /** * Register loop resource (music / effect loop) * * @param key sound key - * @param resource resource path - * @param pitch default pitch (1 = unchanged) - * @param gain default gain (0-1) - * @param fadeIn default time for fadeIn - * @param fadeOut default time for fadeOut + * @param loop the loop to add (Obtained from audio module) */ - public void addLoop(String key, String resource, double pitch, double gain, double fadeIn, double fadeOut) + public void addLoop(String key, LoopPlayer loop) { - loops.put(key, App.audio().createLoop(resource, pitch, gain, fadeIn, fadeOut)); + loops.put(key, loop); } - - + + /** * Get a loop player for key * @@ -64,8 +57,8 @@ public class SoundRegistry { } return p; } - - + + /** * Get a effect player for key * diff --git a/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java b/src/mightypork/gamecore/audio/players/AudioPlayer.java similarity index 67% rename from src/mightypork/gamecore/audio/players/BaseAudioPlayer.java rename to src/mightypork/gamecore/audio/players/AudioPlayer.java index a6c21b5..198b33b 100644 --- a/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java +++ b/src/mightypork/gamecore/audio/players/AudioPlayer.java @@ -1,66 +1,61 @@ package mightypork.gamecore.audio.players; -import mightypork.gamecore.audio.DeferredAudio; +import mightypork.gamecore.audio.IAudio; import mightypork.gamecore.audio.Volume; import mightypork.utils.interfaces.Destroyable; /** - * Basic abstract player + * Base of an audio player * * @author Ondřej Hruška (MightyPork) */ -public abstract class BaseAudioPlayer implements Destroyable { - +public abstract class AudioPlayer implements Destroyable { + /** the track */ - private final DeferredAudio audio; - + private final IAudio audio; + /** base gain for sfx */ - private final double baseGain; - + private double baseGain; + /** base pitch for sfx */ - private final double basePitch; - + private double basePitch; + /** dedicated volume control */ private final Volume gainMultiplier; - - + + /** * @param track audio resource - * @param basePitch base pitch (pitch multiplier) - * @param baseGain base gain (volume multiplier) * @param volume colume control */ - public BaseAudioPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) + public AudioPlayer(IAudio track, Volume volume) { this.audio = track; - - this.baseGain = baseGain; - this.basePitch = basePitch; - + if (volume == null) volume = new Volume(1D); - + this.gainMultiplier = volume; } - - + + @Override public void destroy() { audio.destroy(); } - - + + /** * @return audio resource */ - protected DeferredAudio getAudio() + protected IAudio getAudio() { return audio; } - - + + /** * Get play gain, computed based on volume and given multiplier * @@ -71,8 +66,8 @@ public abstract class BaseAudioPlayer implements Destroyable { { return baseGain * gainMultiplier.get() * multiplier; } - - + + /** * Get pitch * @@ -83,8 +78,8 @@ public abstract class BaseAudioPlayer implements Destroyable { { return basePitch * multiplier; } - - + + /** * Get if audio is valid * @@ -94,13 +89,27 @@ public abstract class BaseAudioPlayer implements Destroyable { { return (audio != null); } - - + + + /** + * Set base gain. 1 is original volume, 0 is silence. + * + * @param baseGain base gain + */ + public void setGain(double baseGain) + { + this.baseGain = baseGain; + } + + /** - * force load the resource + * Set base pitch. 1 is original pitch, less is deeper, more is higher. + * + * @param basePitch base pitch */ - public void load() + public void setPitch(double basePitch) { - if (hasAudio()) audio.load(); + this.basePitch = basePitch; } + } diff --git a/src/mightypork/gamecore/audio/players/EffectPlayer.java b/src/mightypork/gamecore/audio/players/EffectPlayer.java index eeaf526..413c115 100644 --- a/src/mightypork/gamecore/audio/players/EffectPlayer.java +++ b/src/mightypork/gamecore/audio/players/EffectPlayer.java @@ -1,7 +1,7 @@ package mightypork.gamecore.audio.players; -import mightypork.gamecore.audio.DeferredAudio; +import mightypork.gamecore.audio.IAudio; import mightypork.gamecore.audio.Volume; import mightypork.utils.math.constraints.vect.Vect; @@ -11,34 +11,32 @@ import mightypork.utils.math.constraints.vect.Vect; * * @author Ondřej Hruška (MightyPork) */ -public class EffectPlayer extends BaseAudioPlayer { - +public class EffectPlayer extends AudioPlayer { + /** * @param track audio resource - * @param basePitch base pitch (pitch multiplier) - * @param baseGain base gain (volume multiplier) * @param volume volume control */ - public EffectPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) + public EffectPlayer(IAudio track, Volume volume) { - super(track, (float) basePitch, (float) baseGain, volume); + super(track, volume); } - - + + /** * Play at listener * - * @param pitch play pitch * @param gain play gain + * @param pitch play pitch */ - public void play(double pitch, double gain) + public void play(double gain, double pitch) { if (!hasAudio()) return; - - getAudio().play(computePitch(pitch), computeGain(gain), false); + + getAudio().play(computeGain(gain), computePitch(pitch), false); } - - + + /** * Play at listener * @@ -46,22 +44,34 @@ public class EffectPlayer extends BaseAudioPlayer { */ public void play(double gain) { - play(1, gain); + play(gain, 1); } - - + + /** * Play at given position * - * @param pitch play pitch * @param gain play gain * @param pos play position */ - public void play(double pitch, double gain, Vect pos) + public void play(double gain, Vect pos) + { + play(gain, 1, pos); + } + + + /** + * Play at given position + * + * @param gain play gain + * @param pitch play pitch + * @param pos play position + */ + public void play(double gain, double pitch, Vect pos) { if (!hasAudio()) return; - - getAudio().play(computePitch(pitch), computeGain(gain), false, pos); + + getAudio().play(computeGain(gain), computePitch(pitch), false, pos); } - + } diff --git a/src/mightypork/gamecore/audio/players/LoopPlayer.java b/src/mightypork/gamecore/audio/players/LoopPlayer.java index 3440cf7..eb733e9 100644 --- a/src/mightypork/gamecore/audio/players/LoopPlayer.java +++ b/src/mightypork/gamecore/audio/players/LoopPlayer.java @@ -13,33 +13,31 @@ import mightypork.utils.math.animation.NumAnimated; * * @author Ondřej Hruška (MightyPork) */ -public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable { - +public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable { + /** animator for fade in and fade out */ private final NumAnimated fadeAnim = new NumAnimated(0); - + private double lastUpdateGain = 0; - + /** flag that track is paused */ private boolean paused = true; - + /** Default fadeIn time */ private double inTime = 1; - + /** Default fadeOut time */ private double outTime = 1; - - + + /** * @param track audio resource - * @param basePitch base pitch (pitch multiplier) - * @param baseGain base gain (volume multiplier) * @param volume volume control */ - public LoopPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) + public LoopPlayer(DeferredAudio track, Volume volume) { - super(track, (float) basePitch, (float) baseGain, volume); - + super(track, volume); + paused = true; } @@ -55,68 +53,77 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable inTime = in; outTime = out; } - - + + private void initLoop() { - if (hasAudio()) { - getAudio().play(computePitch(1), computeGain(1), true); + if (hasAudio() && !getAudio().isActive()) { + getAudio().play(computeGain(1), computePitch(1), true); getAudio().pauseLoop(); } } - - + + @Override public void pause() { if (!hasAudio() || paused) return; - + initLoop(); - + getAudio().pauseLoop(); paused = true; } - - + + @Override public boolean isPaused() { return paused; } - - + + + /** + * Alias to resume (more meaningful name) + */ + public void play() + { + resume(); + } + + @Override public void resume() { if (!hasAudio() || !paused) return; - + initLoop(); - + paused = false; - + getAudio().adjustGain(computeGain(fadeAnim.value())); } - - + + @Override public void update(double delta) { if (!hasAudio() || paused) return; - + initLoop(); - + fadeAnim.update(delta); - + final double gain = computeGain(fadeAnim.value()); if (!paused && gain != lastUpdateGain) { getAudio().adjustGain(gain); lastUpdateGain = gain; } - + if (gain == 0 && !paused) pause(); // pause on zero volume } - - + + /** * Resume if paused, and fade in (pick up from current volume). * @@ -125,13 +132,13 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable public void fadeIn(double fadeTime) { if (!hasAudio()) return; - + if (isPaused()) fadeAnim.setTo(0); resume(); fadeAnim.fadeIn(fadeTime); } - - + + /** * Fade out and pause when reached zero volume * @@ -143,8 +150,8 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable if (isPaused()) return; fadeAnim.fadeOut(fadeTime); } - - + + /** * Fade in with default duration */ @@ -152,8 +159,8 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable { fadeIn(inTime); } - - + + /** * Fade out with default duration */ @@ -161,5 +168,5 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable { fadeOut(outTime); } - + } diff --git a/src/mightypork/gamecore/graphics/GraphicsModule.java b/src/mightypork/gamecore/graphics/GraphicsModule.java index a942a6e..b32474a 100644 --- a/src/mightypork/gamecore/graphics/GraphicsModule.java +++ b/src/mightypork/gamecore/graphics/GraphicsModule.java @@ -272,7 +272,7 @@ public abstract class GraphicsModule extends BackendModule { * @param path path to texture * @return the deferred font */ - public abstract DeferredTexture createDeferredTexture(String path); + public abstract DeferredTexture createTextureResource(String path); /** @@ -281,7 +281,7 @@ public abstract class GraphicsModule extends BackendModule { * @param path path to font, or font name in the system * @return the deferred font */ - public abstract DeferredFont createDeferredFont(String path); + public abstract DeferredFont createFontResource(String path); /** diff --git a/src/mightypork/gamecore/graphics/textures/TextureRegistry.java b/src/mightypork/gamecore/graphics/textures/TextureRegistry.java index af299b4..4c2b4a7 100644 --- a/src/mightypork/gamecore/graphics/textures/TextureRegistry.java +++ b/src/mightypork/gamecore/graphics/textures/TextureRegistry.java @@ -51,7 +51,7 @@ public class TextureRegistry { { if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException(); - final DeferredTexture texture = App.gfx().createDeferredTexture(resourcePath); + final DeferredTexture texture = App.gfx().createTextureResource(resourcePath); texture.setFilter(filter); texture.setWrap(wrap);