Fix playing portaudio notifications, remove writer thread in portaudio renderer seems to be the issue with low quality of played sound durring call.

cusax-fix
Damian Minkov 17 years ago
parent 325a6f5c05
commit d1b328fd7e

@ -12,6 +12,7 @@
import net.java.sip.communicator.impl.media.*;
import net.java.sip.communicator.impl.media.device.*;
import net.java.sip.communicator.service.audionotifier.*;
import net.java.sip.communicator.util.*;
/**
* The implementation of the AudioNotifierService.
@ -19,7 +20,8 @@
* @author Yana Stamcheva
*/
public class AudioNotifierServiceImpl
implements AudioNotifierService
implements AudioNotifierService,
PropertyChangeListener
{
private static final Map<String, SCAudioClipImpl> audioClips =
new HashMap<String, SCAudioClipImpl>();
@ -38,6 +40,7 @@ public class AudioNotifierServiceImpl
public AudioNotifierServiceImpl(DeviceConfiguration deviceConfiguration)
{
this.deviceConfiguration = deviceConfiguration;
deviceConfiguration.addPropertyChangeListener(this);
}
/**
@ -156,4 +159,17 @@ public DeviceConfiguration getDeviceConfiguration()
{
return deviceConfiguration;
}
/**
* Listens for changes in notify device
* @param evt the event that notify device has changed.
*/
public void propertyChange(PropertyChangeEvent evt)
{
if(evt.getPropertyName().equals(
DeviceConfiguration.AUDIO_NOTIFY_DEVICE))
{
audioClips.clear();
}
}
}

@ -12,7 +12,6 @@
import javax.sound.sampled.*;
import net.java.sip.communicator.impl.media.protocol.portaudio.*;
import net.java.sip.communicator.impl.media.device.*;
import net.java.sip.communicator.util.*;
/**
@ -22,19 +21,14 @@
*/
public class PortAudioClipImpl
extends SCAudioClipImpl
implements PropertyChangeListener
{
private static final Logger logger
= Logger.getLogger(PortAudioClipImpl.class);
private final AudioNotifierServiceImpl audioNotifier;
private Thread playThread = new Thread(new PlayThread());
private boolean started = false;
private long portAudioStream = 0;
private URL url = null;
/**
@ -50,8 +44,6 @@ public PortAudioClipImpl(URL url, AudioNotifierServiceImpl audioNotifier)
{
this.audioNotifier = audioNotifier;
this.url = url;
audioNotifier.getDeviceConfiguration().addPropertyChangeListener(this);
}
/**
@ -62,7 +54,7 @@ public void play()
if ((url != null) && !audioNotifier.isMute())
{
started = true;
playThread.start();
new Thread(new PlayThread()).start();
}
}
@ -79,7 +71,7 @@ public void playInLoop(int interval)
if(!audioNotifier.isMute())
{
started = true;
playThread.start();
new Thread(new PlayThread()).start();
}
}
@ -105,24 +97,10 @@ public void internalStop()
started = false;
}
/**
* Notified when device configuration has changed.
* @param evt the event of the change
*/
public void propertyChange(PropertyChangeEvent evt)
{
if(evt.getPropertyName().equals(
DeviceConfiguration.AUDIO_NOTIFY_DEVICE))
{
// make the stream 0, to be sure next time the new
// device will be used
portAudioStream = 0;
}
}
private class PlayThread
implements Runnable
{
private long portAudioStream = 0;
byte[] buffer = new byte[1024];
public void run()

@ -42,9 +42,7 @@ public class PortAudioRenderer
boolean started = false;
private WriterThread writerThread = null;
private final Object bufferSync = new Object();
private byte[] buffer = null;
// private final Object bufferSync = new Object();
private static int deviceIndex = -1;
@ -98,20 +96,16 @@ public void start()
/**
* Halts the rendering process.
*/
public void stop()
public synchronized void stop()
{
synchronized(bufferSync)
try
{
try
{
started = false;
PortAudio.Pa_CloseStream(stream);
writerThread = null;
}
catch (PortAudioException e)
{
logger.error("Closing portaudio stream failed", e);
}
started = false;
PortAudio.Pa_CloseStream(stream);
}
catch (PortAudioException e)
{
logger.error("Closing portaudio stream failed", e);
}
}
@ -121,26 +115,24 @@ public void stop()
* @param inputBuffer the input data.
* @return BUFFER_PROCESSED_OK if the processing is successful.
*/
public int process(Buffer inputBuffer)
public synchronized int process(Buffer inputBuffer)
{
synchronized(bufferSync)
{
byte[] buff = new byte[inputBuffer.getLength()];
System.arraycopy(
(byte[])inputBuffer.getData(),
inputBuffer.getOffset(),
buff,
0,
buff.length);
byte[] buff = new byte[inputBuffer.getLength()];
System.arraycopy(
(byte[])inputBuffer.getData(),
inputBuffer.getOffset(),
buff,
0,
buff.length);
buffer = buff;
bufferSync.notifyAll();
try
{
PortAudio.Pa_WriteStream(
stream, buff, buff.length/frameSize);
}
if(writerThread == null)
catch (PortAudioException e)
{
writerThread = new WriterThread();
writerThread.start();
logger.error("Error writing to device", e);
}
return BUFFER_PROCESSED_OK;
@ -273,50 +265,4 @@ public static void setDevice(MediaLocator locator)
= PortAudio.Pa_GetSampleSize(PortAudio.SAMPLE_FORMAT_INT16)
* outputChannels;
}
/**
* Writes data to the portaudio stream. If there is no data for
* particular time write some silence so we wont hear some cracks in
* the sound.
*/
private class WriterThread
extends Thread
{
public WriterThread()
{
setName("Portaudio Renderer");
}
public void run()
{
while(true)
{
try
{
synchronized(bufferSync)
{
// put some silence if there is no data
if(buffer == null)
{
buffer = new byte[1024];
}
PortAudio.Pa_WriteStream(
stream, buffer, buffer.length/frameSize);
buffer = null;
bufferSync.wait(90);
}
if(!started)
return;
}
catch (Exception e)
{
logger.error("writing to stream", e);
}
}
}
}
}

Loading…
Cancel
Save