diff --git a/framework/src/main/java/org/toop/framework/audio/AudioVolumeManager.java b/framework/src/main/java/org/toop/framework/audio/AudioVolumeManager.java new file mode 100644 index 0000000..0d94d04 --- /dev/null +++ b/framework/src/main/java/org/toop/framework/audio/AudioVolumeManager.java @@ -0,0 +1,69 @@ +package org.toop.framework.audio; + +import javafx.scene.media.MediaPlayer; +import org.toop.framework.audio.events.AudioEvents; +import org.toop.framework.eventbus.EventFlow; + +import javax.sound.sampled.Clip; +import javax.sound.sampled.FloatControl; + +public class AudioVolumeManager { + private final SoundManager sM; + + private double volume = 1.0; + private double fxVolume = 1.0; + + public AudioVolumeManager(SoundManager soundManager){ + this.sM = soundManager; + + new EventFlow() + .listen(this::handleVolumeChange) + .listen(this::handleFxVolumeChange) + .listen(this::handleGetCurrentVolume) + .listen(this::handleGetCurrentFxVolume); + } + + public void updateMusicVolume(MediaPlayer mediaPlayer){ + mediaPlayer.setVolume(this.volume); + } + + public void updateSoundEffectVolume(Clip clip){ + if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)){ + FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); + float min = volumeControl.getMinimum(); + float max = volumeControl.getMaximum(); + float dB = (float) (Math.log10(Math.max(fxVolume, 0.0001)) * 20.0); // convert linear to dB + dB = Math.max(min, Math.min(max, dB)); + volumeControl.setValue(dB); + } + } + + private double limitVolume(double volume) { + if (volume > 1.0) return 1.0; + else return Math.max(volume, 0.0); + } + + private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) { + this.fxVolume = limitVolume(event.newVolume() / 100); + for (Clip clip : sM.getActiveSoundEffects().values()){ + updateSoundEffectVolume(clip); + } + } + + private void handleVolumeChange(AudioEvents.ChangeVolume event) { + this.volume = limitVolume(event.newVolume() / 100); + for (MediaPlayer mediaPlayer : sM.getActiveMusic()) { + this.updateMusicVolume(mediaPlayer); + } + } + + private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { + new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeResponse(volume * 100, event.snowflakeId())) + .asyncPostEvent(); + } + + private void handleGetCurrentFxVolume(AudioEvents.GetCurrentFxVolume event) { + new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId())) + .asyncPostEvent(); + } +} diff --git a/framework/src/main/java/org/toop/framework/audio/SoundManager.java b/framework/src/main/java/org/toop/framework/audio/SoundManager.java index 30036bd..51c31ad 100644 --- a/framework/src/main/java/org/toop/framework/audio/SoundManager.java +++ b/framework/src/main/java/org/toop/framework/audio/SoundManager.java @@ -23,9 +23,8 @@ public class SoundManager { private final Map activeSoundEffects = new HashMap<>(); private final HashMap audioResources = new HashMap<>(); private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator + private final AudioVolumeManager audioVolumeManager = new AudioVolumeManager(this); - private double volume = 1.0; - private double fxVolume = 1.0; public SoundManager() { // Get all Audio Resources and add them to a list. @@ -40,10 +39,6 @@ public class SoundManager { .listen(this::handlePlaySound) .listen(this::handleStopSound) .listen(this::handleMusicStart) - .listen(this::handleVolumeChange) - .listen(this::handleFxVolumeChange) - .listen(this::handleGetCurrentVolume) - .listen(this::handleGetCurrentFxVolume) .listen(AudioEvents.ClickButton.class, _ -> { try { playSound("medium-button-click.wav", false); @@ -71,46 +66,6 @@ public class SoundManager { this.audioResources.put(audioAsset.getName(), audioAsset.getResource()); } - private double limitVolume(double volume) { - if (volume > 1.0) return 1.0; - else return Math.max(volume, 0.0); - } - - private void handleVolumeChange(AudioEvents.ChangeVolume event) { - this.volume = limitVolume(event.newVolume() / 100); - for (MediaPlayer mediaPlayer : this.activeMusic) { - mediaPlayer.setVolume(this.volume); - } - } - - private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) { - this.fxVolume = limitVolume(event.newVolume() / 100); - for (Clip clip : this.activeSoundEffects.values()){ - updateClipVolume(clip); - } - } - - private void updateClipVolume(Clip clip){ - if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)){ - FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); - float min = volumeControl.getMinimum(); - float max = volumeControl.getMaximum(); - float dB = (float) (Math.log10(Math.max(fxVolume, 0.0001)) * 20.0); // convert linear to dB - dB = Math.max(min, Math.min(max, dB)); - volumeControl.setValue(dB); - } - } - - private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { - new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeResponse(volume * 100, event.snowflakeId())) - .asyncPostEvent(); - } - - private void handleGetCurrentFxVolume(AudioEvents.GetCurrentFxVolume event) { - new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId())) - .asyncPostEvent(); - } - private void handleMusicStart(AudioEvents.StartBackgroundMusic e) { backgroundMusicQueue.clear(); List shuffledArray = new ArrayList<>(ResourceManager.getAllOfType(MusicAsset.class) @@ -154,7 +109,7 @@ public class SoundManager { ma.unload(); }); - mediaPlayer.setVolume(this.volume); + audioVolumeManager.updateMusicVolume(mediaPlayer); mediaPlayer.play(); activeMusic.add(mediaPlayer); logger.info("Playing background music: {}", ma.getFile().getName()); @@ -174,7 +129,7 @@ public class SoundManager { Clip clip = asset.getNewClip(); // Set volume of clip - updateClipVolume(clip); + audioVolumeManager.updateSoundEffectVolume(clip); // If supposed to loop make it loop, else just start it once if (loop) { @@ -223,4 +178,8 @@ public class SoundManager { } activeSoundEffects.clear(); } + + public Map getActiveSoundEffects(){ return this.activeSoundEffects; } + + public List getActiveMusic() { return activeMusic; } }