Audio improvements

v5stable
Ondřej Hruška 10 years ago
parent a4c485a7de
commit 6220aa9918
  1. 4
      .gitignore
  2. 7
      src/mightypork/gamecore/core/events/MainLoopRequest.java
  3. 3
      src/mightypork/gamecore/core/events/ShudownRequest.java
  4. 36
      src/mightypork/gamecore/core/modules/MainLoop.java
  5. 5
      src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java
  6. 4
      src/mightypork/gamecore/gui/screens/impl/FadingLayer.java
  7. 14
      src/mightypork/gamecore/resources/AsyncResourceLoader.java
  8. 14
      src/mightypork/gamecore/resources/BaseLazyResource.java
  9. 32
      src/mightypork/gamecore/resources/Profiler.java
  10. 2
      src/mightypork/gamecore/resources/Res.java
  11. 16
      src/mightypork/gamecore/resources/audio/SoundSystem.java
  12. 13
      src/mightypork/gamecore/resources/audio/players/LoopPlayer.java

4
.gitignore vendored

@ -1,8 +1,8 @@
/bin/
/target/
/~local/
/.rogue-save/
/build/.rogue-save/
/build/out/.rogue-save/
/build/
/build/out/*.jar
/build/in/*.jar
*.log

@ -15,20 +15,23 @@ import mightypork.gamecore.eventbus.event_flags.SingleReceiverEvent;
public class MainLoopRequest extends BusEvent<MainLoop> {
private final Runnable task;
private final boolean priority;
/**
* @param task task to run on main thread in rendering context
* @param priority if true, skip other tasks in queue
*/
public MainLoopRequest(Runnable task)
public MainLoopRequest(Runnable task, boolean priority)
{
this.task = task;
this.priority = priority;
}
@Override
public void handleBy(MainLoop handler)
{
handler.queueTask(task);
handler.queueTask(task, priority);
}
}

@ -5,6 +5,7 @@ import mightypork.gamecore.core.modules.MainLoop;
import mightypork.gamecore.eventbus.BusEvent;
import mightypork.gamecore.eventbus.event_flags.NonConsumableEvent;
import mightypork.gamecore.eventbus.event_flags.SingleReceiverEvent;
import mightypork.gamecore.resources.audio.SoundSystem;
/**
@ -27,6 +28,6 @@ public class ShudownRequest extends BusEvent<MainLoop> {
{
handler.shutdown();
}
});
}, true);
}
}

@ -1,14 +1,18 @@
package mightypork.gamecore.core.modules;
import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import mightypork.gamecore.eventbus.events.UpdateEvent;
import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.render.Renderable;
import mightypork.gamecore.render.TaskTakeScreenshot;
import mightypork.gamecore.render.events.ScreenshotRequestListener;
import mightypork.gamecore.resources.Profiler;
import mightypork.gamecore.util.Utils;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.math.timing.TimerDelta;
@ -21,7 +25,10 @@ import mightypork.gamecore.util.math.timing.TimerDelta;
*/
public class MainLoop extends AppModule implements ScreenshotRequestListener {
private final Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();
private static final double MAX_TIME_TASKS = 1 / 30D; // (avoid queue from hogging timing)
private static final double MAX_DELTA = 1 / 20D; // (skip huge gaps caused by loading resources etc)
private final Deque<Runnable> tasks = new ConcurrentLinkedDeque<>();
private TimerDelta timer;
private Renderable rootRenderable;
private volatile boolean running = true;
@ -58,11 +65,23 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
while (running) {
getDisplay().beginFrame();
getEventBus().sendDirect(new UpdateEvent(timer.getDelta()));
double delta = timer.getDelta();
if (delta > MAX_DELTA) {
Log.f3("(timing) Cropping delta: was " + delta + " , limit " + MAX_DELTA);
delta = MAX_DELTA;
}
getEventBus().sendDirect(new UpdateEvent(delta));
Runnable r;
while ((r = taskQueue.poll()) != null) {
long t = Profiler.begin();
while ((r = tasks.poll()) != null) {
Log.f3(" * Main loop task.");
r.run();
if (Profiler.end(t) > MAX_TIME_TASKS) {
Log.f3("! Postponing main loop tasks to next cycle.");
break;
}
}
beforeRender();
@ -109,10 +128,15 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
* Add a task to queue to be executed in the main loop (OpenGL thread)
*
* @param request task
* @param priority if true, skip other tasks
*/
public synchronized void queueTask(Runnable request)
public synchronized void queueTask(Runnable request, boolean priority)
{
taskQueue.add(request);
if (priority) {
tasks.addFirst(request);
} else {
tasks.addLast(request);
}
}
@ -127,7 +151,7 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
{
Utils.runAsThread(new TaskTakeScreenshot());
}
});
}, false);
}
}

