mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
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:
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user