feat(audio): Refactor audio control integration in AudioStrategy and players for improved option management
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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,32 +130,34 @@ final class AudioStrategyJavaMixer implements AudioStrategy {
|
||||
|
||||
// SFX
|
||||
|
||||
if (!this.sfxQueue.isEmpty()) {
|
||||
for (int i = 0; i < SFX_PLAYERS; i++) {
|
||||
this.sfxAudioPlayers.get(i).audioPlayer().updateAudioOptions(this.clientEngineData.getSfxOptions());
|
||||
this.sfxPlayersBySize.get(i).queueSize = this.sfxPlayersBySize.get(i).audioPlayer.getQueue().size();
|
||||
}
|
||||
Collections.sort(this.sfxPlayersBySize);
|
||||
synchronized (this.sfxQueue) {
|
||||
if (!this.sfxQueue.isEmpty()) {
|
||||
for (int i = 0; i < SFX_PLAYERS; i++) {
|
||||
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);
|
||||
|
||||
while (!this.sfxQueue.isEmpty()) {
|
||||
int i = 0;
|
||||
final Iterator<StaticResource> it = this.sfxQueue.iterator();
|
||||
do {
|
||||
this.sfxPlayersBySize.get(i).queueSize++;
|
||||
while (!this.sfxQueue.isEmpty()) {
|
||||
int i = 0;
|
||||
final Iterator<StaticResource> it = this.sfxQueue.iterator();
|
||||
do {
|
||||
this.sfxPlayersBySize.get(i).queueSize++;
|
||||
|
||||
final AudioPlayer player = this.sfxPlayersBySize.get(i).audioPlayer;
|
||||
final StaticResource nextFile = it.next();
|
||||
it.remove();
|
||||
final AudioPlayer player = this.sfxPlayersBySize.get(i).audioPlayer;
|
||||
final StaticResource nextFile = it.next();
|
||||
it.remove();
|
||||
|
||||
this.audioLoader.getQueue().offer(new AudioLoaderRequest(nextFile, true, stream -> player.getQueue().offer(new AudioData(nextFile.resourceName(), stream))));
|
||||
} while (it.hasNext() && ++i < this.sfxPlayersBySize.size() && this.sfxPlayersBySize.get(i - 1).queueSize > this.sfxPlayersBySize.get(i).queueSize);
|
||||
this.audioLoader.getQueue().offer(new AudioLoaderRequest(nextFile, true, stream -> player.getQueue().offer(new AudioData(nextFile.resourceName(), stream))));
|
||||
} while (it.hasNext() && ++i < this.sfxPlayersBySize.size() && this.sfxPlayersBySize.get(i - 1).queueSize > this.sfxPlayersBySize.get(i).queueSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
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))));
|
||||
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);
|
||||
}
|
||||
@@ -141,7 +146,7 @@ final class AudioStrategySoftwareMixing implements AudioStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
if (musicAudioFiles.equals(this.musicFiles)) {
|
||||
if (musicAudioFiles.equals(this.musicFiles)) {
|
||||
this.musicFirstQueued = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user