From 682469e0f235dd91c172288248580e63d92ed0e5 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Mon, 28 Mar 2011 16:55:53 +0000 Subject: Clips the audio signal instead of wrapping it when increasing the volume. --- .../media/renderer/audio/PortAudioRenderer.java | 79 ++++++++++++++-------- 1 file changed, 52 insertions(+), 27 deletions(-) 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 7c663f3..4b3648b 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 @@ -21,7 +21,7 @@ import net.java.sip.communicator.util.*; * Implements an audio Renderer which uses PortAudio. * * @author Damian Minkov - * @author Lubomir Marinov + * @author Lyubomir Marinov */ public class PortAudioRenderer extends ControlsAdapter @@ -152,7 +152,8 @@ public class PortAudioRenderer private Format[] supportedInputFormats; /** - * Volume Control used to control volume/gain of current played media. + * The GainControl used to control volume/gain of current played + * media. */ private GainControl gainControl = null; @@ -176,6 +177,53 @@ public class PortAudioRenderer } /** + * Applies the gain specified by {@link #gainControl} to the signal defined + * by the length number of samples given in buffer + * starting at offset. + * + * @param buffer the samples of the signal to apply the gain to + * @param offset the start of the samples of the signal in buffer + * @param length the number of samples of the signal given in + * buffer + */ + private void applyGain(byte[] buffer, int offset, int length) + { + if (gainControl.getMute()) + Arrays.fill(buffer, offset, offset + length, (byte) 0); + else + { + float db = gainControl.getDB(); + + if (db != 0) + { + // factor = pow(10, dB/10) + double factor = Math.pow(10, (db / 10d)); + + for (int i = offset, toIndex = offset + length; + i < toIndex; + i += 2) + { + int i1 = i + 1; + short s = (short) ((buffer[i] & 0xff) | (buffer[i1] << 8)); + + /* Clip, don't wrap. */ + int si = (int) (s * factor); + + if (si > Short.MAX_VALUE) + s = Short.MAX_VALUE; + else if (si < Short.MIN_VALUE) + s = Short.MIN_VALUE; + else + s = (short) si; + + buffer[i] = (byte) s; + buffer[i1] = (byte) (s >> 8); + } + } + } + } + + /** * Closes this PlugIn. */ public synchronized void close() @@ -504,31 +552,8 @@ public class PortAudioRenderer if (numberOfWrites > 0) { // if we have some volume setting apply them - if(gainControl != null) - { - if(gainControl.getMute()) - { - Arrays.fill(buffer, (byte)0); - } - else if(gainControl.getDB() != 0) - { - // increase/decrease a little more than - // if using levels for factor - // we use factor = pow(10, dB/10), - // but level = pow(10, dB/20); - double factor = Math.pow(10, (gainControl.getDB() / 10d)); - - for (int i = 0; i < buffer.length; i+=2) - { - short s = (short)((buffer[i]&0xff) - | (buffer[i + 1]<<8)); - s = (short)(s*factor); - - buffer[i] = (byte) s; - buffer[i+1] = (byte) (s >> 8); - } - } - } + if (gainControl != null) + applyGain(buffer, offset, length); PortAudio.Pa_WriteStream( stream, -- cgit v1.1