Initial commit of redesigned internal processing and audio management.

Note: Several of the decoders are currently non-functioning in this
commit.  If you want the latest functioning codebase, please checkout
the commit prior to this one.  All decoders will eventually be updated
with this new architecture.

Currently broken:
- Logging and recording
- Aux decoders (Fleetsync/MDC/LoJack/Tait)
- LTR/Passport decoders

Changes in this commit:
- Module architecture for decoders and components with central
provisioning by the DecoderFactory
- Transition from Complex sample stream processing to float buffer
processing for improved memory management
- Redesigned filter structures - to support buffers and streams
- Resolved several memory leak issues
- Universal sharing of the thread pool manager
- Added centralized audio management with call/user prioritization and
new gui with mute/volume controls
- Embedded audio metadata for eventual streaming support
- Redesigned ProcessingChain to support independent re-use
- Added new TrafficChannelManager to handle traffic channel allocations
- Traffic Channel pool size and Call timeout available in P25 and
MPT1327 configs
- Redesigned channel and decoder gui components
This commit is contained in:
denny
2015-09-01 07:10:26 -04:00
parent 538a299246
commit f4d8ea281d
570 changed files with 21578 additions and 17012 deletions

View File

@@ -21,12 +21,12 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import module.ProcessingChainOld;
import properties.SystemProperties;
import record.config.RecordConfiguration;
import record.wave.ComplexWaveRecorder;
import record.wave.FloatWaveRecorder;
import util.TimeStamp;
import controller.channel.ProcessingChain;
public class RecorderManager
{
@@ -36,7 +36,7 @@ public class RecorderManager
{
}
public List<Recorder> getRecorder( ProcessingChain channel )
public List<Recorder> getRecorder( ProcessingChainOld channel )
{
/* Note: the file suffix (ie .wav) gets added by the recorder */

View File

@@ -19,6 +19,7 @@ package record.wave;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.LinkedBlockingQueue;
import javax.sound.sampled.AudioFormat;
@@ -29,15 +30,14 @@ import org.slf4j.LoggerFactory;
import record.Recorder;
import record.RecorderType;
import sample.Listener;
import sample.complex.ComplexSample;
import sample.complex.ComplexBuffer;
import util.waveaudio.WaveWriter;
import buffer.ComplexSampleBufferAssembler;
/**
* Threaded WAVE audio recorder for recording complex (I&Q) samples to a wave
* file
*/
public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSample>
public class ComplexWaveRecorder extends Recorder implements Listener<ComplexBuffer>
{
private final static Logger mLog =
LoggerFactory.getLogger( ComplexWaveRecorder.class );
@@ -48,11 +48,12 @@ public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSam
private WaveWriter mWriter;
private String mFileName;
private BufferProcessor mBufferProcessor;
private Listener<ComplexBuffer> mListener;
//Sample buffer queue ... constrained to 512 sample buffers (arbitrary size)
private LinkedBlockingQueue<ByteBuffer> mToWriteBufferQueue =
new LinkedBlockingQueue<ByteBuffer>( 512 );
private ComplexSampleBufferAssembler mCurrentBuffer;
public ComplexWaveRecorder( int sampleRate, String filename )
{
@@ -64,11 +65,28 @@ public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSam
true, //Signed
false ); //Little Endian
mCurrentBuffer = new ComplexSampleBufferAssembler( sampleRate );
mFileName = filename;
}
/**
* Converts the float samples in a complex buffer to a little endian 16-bit
* buffer
*/
public static ByteBuffer convert( ComplexBuffer buffer )
{
float[] samples = buffer.getSamples();
ByteBuffer converted = ByteBuffer.allocate( samples.length * 2 );
converted.order( ByteOrder.LITTLE_ENDIAN );
for( float sample: samples )
{
converted.putShort( (short)( sample * Short.MAX_VALUE ) );
}
return converted;
}
@Override
public String getFileName()
{
@@ -131,23 +149,26 @@ public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSam
}
@Override
public void receive( ComplexSample sample )
public void receive( ComplexBuffer buffer )
{
mCurrentBuffer.put( sample );
if( !mCurrentBuffer.hasRemaining() )
//Dispatch the buffer to be written to disk
if( !mToWriteBufferQueue.offer( convert( buffer ) ) )
{
//Dispatch the buffer to be written to disk
if( !mToWriteBufferQueue.offer( mCurrentBuffer.get() ) )
{
//We had an overflow ... log it
mLog.error( "ComplexWaveRecorder: buffer overflow - throwing "
+ "away 1 second of sample data" );
}
mCurrentBuffer.clear();
//We had an overflow ... log it
mLog.error( "ComplexWaveRecorder: buffer overflow - throwing "
+ "away a buffer of sample data" );
}
if( mListener != null )
{
mListener.receive( buffer );
}
}
public void setListener( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
public class BufferProcessor extends Thread
{
@@ -175,5 +196,4 @@ public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSam
}
}
}
}

View File

@@ -19,6 +19,7 @@ package record.wave;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.LinkedBlockingQueue;
import javax.sound.sampled.AudioFormat;
@@ -28,6 +29,9 @@ import org.slf4j.LoggerFactory;
import record.Recorder;
import record.RecorderType;
import sample.Listener;
import sample.complex.ComplexBuffer;
import sample.real.RealBuffer;
import sample.real.RealSampleListener;
import util.waveaudio.WaveWriter;
import buffer.FloatSampleBufferAssembler;
@@ -35,7 +39,8 @@ import buffer.FloatSampleBufferAssembler;
/**
* Threaded WAVE audio recorder for recording mono float samples to a wave file
*/
public class FloatWaveRecorder extends Recorder implements RealSampleListener
public class FloatWaveRecorder extends Recorder implements RealSampleListener,
Listener<RealBuffer>
{
private final static Logger mLog =
LoggerFactory.getLogger( FloatWaveRecorder.class );
@@ -52,6 +57,8 @@ public class FloatWaveRecorder extends Recorder implements RealSampleListener
new LinkedBlockingQueue<ByteBuffer>( 512 );
private FloatSampleBufferAssembler mCurrentBuffer;
private Listener<RealBuffer> mListener;
public FloatWaveRecorder( int sampleRate, String filename )
{
super( RecorderType.AUDIO );
@@ -67,6 +74,11 @@ public class FloatWaveRecorder extends Recorder implements RealSampleListener
mFileName = filename;
}
public void setListener( Listener<RealBuffer> listener )
{
mListener = listener;
}
@Override
public String getFileName()
{
@@ -127,7 +139,42 @@ public class FloatWaveRecorder extends Recorder implements RealSampleListener
}
}
}
@Override
public void receive( RealBuffer buffer )
{
//Dispatch the buffer to be written to disk
if( !mToWriteBufferQueue.offer( convert( buffer ) ) )
{
//We had an overflow ... log it
mLog.error( "buffer overflow - throwing away a buffer of sample data" );
}
if( mListener != null )
{
mListener.receive( buffer );
}
}
/**
* Converts the float samples in a complex buffer to a little endian 16-bit
* buffer
*/
public static ByteBuffer convert( RealBuffer buffer )
{
float[] samples = buffer.getSamples();
ByteBuffer converted = ByteBuffer.allocate( samples.length * 2 );
converted.order( ByteOrder.LITTLE_ENDIAN );
for( float sample: samples )
{
converted.putShort( (short)( sample * Short.MAX_VALUE ) );
}
return converted;
}
@Override
public void receive( float sample )
{
@@ -173,5 +220,4 @@ public class FloatWaveRecorder extends Recorder implements RealSampleListener
}
}
}
}