[WIP] Removes all usage of Buffer, RealBuffer and ComplexBuffer.

This commit is contained in:
Denny
2018-06-30 06:54:36 -04:00
parent 6f1ce79461
commit ad560db5ea
50 changed files with 1224 additions and 2431 deletions

View File

@@ -1,7 +1,6 @@
package io.github.dsheirer.sample;
import io.github.dsheirer.sample.buffer.ReusableBuffer;
import io.github.dsheirer.sample.real.RealBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -53,24 +52,6 @@ public class ConversionUtils
return converted;
}
/**
* Converts the float samples in a complex buffer to a little endian 16-bit
* buffer
*/
public static ByteBuffer convertToSigned16BitSamples(Buffer buffer)
{
return convertToSigned16BitSamples(buffer.getSamples());
}
/**
* Converts the float samples in a complex buffer to a little endian 16-bit
* buffer
*/
public static ByteBuffer convertToSigned16BitSamples(RealBuffer buffer)
{
return convertToSigned16BitSamples(buffer.getSamples());
}
/**
* Converts the float samples in a complex buffer to a little endian 16-bit
* buffer

View File

@@ -13,17 +13,13 @@
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.sample.complex;
package io.github.dsheirer.sample;
import io.github.dsheirer.sample.Buffer;
public class ComplexBuffer extends Buffer
public interface IOverflowListener
{
/**
* Wrapper around float array containing interleaved I/Q samples
* Indicates that the source is in overflow state (true) or out of overflow state (false)
* @param overflow true to indicate an overflow state
*/
public ComplexBuffer(float[] samples)
{
super(samples);
}
void sourceOverflow(boolean overflow);
}

View File

