diff --git a/Platform/Apple/tools/jace/src/main/java/jace/hardware/CardMockingboard.java b/Platform/Apple/tools/jace/src/main/java/jace/hardware/CardMockingboard.java index f947b87a..be2ed538 100644 --- a/Platform/Apple/tools/jace/src/main/java/jace/hardware/CardMockingboard.java +++ b/Platform/Apple/tools/jace/src/main/java/jace/hardware/CardMockingboard.java @@ -18,6 +18,7 @@ */ package jace.hardware; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -26,8 +27,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; -import javax.sound.sampled.SourceDataLine; - import jace.config.ConfigurableField; import jace.config.Name; import jace.core.Card; @@ -35,6 +34,7 @@ import jace.core.Computer; import jace.core.Motherboard; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; +import jace.core.SoundMixer.SoundBuffer; import jace.core.RAMListener; import jace.core.SoundMixer; import jace.hardware.mockingboard.PSG; @@ -254,8 +254,6 @@ public class CardMockingboard extends Card implements Runnable { /////////////////////////////////////////////////////////// public static int[] VolTable; - int[][] buffers; - int bufferLength = -1; public void playSound(int[] left, int[] right) { chips[0].update(left, true, left, false, left, false, BUFFER_LENGTH); @@ -346,19 +344,16 @@ public class CardMockingboard extends Card implements Runnable { * This is the audio playback thread */ public void run() { - SourceDataLine out = null; + SoundBuffer buffer = SoundMixer.createBuffer(true); try { - // out = computer.mixer.getLine(); - if (out == null) { + if (buffer == null) { setRun(false); return; } - int[] leftBuffer = new int[BUFFER_LENGTH]; - int[] rightBuffer = new int[BUFFER_LENGTH]; - int frameSize = out.getFormat().getFrameSize(); - byte[] buffer = new byte[BUFFER_LENGTH * frameSize]; System.out.println("Mockingboard playback started"); - int bytesPerSample = frameSize / 2; + int bufferSize = SoundMixer.BUFFER_SIZE; + int[] left = new int[bufferSize]; + int[] right = new int[bufferSize]; buildMixerTable(); ticksBetweenPlayback = (int) ((Motherboard.DEFAULT_SPEED * BUFFER_LENGTH) / SAMPLE_RATE); System.out.println("Ticks between playback: "+ticksBetweenPlayback); @@ -371,30 +366,27 @@ public class CardMockingboard extends Card implements Runnable { Thread.sleep(1000); } if (isRunning() && !Thread.interrupted()) { - playSound(leftBuffer, rightBuffer); - int p = 0; - for (int idx = 0; idx < BUFFER_LENGTH; idx++) { - int sampleL = leftBuffer[idx]; - int sampleR = rightBuffer[idx]; - // Convert left + right samples into buffer format - if (sampleL == 0 && sampleR == 0) { - zeroSamples++; - } else { - zeroSamples = 0; - } - for (int shift = SoundMixer.BITS - 8, index = 0; shift >= 0; shift -= 8, index++) { - buffer[p + index] = (byte) (sampleR >> shift); - buffer[p + index + bytesPerSample] = (byte) (sampleL >> shift); - } - p += frameSize; - } + playSound(left, right); try { + for (int i=0; i < bufferSize; i++) { + buffer.playSample((short) left[i]); + buffer.playSample((short) right[i]); + } timerSync.lock(); ticksSinceLastPlayback -= ticksBetweenPlayback; + } catch (ExecutionException e) { + Logger.getLogger(CardMockingboard.class.getName()).log(Level.SEVERE, "Mockingboard playback encountered fatal exception", e); + try { + buffer.shutdown(); + } catch (ExecutionException e1) { + // Ignore shutdown errors, we're already reporting a fatal error + } + buffer=null; + setRun(false); + break; } finally { timerSync.unlock(); } - out.write(buffer, 0, buffer.length); if (zeroSamples >= MAX_IDLE_SAMPLES) { zeroSamples = 0; pause = true; @@ -437,9 +429,12 @@ public class CardMockingboard extends Card implements Runnable { } finally { computer.getMotherboard().cancelSpeedRequest(this); System.out.println("Mockingboard playback stopped"); - if (out != null && out.isRunning()) { - out.drain(); - out.close(); + if (buffer != null && buffer.isAlive()) { + try { + buffer.shutdown(); + } catch (InterruptedException | ExecutionException e) { + // Ignore errors during shutdown + } } } }