diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java index 4f3a78a2b..f53dfa5c2 100644 --- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/audio/PortAudioRenderer.java @@ -329,8 +329,17 @@ public synchronized void open() { if (stream == 0) { - int deviceIndex = DataSource.getDeviceIndex(getLocator()); + MediaLocator locator = getLocator(); + + if (locator == null) + throw new ResourceUnavailableException("locator not set"); + + int deviceIndex = DataSource.getDeviceIndex(locator); AudioFormat inputFormat = this.inputFormat; + + if (inputFormat == null) + throw new ResourceUnavailableException("inputFormat not set"); + int channels = inputFormat.getChannels(); if (channels == Format.NOT_SPECIFIED) diff --git a/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java b/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java index bf9dd2de2..c42968f90 100644 --- a/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/notify/PortAudioClipImpl.java @@ -12,6 +12,7 @@ import javax.media.*; import javax.sound.sampled.*; +import net.java.sip.communicator.impl.neomedia.codec.audio.speex.*; import net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio.*; import net.java.sip.communicator.util.*; @@ -216,18 +217,65 @@ private boolean runOnceInPlayThread( if (audioStream == null) return false; + Codec resampler = null; + try { AudioFormat audioStreamFormat = audioStream.getFormat(); - javax.media.format.AudioFormat rendererFormat + Format rendererFormat = new javax.media.format.AudioFormat( javax.media.format.AudioFormat.LINEAR, audioStreamFormat.getSampleRate(), audioStreamFormat.getSampleSizeInBits(), audioStreamFormat.getChannels()); + Format resamplerFormat = null; + + if (renderer.setInputFormat(rendererFormat) == null) + { + /* + * Try to negotiate a resampling of the audioStreamFormat to one + * of the formats supported by the renderer. + */ + resampler = new SpeexResampler(); + resamplerFormat = rendererFormat; + resampler.setInputFormat(resamplerFormat); - renderer.setInputFormat(rendererFormat); - buffer.setFormat(rendererFormat); + Format[] supportedResamplerFormats + = resampler.getSupportedOutputFormats(resamplerFormat); + + for (Format supportedRendererFormat + : renderer.getSupportedInputFormats()) + { + for (Format supportedResamplerFormat + : supportedResamplerFormats) + { + if (supportedRendererFormat.matches( + supportedResamplerFormat)) + { + rendererFormat = supportedRendererFormat; + resampler.setOutputFormat(rendererFormat); + renderer.setInputFormat(rendererFormat); + break; + } + } + } + } + + Buffer rendererBuffer = buffer; + Buffer resamplerBuffer; + + rendererBuffer.setFormat(rendererFormat); + if (resampler == null) + resamplerBuffer = null; + else + { + resamplerBuffer = new Buffer(); + bufferData = new byte[bufferData.length]; + resamplerBuffer.setData(bufferData); + resamplerBuffer.setFormat(resamplerFormat); + + resampler.open(); + } try { @@ -240,9 +288,22 @@ private boolean runOnceInPlayThread( && ((bufferLength = audioStream.read(bufferData)) != -1)) { - buffer.setLength(bufferLength); - buffer.setOffset(0); - renderer.process(buffer); + if (resampler == null) + { + rendererBuffer.setLength(bufferLength); + rendererBuffer.setOffset(0); + } + else + { + resamplerBuffer.setLength(bufferLength); + resamplerBuffer.setOffset(0); + rendererBuffer.setLength(0); + rendererBuffer.setOffset(0); + resampler.process(resamplerBuffer, rendererBuffer); + } + while ((renderer.process(rendererBuffer) + & Renderer.INPUT_BUFFER_NOT_CONSUMED) + == Renderer.INPUT_BUFFER_NOT_CONSUMED); } } catch (IOException ioex) @@ -256,6 +317,14 @@ private boolean runOnceInPlayThread( return false; } } + catch (ResourceUnavailableException ruex) + { + if (resampler != null) + { + logger.error("Failed to open SpeexResampler.", ruex); + return false; + } + } finally { try @@ -269,6 +338,9 @@ private boolean runOnceInPlayThread( * will fail to open again so ignore the exception. */ } + + if (resampler != null) + resampler.close(); } return true; }