feat(audio): Refactor audio control integration in AudioStrategy and players for improved option management

This commit is contained in:
extio-de
2025-12-24 21:57:32 +01:00
parent b07f957041
commit 43dff6454e
5 changed files with 77 additions and 53 deletions

View File

@@ -11,7 +11,7 @@ public final class AudioController implements AudioControl {
private final StorageService storageService;
private AudioOptions audioOptions;
private final AudioOptions audioOptions; // Passed as reference to strategies
private AudioStrategy audioStrategy;
@@ -31,12 +31,12 @@ public final class AudioController implements AudioControl {
public AudioController(final StaticResourceService resourceService, final StorageService storageService) {
this.storageService = storageService;
storageService.loadByPath(AudioOptions.class, List.of("audio"), "audioOptions").ifPresentOrElse(
this.audioOptions = new AudioOptions();
storageService.loadByPath(AudioOptions.class, List.of("gameEngine"), "audioOptions").ifPresentOrElse(
loadedOptions -> {
this.audioOptions = loadedOptions;
this.audioOptions.apply(loadedOptions);
},
() -> {
this.audioOptions = new AudioOptions();
this.storeAudioOptions();
});
@@ -63,7 +63,7 @@ public final class AudioController implements AudioControl {
}
private void storeAudioOptions() {
this.storageService.store(List.of("audio"), "audioOptions", this.audioOptions);
this.storageService.store(List.of("gameEngine"), "audioOptions", this.audioOptions);
}
public void run() {
@@ -91,11 +91,11 @@ public final class AudioController implements AudioControl {
.start(this.audioLoader);
if (this.audioOptions.getSfxOptions().isSoftwareMixing()) {
this.audioStrategy = new AudioStrategySoftwareMixing(this.audioOptions, this.audioLoader);
this.audioStrategy = new AudioStrategySoftwareMixing(this, this.audioOptions, this.audioLoader);
this.useSoftwareMixing = true;
}
else {
this.audioStrategy = new AudioStrategyJavaMixer(this.audioOptions, this.audioLoader);
this.audioStrategy = new AudioStrategyJavaMixer(this, this.audioOptions, this.audioLoader);
this.useSoftwareMixing = false;
}

View File

@@ -27,6 +27,8 @@ final class AudioPlayerMultiStream implements AudioPlayer {
private final BlockingQueue<AudioData> queue = new LinkedBlockingQueue<>(20);
private final AudioControl audioControl;
private volatile AudioData musicQueue;
private volatile boolean musicPlaying;
@@ -51,7 +53,8 @@ final class AudioPlayerMultiStream implements AudioPlayer {
private long notStartedAudioCnt;
public AudioPlayerMultiStream() {
public AudioPlayerMultiStream(AudioControl audioControl) {
this.audioControl = audioControl;
}
@Override
@@ -288,6 +291,10 @@ final class AudioPlayerMultiStream implements AudioPlayer {
if (++this.notStartedAudioCnt > 5) {
this.notStartedAudioCnt = 0;
var options =this.audioControl.getAudioOptions();
options.getSfxOptions().enable = false;
options.getMusicOptions().enable = false;
this.audioControl.applyAudioOptions(options);
this.exit = true;
LOGGER.error("Too many audio playback errors, shutting down audio player.");
}

View File

@@ -24,6 +24,8 @@ final class AudioPlayerSingleStream implements AudioPlayer {
private final BlockingQueue<AudioData> queue = new LinkedBlockingQueue<>(5);
private final AudioControl audioControl;
private volatile boolean stopAudio;
private volatile boolean playing;
@@ -40,7 +42,8 @@ final class AudioPlayerSingleStream implements AudioPlayer {
private int notStartedAudioCnt;
public AudioPlayerSingleStream() {
public AudioPlayerSingleStream(AudioControl audioControl) {
this.audioControl = audioControl;
}
@Override
@@ -124,6 +127,10 @@ final class AudioPlayerSingleStream implements AudioPlayer {
if (++this.notStartedAudioCnt > 5) {
this.notStartedAudioCnt = 0;
var options =this.audioControl.getAudioOptions();
options.getSfxOptions().enable = false;
options.getMusicOptions().enable = false;
this.audioControl.applyAudioOptions(options);
this.exit = true;
LOGGER.error("Too many audio playback errors, shutting down audio player.");
}

View File

@@ -25,7 +25,9 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
private final static int MUSIC_INITIAL_DELAY_MS = 1000;
private final AudioOptions clientEngineData;
private final AudioControl audioControl;
private final AudioOptions audioOptions;
private final AudioLoader audioLoader;
@@ -33,7 +35,7 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
private final List<AudioThread> sfxAudioPlayers = new ArrayList<>(SFX_PLAYERS);
private final Set<StaticResource> sfxQueue = new LinkedHashSet<>();
private final Set<StaticResource> sfxQueue = Collections.synchronizedSet(new LinkedHashSet<>());
private final List<AudioPlayerReference> sfxPlayersBySize = new ArrayList<>(SFX_PLAYERS);
@@ -47,15 +49,16 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
private long musicFirstQueued;
public AudioStrategyJavaMixer(final AudioOptions clientEngineData, final AudioLoader audioLoader) {
this.clientEngineData = clientEngineData;
public AudioStrategyJavaMixer(final AudioControl audioControl, final AudioOptions audioOptions, final AudioLoader audioLoader) {
this.audioControl = audioControl;
this.audioOptions = audioOptions;
this.audioLoader = audioLoader;
}
@Override
public void start() {
{
final var musicAudioPlayer = new AudioPlayerSingleStream();
final var musicAudioPlayer = new AudioPlayerSingleStream(this.audioControl);
final var musicThread = Thread.ofPlatform()
.name("Audio Music")
.daemon(true)
@@ -65,7 +68,7 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
}
for (int i = 0; i < SFX_PLAYERS; i++) {
final AudioPlayer audioPlayer = new AudioPlayerSingleStream();
final AudioPlayer audioPlayer = new AudioPlayerSingleStream(this.audioControl);
final var audioThread = Thread.ofPlatform()
.name("Audio SFX " + i)
.daemon(true)
@@ -91,7 +94,7 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
public void run() {
// Music
if (!this.clientEngineData.getMusicOptions().isEnable()) {
if (!this.audioOptions.getMusicOptions().isEnable()) {
if (this.musicAudioPlayer.audioPlayer().isPlaying()) {
this.musicAudioPlayer.audioPlayer().stopAudio();
}
@@ -113,7 +116,7 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
}
if (this.musicAudioPlayer.audioPlayer().isPlaying() || !this.musicPlayQueue.isEmpty()) {
this.musicAudioPlayer.audioPlayer().updateAudioOptions(this.clientEngineData.getMusicOptions());
this.musicAudioPlayer.audioPlayer().updateAudioOptions(this.audioOptions.getMusicOptions());
}
if (!this.musicAudioPlayer.audioPlayer().isPlaying() &&
@@ -127,9 +130,10 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
// SFX
synchronized (this.sfxQueue) {
if (!this.sfxQueue.isEmpty()) {
for (int i = 0; i < SFX_PLAYERS; i++) {
this.sfxAudioPlayers.get(i).audioPlayer().updateAudioOptions(this.clientEngineData.getSfxOptions());
this.sfxAudioPlayers.get(i).audioPlayer().updateAudioOptions(this.audioOptions.getSfxOptions());
this.sfxPlayersBySize.get(i).queueSize = this.sfxPlayersBySize.get(i).audioPlayer.getQueue().size();
}
Collections.sort(this.sfxPlayersBySize);
@@ -149,10 +153,11 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
}
}
}
}
@Override
public void queueSfx(final Collection<StaticResource> audioFile) {
if (!this.clientEngineData.getSfxOptions().isEnable()) {
if (!this.audioOptions.getSfxOptions().isEnable()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Not queued audio file (audio disabled): " + audioFile);
}

View File

@@ -24,7 +24,9 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
private final static int MUSIC_INITIAL_DELAY_MS = 1000;
private final AudioOptions clientEngineData;
private final AudioControl audioControl;
private final AudioOptions audioOptions;
private final AudioLoader audioLoader;
@@ -32,7 +34,7 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
private AudioThread audioPlayer;
private final Set<StaticResource> sfxQueue = new LinkedHashSet<>();
private final Set<StaticResource> sfxQueue = Collections.synchronizedSet(new LinkedHashSet<>());
private final List<StaticResource> musicFiles = new ArrayList<>();
@@ -40,14 +42,15 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
private long musicFirstQueued;
public AudioStrategySoftwareMixing(final AudioOptions clientEngineData, final AudioLoader audioLoader) {
this.clientEngineData = clientEngineData;
public AudioStrategySoftwareMixing(final AudioControl audioControl, final AudioOptions audioOptions, final AudioLoader audioLoader) {
this.audioControl = audioControl;
this.audioOptions = audioOptions;
this.audioLoader = audioLoader;
}
@Override
public void start() {
final var multiStreamPlayer = new AudioPlayerMultiStream();
final var multiStreamPlayer = new AudioPlayerMultiStream(this.audioControl);
final var multiStreamThread = Thread.ofPlatform()
.name("Audio MultiStream")
.daemon(true)
@@ -64,13 +67,13 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
@Override
public void run() {
if (this.audioPlayer.audioPlayer().isPlaying() || !this.sfxQueue.isEmpty() || !this.musicPlayQueue.isEmpty() || !this.musicFiles.isEmpty()) {
this.audioPlayer.audioPlayer().updateAudioOptions(this.clientEngineData.getSfxOptions());
this.audioPlayer.audioPlayer().updateMusicAudioOptions(this.clientEngineData.getMusicOptions());
this.audioPlayer.audioPlayer().updateAudioOptions(this.audioOptions.getSfxOptions());
this.audioPlayer.audioPlayer().updateMusicAudioOptions(this.audioOptions.getMusicOptions());
}
// Music
if (!this.clientEngineData.getMusicOptions().isEnable()) {
if (!this.audioOptions.getMusicOptions().isEnable()) {
if (this.audioPlayer.audioPlayer().isMusicPlaying()) {
this.audioPlayer.audioPlayer().setStopMusic(true);
}
@@ -94,13 +97,15 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
// Sfx
synchronized (this.sfxQueue) {
if (!this.sfxQueue.isEmpty()) {
final Iterator<StaticResource> it = this.sfxQueue.iterator();
while (it.hasNext()) {
final StaticResource nextFile = it.next();
this.audioLoader.getQueue().offer(new AudioLoaderRequest(nextFile, true, stream -> this.audioPlayer.audioPlayer().getQueue().offer(new AudioData(nextFile.resourceName(), stream))));
it.remove();
}
}
this.sfxQueue.clear();
}
}
@@ -111,7 +116,7 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
@Override
public void queueSfx(final Collection<StaticResource> audioFiles) {
if (!this.clientEngineData.getSfxOptions().isEnable()) {
if (!this.audioOptions.getSfxOptions().isEnable()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Not queued audio file (audio disabled): " + audioFiles);
}