mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-11 08:07:24 -05:00
Audio outputs - added exception handler to catch any errors that occur
while the buffer processor thread is running. Added check for 0 space available in data line buffers to avoid trying to write a zero-length audio chunk to the data line. Added thread sleep for 100 milliseconds when we detect that the data line buffer is full, to allow time for the data line to drain before we check it again. Hopefully this should minimize the chattering during playback when the code was repeatedly hitting the available() method to check for space availability.
This commit is contained in:
@@ -24,7 +24,6 @@ import audio.AudioEvent;
|
||||
import audio.AudioFormats;
|
||||
import audio.AudioPacket;
|
||||
import audio.AudioPacket.Type;
|
||||
import audio.output.StereoAudioOutput.QueueProcessor;
|
||||
import controller.NamingThreadFactory;
|
||||
|
||||
/**
|
||||
@@ -144,96 +143,115 @@ public class MonoAudioOutput extends AudioOutput
|
||||
{
|
||||
private AtomicBoolean mProcessing = new AtomicBoolean();
|
||||
|
||||
public QueueProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
/* The mProcessing flag ensures that only one instance of the
|
||||
* processor can run at any given time */
|
||||
if( mProcessing.compareAndSet( false, true ) )
|
||||
try
|
||||
{
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
mBuffer.drainTo( packets );
|
||||
|
||||
if( packets.size() > 0 )
|
||||
/* The mProcessing flag ensures that only one instance of the
|
||||
* processor can run at any given time */
|
||||
if( mProcessing.compareAndSet( false, true ) )
|
||||
{
|
||||
broadcast( mAudioContinuationEvent );
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
for( AudioPacket packet: packets )
|
||||
mBuffer.drainTo( packets );
|
||||
|
||||
if( packets.size() > 0 )
|
||||
{
|
||||
if( mCanProcessAudio )
|
||||
broadcast( mAudioContinuationEvent );
|
||||
|
||||
for( AudioPacket packet: packets )
|
||||
{
|
||||
if( isSquelched() )
|
||||
if( mCanProcessAudio )
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
else if( packet.getType() == Type.AUDIO )
|
||||
{
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
/* Little-endian byte buffer */
|
||||
ByteBuffer buffer =
|
||||
ByteBuffer.allocate( samples.length * 2 )
|
||||
.order( ByteOrder.LITTLE_ENDIAN );
|
||||
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
|
||||
for( float sample: samples )
|
||||
if( isSquelched() )
|
||||
{
|
||||
shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
|
||||
checkStop();
|
||||
}
|
||||
|
||||
if( mOutput.available() >= buffer.array().length )
|
||||
else if( packet.getType() == Type.AUDIO )
|
||||
{
|
||||
mOutput.write( buffer.array(), 0,
|
||||
buffer.array().length );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
int wrote = 0;
|
||||
|
||||
int toWrite = buffer.array().length;
|
||||
float[] samples = packet.getAudioBuffer().getSamples();
|
||||
|
||||
while( toWrite > 0 )
|
||||
{
|
||||
int available = mOutput.available();
|
||||
/* Little-endian byte buffer */
|
||||
ByteBuffer buffer =
|
||||
ByteBuffer.allocate( samples.length * 2 )
|
||||
.order( ByteOrder.LITTLE_ENDIAN );
|
||||
|
||||
ShortBuffer shortBuffer = buffer.asShortBuffer();
|
||||
|
||||
if( available < toWrite )
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
available );
|
||||
}
|
||||
else
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
toWrite );
|
||||
}
|
||||
for( float sample: samples )
|
||||
{
|
||||
shortBuffer.put( (short)( sample * Short.MAX_VALUE ) );
|
||||
}
|
||||
|
||||
if( mOutput.available() >= buffer.array().length )
|
||||
{
|
||||
mOutput.write( buffer.array(), 0,
|
||||
buffer.array().length );
|
||||
|
||||
checkStart();
|
||||
|
||||
toWrite = buffer.array().length - wrote;
|
||||
}
|
||||
}
|
||||
|
||||
broadcast( packet.getAudioMetadata() );
|
||||
else
|
||||
{
|
||||
int wrote = 0;
|
||||
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
int toWrite = buffer.array().length;
|
||||
|
||||
while( toWrite > 0 )
|
||||
{
|
||||
int available = mOutput.available();
|
||||
|
||||
if( available < toWrite )
|
||||
{
|
||||
if( available > 0 )
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(),
|
||||
wrote, available );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep( 100 );
|
||||
}
|
||||
catch ( InterruptedException e )
|
||||
{
|
||||
mLog.debug( "Mono Audio Output - interrupted while sleeping awaiting buffer drain" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
toWrite );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
|
||||
toWrite = buffer.array().length - wrote;
|
||||
}
|
||||
}
|
||||
|
||||
broadcast( packet.getAudioMetadata() );
|
||||
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
|
||||
mProcessing.set( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
|
||||
mProcessing.set( false );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Error while processing audio buffers", e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,78 +177,90 @@ public class StereoAudioOutput extends AudioOutput
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
/* The mProcessing flag ensures that only one instance of the
|
||||
* processor can run at any given time */
|
||||
if( mProcessing.compareAndSet( false, true ) )
|
||||
try
|
||||
{
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
mBuffer.drainTo( packets );
|
||||
|
||||
if( packets.size() > 0 )
|
||||
/* The mProcessing flag ensures that only one instance of the
|
||||
* processor can run at any given time */
|
||||
if( mProcessing.compareAndSet( false, true ) )
|
||||
{
|
||||
broadcast( mAudioContinuationEvent );
|
||||
List<AudioPacket> packets = new ArrayList<AudioPacket>();
|
||||
|
||||
for( AudioPacket packet: packets )
|
||||
mBuffer.drainTo( packets );
|
||||
|
||||
if( packets.size() > 0 )
|
||||
{
|
||||
if( mCanProcessAudio )
|
||||
broadcast( mAudioContinuationEvent );
|
||||
|
||||
for( AudioPacket packet: packets )
|
||||
{
|
||||
if( isSquelched() )
|
||||
if( mCanProcessAudio )
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
else if( packet.getType() == Type.AUDIO )
|
||||
{
|
||||
ByteBuffer buffer = convert(
|
||||
packet.getAudioBuffer().getSamples() );
|
||||
|
||||
if( mOutput.available() >= buffer.array().length )
|
||||
if( isSquelched() )
|
||||
{
|
||||
mOutput.write( buffer.array(), 0,
|
||||
buffer.array().length );
|
||||
|
||||
checkStart();
|
||||
checkStop();
|
||||
}
|
||||
else
|
||||
else if( packet.getType() == Type.AUDIO )
|
||||
{
|
||||
int wrote = 0;
|
||||
|
||||
int toWrite = buffer.array().length;
|
||||
ByteBuffer buffer = convert(
|
||||
packet.getAudioBuffer().getSamples() );
|
||||
|
||||
while( toWrite > 0 )
|
||||
if( mOutput.available() >= buffer.array().length )
|
||||
{
|
||||
int available = mOutput.available();
|
||||
|
||||
if( available < toWrite )
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
available );
|
||||
}
|
||||
else
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
toWrite );
|
||||
}
|
||||
mOutput.write( buffer.array(), 0,
|
||||
buffer.array().length );
|
||||
|
||||
checkStart();
|
||||
|
||||
toWrite = buffer.array().length - wrote;
|
||||
}
|
||||
else
|
||||
{
|
||||
int wrote = 0;
|
||||
|
||||
int toWrite = buffer.array().length;
|
||||
|
||||
while( toWrite > 0 )
|
||||
{
|
||||
int available = mOutput.available();
|
||||
|
||||
if( available < toWrite )
|
||||
{
|
||||
if( available > 0 )
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(),
|
||||
wrote, available );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wrote += mOutput.write( buffer.array(), wrote,
|
||||
toWrite );
|
||||
|
||||
checkStart();
|
||||
}
|
||||
|
||||
toWrite = buffer.array().length - wrote;
|
||||
}
|
||||
}
|
||||
|
||||
broadcast( packet.getAudioMetadata() );
|
||||
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
broadcast( packet.getAudioMetadata() );
|
||||
|
||||
mLastActivity = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
|
||||
mProcessing.set( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
checkStop();
|
||||
}
|
||||
|
||||
mProcessing.set( false );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Error while processing audio buffers", e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user