@ -67,6 +67,11 @@ public class CrossfadeOverlay extends Overlay {
{
requestedScreenName = screen;
if(screen == null) {
// going for halt
getSoundSystem().fadeOutAllLoops();
}
if (fromDark) {
alpha.setTo(1);
revealTask.run();

@ -3,6 +3,7 @@ package mightypork.gamecore.gui.screens.impl;
import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.timing.TimedTask;
@ -73,6 +74,7 @@ public abstract class FadingLayer extends ScreenLayer {
/**
* Called after the fade-out was completed
*/
@DefaultImpl
protected void onHideFinished()
{
}
@ -81,6 +83,7 @@ public abstract class FadingLayer extends ScreenLayer {
/**
* Called after the fade-in was completed
*/
@DefaultImpl
protected void onShowFinished()
{
}
@ -98,6 +101,7 @@ public abstract class FadingLayer extends ScreenLayer {
super.show();
numa.fadeIn();
hideTimer.stop();
showTimer.start(numa.getDefaultDuration());
fadingOut = false;
fadingIn = true;

@ -18,7 +18,7 @@ import mightypork.gamecore.logging.Log;
*/
public class AsyncResourceLoader extends Thread implements ResourceLoader, Destroyable {
private final ExecutorService exs = Executors.newCachedThreadPool();
private final ExecutorService exs = Executors.newFixedThreadPool(2);
private final LinkedBlockingQueue<LazyResource> toLoad = new LinkedBlockingQueue<>();
private volatile boolean stopped;
@ -57,9 +57,9 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
if (resource.getClass().isAnnotationPresent(TextureBasedResource.class)) {
if (!mainLoopQueuing) {
Log.f3("<LOADER> Cannot load async: " + Log.str(resource));
// just let it be
} else {
Log.f3("<LOADER> Delegating to main thread:\n " + Log.str(resource));
Log.f3("(loader) Delegating to main thread: " + Log.str(resource));
app.getEventBus().send(new MainLoopRequest(new Runnable() {
@ -68,7 +68,7 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
{
resource.load();
}
}));
}, false));
}
return;
@ -91,14 +91,16 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
if (!def.isLoaded()) {
Log.f3("<LOADER> Loading: " + Log.str(def));
Log.f3("(loader) Scheduling... " + Log.str(def));
exs.submit(new Runnable() {
@Override
public void run()
{
def.load();
if(!def.isLoaded()) {
def.load();
}
}
});
}

@ -6,6 +6,8 @@ import java.io.IOException;
import mightypork.gamecore.eventbus.events.Destroyable;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.logging.LogAlias;
import mightypork.gamecore.util.math.Calc;
import mightypork.gamecore.util.strings.StringUtils;
/**
@ -45,12 +47,14 @@ public abstract class BaseLazyResource implements LazyResource, Destroyable {
throw new NullPointerException("Resource string cannot be null for non-null resource.");
}
Log.f3("<RES> Loading: " + this);
long time = Profiler.begin();
Log.f3("(res) + Load: " + this);
loadResource(resource);
Log.f3("<RES> Loaded: " + this);
Log.f3("(res) - Done: " + this + " in " + Profiler.endStr(time));
} catch (final Throwable t) {
loadFailed = true;
Log.e("<RES> Failed to load: " + this, t);
Log.e("(res) Failed to load: " + this, t);
}
}
@ -74,7 +78,7 @@ public abstract class BaseLazyResource implements LazyResource, Destroyable {
} else {
if (loadFailed) return false;
Log.f3("<RES> (!) Loading on access: " + this);
Log.f3("(res) !! Loading on access: " + this);
load();
}
@ -99,7 +103,7 @@ public abstract class BaseLazyResource implements LazyResource, Destroyable {
@Override
public String toString()
{
return Log.str(getClass()) + "(\"" + resource + "\")";
return StringUtils.fromLastChar(resource, '/');
}

@ -0,0 +1,32 @@
package mightypork.gamecore.resources;
import mightypork.gamecore.util.math.Calc;
public class Profiler {
public static long begin()
{
return System.currentTimeMillis();
}
public static double end(long begun)
{
return endLong(begun) / 1000D;
}
public static long endLong(long begun)
{
return System.currentTimeMillis() - begun;
}
public static String endStr(long begun)
{
return Calc.toString(end(begun)) + " s";
}
}

@ -94,8 +94,8 @@ public final class Res {
public static void load(ResourceSetup binder)
{
binder.addFonts(fonts);
binder.addSounds(sounds);
binder.addTextures(textures);
binder.addSounds(sounds);
}
}

@ -2,7 +2,9 @@ package mightypork.gamecore.resources.audio;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mightypork.gamecore.core.modules.AppAccess;
@ -71,8 +73,8 @@ public class SoundSystem extends RootBusNode implements Updateable {
private final Volume effectsVolume = new JointVolume(masterVolume);
private final Volume loopsVolume = new JointVolume(masterVolume);
private final Set<LoopPlayer> loopPlayers = new HashSet<>();
private final Set<LazyAudio> resources = new HashSet<>();
private final List<LoopPlayer> loopPlayers = new ArrayList<>();
private final List<LazyAudio> resources = new ArrayList<>();
/**
@ -130,7 +132,7 @@ public class SoundSystem extends RootBusNode implements Updateable {
*/
public EffectPlayer createEffect(String resource, double pitch, double gain)
{
return new EffectPlayer(getResource(resource), pitch, gain, effectsVolume);
return new EffectPlayer(createResource(resource), pitch, gain, effectsVolume);
}
@ -146,7 +148,7 @@ public class SoundSystem extends RootBusNode implements Updateable {
*/
public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut)
{
final LoopPlayer p = new LoopPlayer(getResource(resource), pitch, gain, loopsVolume);
final LoopPlayer p = new LoopPlayer(createResource(resource), pitch, gain, loopsVolume);
p.setFadeTimes(fadeIn, fadeOut);
loopPlayers.add(p);
return p;
@ -160,12 +162,10 @@ public class SoundSystem extends RootBusNode implements Updateable {
* @return the resource
* @throws IllegalArgumentException if resource is already registered
*/
private LazyAudio getResource(String res)
private LazyAudio createResource(String res)
{
final LazyAudio a = new LazyAudio(res);
final LazyAudio a = new LazyAudio(res);
getEventBus().send(new ResourceLoadRequest(a));
if (resources.contains(a)) throw new IllegalArgumentException("Sound resource " + res + " is already registered.");
resources.add(a);
return a;
}

@ -98,6 +98,8 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
sourceID = getAudio().resumeLoop();
paused = false;
adjustGain(getGain(fadeAnim.value()));
}
@ -112,7 +114,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
final double gain = getGain(fadeAnim.value());
if (!paused && gain != lastUpdateGain) {
AL10.alSourcef(sourceID, AL10.AL_GAIN, (float) gain);
adjustGain(gain);
lastUpdateGain = gain;
}
@ -120,6 +122,12 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
}
private void adjustGain(double gain)
{
AL10.alSourcef(sourceID, AL10.AL_GAIN, (float) gain);
}
/**
* Resume if paused, and fade in (pick up from current volume).
*
@ -129,6 +137,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
{
if (!hasAudio()) return;
if (isPaused()) fadeAnim.setTo(0);
resume();
fadeAnim.fadeIn(secs);
}
@ -142,7 +151,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
public void fadeOut(double secs)
{
if (!hasAudio()) return;
if (isPaused()) return;
fadeAnim.fadeOut(secs);
}

Loading…
Cancel
Save