diff --git a/src/com/limelight/binding/audio/JavaxAudioRenderer.java b/src/com/limelight/binding/audio/JavaxAudioRenderer.java index 7e0ca5e..dfd84ce 100644 --- a/src/com/limelight/binding/audio/JavaxAudioRenderer.java +++ b/src/com/limelight/binding/audio/JavaxAudioRenderer.java @@ -16,8 +16,10 @@ public class JavaxAudioRenderer implements AudioRenderer { private byte[] lineBuffer; private int channelCount; private int sampleRate; + private boolean reallocateLines; - public static final int DEFAULT_BUFFER_SIZE = 4096; + public static final int DEFAULT_BUFFER_SIZE = 0; + public static final int STARING_BUFFER_SIZE = 4096; public static final int STAGING_BUFFERS = 3; // 3 complete frames of audio @Override @@ -26,21 +28,28 @@ public class JavaxAudioRenderer implements AudioRenderer { // Queue the decoded samples into the staging sound buffer soundBuffer.queue(new ShortBufferDescriptor(pcmData, offset, length)); - // If there's space available in the sound line, pull some data out - // of the staging buffer and write it to the sound line int available = soundLine.available(); - - // Kinda jank. If the queued is larger than available, we are going to have a delay - // so we increase the buffer size - if (available < soundBuffer.size()) { - System.out.println("buffer too full, buffer size: " + soundLine.getBufferSize()); - int currentBuffer = soundLine.getBufferSize(); - soundLine.close(); - createSoundLine(currentBuffer*2); - available = soundLine.available(); - System.out.println("creating new line with buffer size: " + soundLine.getBufferSize()); + if (reallocateLines) { + // Kinda jank. If the queued is larger than available, we are going to have a delay + // so we increase the buffer size + if (available < soundBuffer.size()) { + System.out.println("buffer too full, buffer size: " + soundLine.getBufferSize()); + int currentBuffer = soundLine.getBufferSize(); + soundLine.close(); + createSoundLine(currentBuffer*2); + if (soundLine != null) { + available = soundLine.available(); + System.out.println("creating new line with buffer size: " + soundLine.getBufferSize()); + } + else { + available = 0; + System.out.println("failed to create sound line"); + } + } } + // If there's space available in the sound line, pull some data out + // of the staging buffer and write it to the sound line if (available > 0) { int written = soundBuffer.fill(lineBuffer, 0, available); if (written > 0) { @@ -59,10 +68,26 @@ public class JavaxAudioRenderer implements AudioRenderer { private void createSoundLine(int bufferSize) { AudioFormat audioFormat = new AudioFormat(sampleRate, 16, channelCount, true, true); - DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); + + DataLine.Info info; + + if (bufferSize == DEFAULT_BUFFER_SIZE) { + info = new DataLine.Info(SourceDataLine.class, audioFormat); + } + else { + info = new DataLine.Info(SourceDataLine.class, audioFormat, bufferSize); + } + try { soundLine = (SourceDataLine) AudioSystem.getLine(info); - soundLine.open(audioFormat, bufferSize); + + if (bufferSize == DEFAULT_BUFFER_SIZE) { + soundLine.open(audioFormat); + } + else { + soundLine.open(audioFormat, bufferSize); + } + soundLine.start(); lineBuffer = new byte[soundLine.getBufferSize()]; soundBuffer = new SoundBuffer(STAGING_BUFFERS); @@ -75,7 +100,16 @@ public class JavaxAudioRenderer implements AudioRenderer { public void streamInitialized(int channelCount, int sampleRate) { this.channelCount = channelCount; this.sampleRate = sampleRate; - createSoundLine(DEFAULT_BUFFER_SIZE); + + // Workaround OS X's bad Java mixer + if (System.getProperty("os.name").contains("Mac OS X")) { + createSoundLine(STARING_BUFFER_SIZE); + reallocateLines = true; + } + else { + createSoundLine(DEFAULT_BUFFER_SIZE); + reallocateLines = false; + } } }