@@ -18,7 +18,6 @@
******************************************************************************/
package io.github.dsheirer.sample;
import io.github.dsheirer.sample.real.IOverflowListener;
import io.github.dsheirer.source.Source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -15,131 +15,66 @@
******************************************************************************/
package io.github.dsheirer.sample.buffer;
import io.github.dsheirer.dsp.filter.channelizer.SampleTimestampManager;
import io.github.dsheirer.sample.Listener;
import org.apache.commons.lang3.Validate;
import java.nio.FloatBuffer;
import io.github.dsheirer.sample.real.RealSampleListener;
/**
* Assembles complex float samples into a ComplexBuffer containing an array of floats. Monitors incoming sample count
* to accurately assign a relative timestamp to each assembled buffer.
* Assembles single float samples into a ReusableBuffer containing an array of floats
*/
public class ReusableBufferAssembler
public class ReusableBufferAssembler implements RealSampleListener
{
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("ReusableBufferAssembler");
private SampleTimestampManager mTimestampManager;
private FloatBuffer mBuffer;
private int mBufferSize;
private long mCurrentBufferTimestamp;
private Listener<ReusableComplexBuffer> mListener;
private int mBufferPointer;
private ReusableBuffer mCurrentBuffer;
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue("Real");
public ReusableBufferAssembler(int bufferSize, double sampleRate)
private Listener<ReusableBuffer> mListener;
public ReusableBufferAssembler(int bufferSize)
{
Validate.isTrue(bufferSize % 2 == 0);
mBufferSize = bufferSize;
mBuffer = FloatBuffer.allocate(mBufferSize);
mTimestampManager = new SampleTimestampManager(sampleRate);
}
/**
* Updates the reference timestamp to use for all subsequent samples that are assembled. This timestamp should
* identify the relative timestamp of the first/next sample that is received by this assembler.
* @param timestamp to use relative to the incoming sample arrays.
*/
public void updateTimestamp(long timestamp)
{
mTimestampManager.setReferenceTimestamp(timestamp);
if(mBuffer.position() == 0)
{
mCurrentBufferTimestamp = timestamp;
}
}
public void dispose()
{
mReusableComplexBufferQueue.dispose();
mListener = null;
}
/**
* Adds the samples to this assembler. As each buffer is assembled, it will be dispatched to the registered
* listener.
*
* @param samples to assemble
*/
public void receive(float[] samples)
public void reset()
{
if(mBuffer.remaining() >= samples.length)
{
mBuffer.put(samples);
mTimestampManager.increment(samples.length / 2);
mCurrentBuffer.decrementUserCount();
mCurrentBuffer = null;
mBufferPointer = 0;
}
if(!mBuffer.hasRemaining())
@Override
public void receive(float sample)
{
if(mCurrentBuffer == null)
{
mCurrentBuffer = mReusableBufferQueue.getBuffer(mBufferSize);
mCurrentBuffer.incrementUserCount();
mBufferPointer = 0;
}
mCurrentBuffer.getSamples()[mBufferPointer++] = sample;
if (mBufferPointer >= mBufferSize)
{
if (mListener != null)
{
flush();
mListener.receive(mCurrentBuffer);
}
}
else
{
int offset = 0;
while(offset < samples.length)
else
{
int toCopy = mBuffer.remaining();
if((samples.length - offset) < toCopy)
{
toCopy = samples.length - offset;
}
mBuffer.put(samples, offset, toCopy);
offset += toCopy;
mTimestampManager.increment(toCopy / 2);
if(!mBuffer.hasRemaining())
{
flush();
}
mCurrentBuffer.decrementUserCount();
}
mCurrentBuffer = null;
}
}
/**
* Adds the samples to this assembler. As each buffer is assembled, it will be dispatched to the registered
* listener.
*/
public void receive(ReusableComplexBuffer samplesBuffer)
{
receive(samplesBuffer.getSamples());
samplesBuffer.decrementUserCount();
}
/**
* Flushes the current buffer contents to the registered listener
*/
public void flush()
{
if(mListener != null && mBuffer.position() > 0)
{
mBuffer.rewind();
ReusableComplexBuffer reusableComplexBuffer = mReusableComplexBufferQueue.getBuffer(mBufferSize);
reusableComplexBuffer.reloadFrom(mBuffer, mCurrentBufferTimestamp);
reusableComplexBuffer.incrementUserCount();
mListener.receive(reusableComplexBuffer);
}
mBuffer.rewind();
mCurrentBufferTimestamp = mTimestampManager.getCurrentTimestamp();
}
/**
* Sets the listener to receive the output from this buffer assembler. Note: the listener is responsible for
* managing the user count for any buffers received from this buffer assembler.
*/
public void setListener(Listener<ReusableComplexBuffer> listener)
public void setListener(Listener<ReusableBuffer> listener)
{
mListener = listener;
}

View File

@@ -0,0 +1,146 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.sample.buffer;
import io.github.dsheirer.dsp.filter.channelizer.SampleTimestampManager;
import io.github.dsheirer.sample.Listener;
import org.apache.commons.lang3.Validate;
import java.nio.FloatBuffer;
/**
* Assembles complex float samples into a ComplexBuffer containing an array of floats. Monitors incoming sample count
* to accurately assign a relative timestamp to each assembled buffer.
*/
public class ReusableComplexBufferAssembler
{
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("ReusableComplexBufferAssembler");
private SampleTimestampManager mTimestampManager;
private FloatBuffer mBuffer;
private int mBufferSize;
private long mCurrentBufferTimestamp;
private Listener<ReusableComplexBuffer> mListener;
public ReusableComplexBufferAssembler(int bufferSize, double sampleRate)
{
Validate.isTrue(bufferSize % 2 == 0);
mBufferSize = bufferSize;
mBuffer = FloatBuffer.allocate(mBufferSize);
mTimestampManager = new SampleTimestampManager(sampleRate);
}
/**
* Updates the reference timestamp to use for all subsequent samples that are assembled. This timestamp should
* identify the relative timestamp of the first/next sample that is received by this assembler.
* @param timestamp to use relative to the incoming sample arrays.
*/
public void updateTimestamp(long timestamp)
{
mTimestampManager.setReferenceTimestamp(timestamp);
if(mBuffer.position() == 0)
{
mCurrentBufferTimestamp = timestamp;
}
}
public void dispose()
{
mReusableComplexBufferQueue.dispose();
mListener = null;
}
/**
* Adds the samples to this assembler. As each buffer is assembled, it will be dispatched to the registered
* listener.
*
* @param samples to assemble
*/
public void receive(float[] samples)
{
if(mBuffer.remaining() >= samples.length)
{
mBuffer.put(samples);
mTimestampManager.increment(samples.length / 2);
if(!mBuffer.hasRemaining())
{
flush();
}
}
else
{
int offset = 0;
while(offset < samples.length)
{
int toCopy = mBuffer.remaining();
if((samples.length - offset) < toCopy)
{
toCopy = samples.length - offset;
}
mBuffer.put(samples, offset, toCopy);
offset += toCopy;
mTimestampManager.increment(toCopy / 2);
if(!mBuffer.hasRemaining())
{
flush();
}
}
}
}
/**
* Adds the samples to this assembler. As each buffer is assembled, it will be dispatched to the registered
* listener.
*/
public void receive(ReusableComplexBuffer samplesBuffer)
{
receive(samplesBuffer.getSamples());
samplesBuffer.decrementUserCount();
}
/**
* Flushes the current buffer contents to the registered listener
*/
public void flush()
{
if(mListener != null && mBuffer.position() > 0)
{
mBuffer.rewind();
ReusableComplexBuffer reusableComplexBuffer = mReusableComplexBufferQueue.getBuffer(mBufferSize);
reusableComplexBuffer.reloadFrom(mBuffer, mCurrentBufferTimestamp);
reusableComplexBuffer.incrementUserCount();
mListener.receive(reusableComplexBuffer);
}
mBuffer.rewind();
mCurrentBufferTimestamp = mTimestampManager.getCurrentTimestamp();
}
/**
* Sets the listener to receive the output from this buffer assembler. Note: the listener is responsible for
* managing the user count for any buffers received from this buffer assembler.
*/
public void setListener(Listener<ReusableComplexBuffer> listener)
{
mListener = listener;
}
}

View File

@@ -1,35 +0,0 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
/**
* Real sample buffer to stream converter
*/
public class ComplexBufferToStreamConverter implements Listener<ComplexBuffer>
{
private ComplexSampleListener mListener;
public void dispose()
{
mListener = null;
}
@Override
public void receive( ComplexBuffer buffer )
{
if( mListener != null )
{
float[] samples = buffer.getSamples();
for( int x = 0; x < samples.length; x += 2 )
{
mListener.receive( samples[ x ], samples[ x + 1 ] );
}
}
}
public void setListener( ComplexSampleListener listener )
{
mListener = listener;
}
}

View File

@@ -1,81 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2015 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
import org.apache.commons.lang3.Validate;
/**
* Assembles complex float samples into a ComplexBuffer containing an array of floats
*/
public class ComplexToComplexBufferAssembler implements ComplexSampleListener
{
private int mBufferSize;
private float[] mBuffer;
private int mBufferPointer;
private Listener<ComplexBuffer> mListener;
public ComplexToComplexBufferAssembler( int bufferSize )
{
Validate.isTrue(bufferSize % 2 == 0);
mBufferSize = bufferSize;
mBuffer = new float[ mBufferSize ];
}
public void dispose()
{
mListener = null;
mBuffer = null;
}
public void reset()
{
mBuffer = new float[ mBufferSize ];
mBufferPointer = 0;
}
@Override
public void receive( float i, float q )
{
if( mBufferPointer >= mBufferSize )
{
if( mListener != null )
{
mListener.receive( new ComplexBuffer( mBuffer ) );
}
mBuffer = new float[ mBufferSize ];
mBufferPointer = 0;
}
mBuffer[ mBufferPointer ] = i;
mBufferPointer++;
mBuffer[ mBufferPointer ] = q;
mBufferPointer++;
}
public void setListener( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
}

View File

@@ -1,55 +0,0 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RateCounter_CB implements Listener<ComplexBuffer>
{
private final static Logger mLog =
LoggerFactory.getLogger( RateCounter_CB.class );
private Listener<ComplexBuffer> mListener;
private long mCount;
private long mStartTime = -1;
private String mName;
public RateCounter_CB()
{
mName = "UNNAMED";
}
public RateCounter_CB( String name )
{
mName = name;
}
@Override
public void receive( ComplexBuffer buffer )
{
if( mStartTime == -1 )
{
mStartTime = System.currentTimeMillis();
}
mCount += ( buffer.getSamples().length / 2 );
long elapsed = System.currentTimeMillis() - mStartTime;
if( elapsed != 0 )
{
mLog.debug( "[" + mName + "] Sample Rate: " + ( mCount / elapsed ) + " kHz" );
}
if( mListener != null )
{
mListener.receive( buffer );
}
}
public void setListener( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
}

View File

@@ -1,8 +0,0 @@
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Listener;
public interface IFilteredRealBufferListener
{
public Listener<RealBuffer> getFilteredRealBufferListener();
}

View File

@@ -1,9 +0,0 @@
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Listener;
public interface IFilteredRealBufferProvider
{
public void setFilteredRealBufferListener( Listener<RealBuffer> listener );
public void removeFilteredRealBufferListener();
}

View File

@@ -1,28 +0,0 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.sample.real;
public interface IOverflowListener
{
/**
* Indicates that the source is in overflow state (true) or out of overflow state (false)
* @param overflow true to indicate an overflow state
*/
void sourceOverflow(boolean overflow);
}

View File

@@ -1,8 +0,0 @@
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Listener;
public interface IUnFilteredRealBufferListener
{
public Listener<RealBuffer> getUnFilteredRealBufferListener();
}

View File

@@ -1,9 +0,0 @@
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Listener;
public interface IUnFilteredRealBufferProvider
{
public void setUnFilteredRealBufferListener( Listener<RealBuffer> listener );
public void removeUnFilteredRealBufferListener();
}

View File

@@ -1,41 +0,0 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Buffer;
import java.util.Arrays;
public class RealBuffer extends Buffer
{
/**
* Wrapper around float array containing real float samples
*/
public RealBuffer(float[] samples)
{
super(samples);
}
/**
* Creates a deep copy of the buffer and a shallow (reference) copy of the source event
*/
public RealBuffer copyOf()
{
float[] copy = Arrays.copyOf(getSamples(), getSamples().length);
return new RealBuffer(copy);
}
}

View File

@@ -1,72 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2015 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.real;
import io.github.dsheirer.sample.Listener;
/**
* Assembles single float samples into a RealBuffer containing an array of floats
*/
public class RealToRealBufferAssembler implements RealSampleListener
{
private int mBufferSize;
private float[] mBuffer;
private int mBufferPointer;
private Listener<RealBuffer> mListener;
public RealToRealBufferAssembler(int bufferSize)
{
mBufferSize = bufferSize;
mBuffer = new float[mBufferSize];
}
public void dispose()
{
mListener = null;
mBuffer = null;
}
public void reset()
{
mBuffer = new float[mBufferSize];
mBufferPointer = 0;
}
@Override
public void receive(float sample)
{
mBuffer[mBufferPointer++] = sample;
if (mBufferPointer >= mBufferSize)
{
if (mListener != null)
{
mListener.receive(new RealBuffer(mBuffer));
}
mBuffer = new float[mBufferSize];
mBufferPointer = 0;
}
}
public void setListener(Listener<RealBuffer> listener)
{
mListener = listener;
}
}