Partial attempt at getting Mockingboard to run more correctly, start of rewrite of music playback routines

This commit is contained in:
Brendan Robert 2023-10-24 21:54:34 -05:00
parent 64e5317019
commit 6d271362b2
8 changed files with 84 additions and 24 deletions

View File

@ -198,7 +198,6 @@ public class SoundMixer extends Device {
Logger.getLogger(SoundMixer.class.getName()).warning("Playback attempted on stopped buffer!");
return;
}
currentBuffer.put(sample);
if (!currentBuffer.hasRemaining()) {
buffersGenerated++;
currentBuffer.flip();
@ -232,6 +231,7 @@ public class SoundMixer extends Device {
currentBuffer = alternateBuffer;
alternateBuffer = tempBuffer;
}
currentBuffer.put(sample);
}
public void shutdown() throws InterruptedException, ExecutionException {

View File

@ -108,7 +108,7 @@ public abstract class TimedDevice extends Device {
if (worker != null && worker.isAlive()) {
return;
}
worker = new Thread(() -> {
Thread newWorker = new Thread(() -> {
// System.out.println("Worker thread for " + getDeviceName() + " starting");
while (isRunning()) {
hasStopped = false;
@ -124,10 +124,11 @@ public abstract class TimedDevice extends Device {
hasStopped = true;
// System.out.println("Worker thread for " + getDeviceName() + " stopped");
});
worker.setDaemon(false);
worker.setPriority(Thread.MAX_PRIORITY);
worker.start();
worker.setName("Timed device " + getDeviceName() + " worker");
this.worker = newWorker;
newWorker.setDaemon(false);
newWorker.setPriority(Thread.MAX_PRIORITY);
newWorker.setName("Timed device " + getDeviceName() + " worker");
newWorker.start();
}
long nanosPerInterval; // How long to wait between pauses
long cyclesPerInterval; // How many cycles to wait until a pause interval

View File

@ -324,14 +324,13 @@ public class CardMockingboard extends Card implements Runnable {
}
public boolean suspendSound() {
setRun(false);
if (playbackThread == null || !playbackThread.isAlive()) {
return false;
}
if (playbackThread != null) {
playbackThread.interrupt();
try {
// Wait for thread to die
playbackThread.join();
playbackThread.join(500);
} catch (InterruptedException ex) {
}
}

View File

@ -160,6 +160,9 @@ public class LawlessComputer extends Apple2e {
}
public void waitForVBL(int count) throws InterruptedException {
if (!isRunning()) {
return;
}
Semaphore s = new Semaphore(0);
onNextVBL(s::release);
s.acquire();

View File

@ -18,9 +18,6 @@ import jace.cheat.Cheats;
import jace.core.Computer;
import jace.core.RAMEvent;
import jace.lawless.LawlessVideo.RenderEngine;
import javafx.beans.property.DoubleProperty;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;
/**
@ -50,12 +47,10 @@ public class LawlessHacks extends Cheats {
addCheat("Lawless Legends Graphics Modes", RAMEvent.TYPE.ANY, (e) -> {
int addr = e.getAddress();
if (addr >= MODE_SOFTSWITCH_MIN && e.getAddress() <= MODE_SOFTSWITCH_MAX) {
// System.out.println("Trapped " + e.getType().toString() + " to $" + Integer.toHexString(e.getAddress()));
setEngineByOrdinal(e.getAddress() - MODE_SOFTSWITCH_MIN);
}
}, MODE_SOFTSWITCH_MIN, MODE_SOFTSWITCH_MAX);
addCheat("Lawless Legends Music Commands", RAMEvent.TYPE.WRITE, (e) -> {
// System.out.println(Integer.toHexString(e.getAddress()) + " => " + Integer.toHexString(e.getNewValue() & 0x0ff));
playSound(e.getNewValue());
}, SFX_TRIGGER);
}
@ -165,7 +160,7 @@ public class LawlessHacks extends Cheats {
playbackEffect = null;
}
private Optional<Double> getCurrentTime() {
private Optional<Long> getCurrentTime() {
if (currentSongPlayer == null) {
return Optional.empty();
} else if (currentSongPlayer.getCurrentTime() == null) {
@ -181,9 +176,8 @@ public class LawlessHacks extends Cheats {
if (player != null) {
getCurrentTime().ifPresent(val -> lastTime.put(currentSong, val + 1500));
playbackEffect = new Thread(() -> {
DoubleProperty volume = player.volumeProperty();
while (playbackEffect == Thread.currentThread() && volume.get() > 0.0) {
volume.set(volume.get() - FADE_AMT);
while (playbackEffect == Thread.currentThread() && player.getVolume() > 0.0) {
player.setVolume(player.getVolume() - FADE_AMT);
try {
Thread.sleep(FADE_SPEED);
} catch (InterruptedException e) {
@ -208,14 +202,13 @@ public class LawlessHacks extends Cheats {
private void fadeInSong(MediaPlayer player) {
stopSongEffect();
currentSongPlayer = player;
DoubleProperty volume = player.volumeProperty();
if (volume.get() >= 1.0) {
if (player.getVolume() >= 1.0) {
return;
}
playbackEffect = new Thread(() -> {
while (playbackEffect == Thread.currentThread() && volume.get() < 1.0) {
volume.set(volume.get() + FADE_AMT);
while (playbackEffect == Thread.currentThread() && player.getVolume() < 1.0) {
player.setVolume(player.getVolume() + FADE_AMT);
try {
Thread.sleep(FADE_SPEED);
} catch (InterruptedException e) {
@ -250,7 +243,7 @@ public class LawlessHacks extends Cheats {
player.setCycleCount(repeatSong ? MediaPlayer.INDEFINITE : 1);
player.setVolume(0.0);
if (playingFightSong || autoResume.contains(track) || switchScores) {
double time = lastTime.getOrDefault(track, 0.0);
long time = lastTime.getOrDefault(track, 0L);
System.out.println("Auto-resume from time " + time);
player.setStartTime(Duration.millis(time));
}
@ -316,7 +309,7 @@ public class LawlessHacks extends Cheats {
Pattern ENTRY = Pattern.compile("([0-9]+)\\s+(.*)");
private final Map<String, Map<Integer, String>> scores = new HashMap<>();
private final Set<Integer> autoResume = new HashSet<>();
private final Map<Integer, Double> lastTime = new HashMap<>();
private final Map<Integer, Long> lastTime = new HashMap<>();
private void readScores() {
InputStream data = getClass().getResourceAsStream("/jace/data/sound/scores.txt");
readScores(data);

View File

@ -0,0 +1,8 @@
package jace.lawless;
public class Media {
public Media(String resourcePath) {
}
}

View File

@ -0,0 +1,55 @@
package jace.lawless;
import java.time.Duration;
public class MediaPlayer {
double vol = 1.0;
int repeats = 0;
int maxRepetitions = 1;
Status status = Status.STOPPED;
public static enum Status {
PLAYING, PAUSED, STOPPED
}
public static final int INDEFINITE = -1;
public MediaPlayer(Media song) {
}
public Status getStatus() {
return null;
}
public Duration getCurrentTime() {
return null;
}
public double getVolume() {
return vol;
}
public void stop() {
status = Status.STOPPED;
}
public void setCycleCount(int i) {
maxRepetitions = i;
}
public void setVolume(double d) {
vol = Math.max(0.0, Math.min(1.0, d));
}
public void setStartTime(javafx.util.Duration millis) {
}
public void play() {
repeats = 0;
status = Status.PLAYING;
}
}

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
@SuppressWarnings("all")
module lawlesslegends {
requires nestedvm;
requires java.base;