Tries to fix the playback of the notification sounds with PortAudio on devices which cannot be opened with arbitrary sample rates. Reported by Werner Dittmann on the dev mailing list in the thread 'Wideband PortAudio'.

cusax-fix
Lyubomir Marinov 16 years ago
parent 9971db8617
commit 01b4b72409

@ -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)

@ -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;
}

Loading…
Cancel
Save