[WIP] Updates the sample adapters to natively use ReusableBuffers.

Refactors a MixerReader instance from the RealMixerSource so that it
can be reused for both real and complex data outputs.

Updates RealMixerSource to use refactored MixerReader and use a default
sample rate of 8 kHz.

Updates the ComplexMixer to use the refactored MixerReader.

Updates the FCD 1/2 tuners for compatibility with the new ComplexMixer.

Removes several unused classes.
This commit is contained in:
Denny
2018-06-24 09:50:36 -04:00
parent 19fa256c60
commit a621a31aa9
19 changed files with 672 additions and 760 deletions

View File

@@ -15,14 +15,9 @@
******************************************************************************/
package io.github.dsheirer.sample.adapter;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import io.github.dsheirer.sample.buffer.ReusableBuffer;
public interface IComplexSampleAdapter
public abstract class AbstractSampleAdapter<T extends ReusableBuffer>
{
/**
* Converts the sample byte array into complex float samples, loading the converted float samples into the buffer.
* @param samples
* @param reusableComplexBuffer
*/
void convertAndLoad(byte[] samples, ReusableComplexBuffer reusableComplexBuffer);
public abstract T convert(byte[] sampleBytes);
}

View File

@@ -1,52 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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.adapter;
public class ByteSampleAdapter implements ISampleAdapter
{
private final static float[] LOOKUP_VALUES;
/**
* Creates a static lookup table that converts the 8-bit valued range
* from 0 - 255 into scaled float values of -1.0 to 0 to 1.0
*/
static
{
LOOKUP_VALUES = new float[ 256 ];
for( int x = 0; x < 256; x++ )
{
LOOKUP_VALUES[ x ] = (float)( x - 127 ) / 128.0f;
}
}
@Override
public float[] convert( byte[] samples )
{
float[] convertedSamples = new float[ samples.length ];
int pointer = 0;
for( byte sample: samples )
{
/* Convert byte value into float from the lookup table */
convertedSamples[ pointer++ ] = LOOKUP_VALUES[ ( sample & 0xFF ) ];
}
return convertedSamples;
}
}

View File

@@ -1,87 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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.adapter;
import io.github.dsheirer.source.mixer.MixerChannel;
import org.apache.commons.lang3.Validate;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Converts 16-bit little endian byte data into an array of floats
*/
public class ChannelShortAdapter implements ISampleAdapter
{
private ShortToFloatMap mMap = new ShortToFloatMap();
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
private MixerChannel mMixerChannel;
public ChannelShortAdapter( MixerChannel channel )
{
/* Only use with LEFT/RIGHT channels */
Validate.isTrue(channel != MixerChannel.MONO);
mMixerChannel = channel;
}
@Override
public float[] convert( byte[] samples )
{
float[] processed = new float[ samples.length / 4 ];
int pointer = 0;
/* Wrap byte array in a byte buffer so we can process them as shorts */
ByteBuffer buffer = ByteBuffer.wrap( samples );
/* Set endian to correct byte ordering */
buffer.order( mByteOrder );
while( buffer.hasRemaining() )
{
if( mMixerChannel == MixerChannel.LEFT )
{
processed[ pointer ] = mMap.get( buffer.getShort() );
/* Throw away the right channel */
buffer.getShort();
}
else
{
/* Throw away the left channel */
buffer.getShort();
processed[ pointer ] = mMap.get( buffer.getShort() );
}
pointer++;
}
return processed;
}
/**
* Set byte interpretation to little or big endian. Defaults to LITTLE
* endian
*/
public void setByteOrder( ByteOrder order )
{
mByteOrder = order;
}
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
* 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.adapter;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import io.github.dsheirer.sample.buffer.ReusableComplexBufferQueue;
public abstract class ComplexSampleAdapter extends AbstractSampleAdapter<ReusableComplexBuffer>
{
private ReusableComplexBufferQueue mReusableBufferQueue;
/**
* Constructs a real sample adapter
*
* @param debugName to use for debug logging
*/
public ComplexSampleAdapter(String debugName)
{
mReusableBufferQueue = new ReusableComplexBufferQueue(debugName);
}
protected ReusableComplexBuffer getBuffer(int size)
{
return mReusableBufferQueue.getBuffer(size);
}
}

View File

@@ -16,43 +16,61 @@
package io.github.dsheirer.sample.adapter;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* Converts 16-bit little endian byte data into an array of complex floats
* Converts 16-bit/2-byte little endian byte data into a reusable buffer of complex float sample data
*/
public class ComplexShortAdapter implements IComplexSampleAdapter
public class ComplexShortAdapter extends ComplexSampleAdapter
{
private final static Logger mLog = LoggerFactory.getLogger(ComplexShortAdapter.class);
private ShortToFloatMap mMap = new ShortToFloatMap();
private FloatBuffer mFloatBuffer;
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
private ByteBuffer mByteBuffer;
/**
* Constructs a real sample adapter
*
* @param debugName to use for debug logging
*/
public ComplexShortAdapter(String debugName)
{
super(debugName);
}
@Override
public void convertAndLoad(byte[] samples, ReusableComplexBuffer reusableComplexBuffer)
public ReusableComplexBuffer convert(byte[] samples)
{
int sampleCount = samples.length / 2;
ReusableComplexBuffer reusableBuffer = getBuffer(samples.length / 2);
float[] convertedSamples = reusableBuffer.getSamples();
if(mFloatBuffer == null || mFloatBuffer.capacity() != sampleCount)
{
mFloatBuffer = FloatBuffer.allocate(sampleCount);
}
int pointer = 0;
mFloatBuffer.rewind();
/* Wrap byte array in a byte buffer so we can process them as shorts */
ByteBuffer buffer = ByteBuffer.wrap(samples);
mByteBuffer = ByteBuffer.wrap(samples);
/* Set endian to correct byte ordering */
buffer.order(mByteOrder);
mByteBuffer.order(mByteOrder);
while(buffer.hasRemaining())
while(mByteBuffer.hasRemaining())
{
mFloatBuffer.put(mMap.get(buffer.getShort()));
convertedSamples[pointer] = mMap.get(mByteBuffer.getShort());
pointer++;
}
reusableComplexBuffer.reloadFrom(mFloatBuffer, System.currentTimeMillis());
reusableBuffer.incrementUserCount();
return reusableBuffer;
}
/**
* Set byte interpretation to little or big endian. Defaults to LITTLE
* endian
*/
public void setByteOrder(ByteOrder order)
{
mByteOrder = order;
}
}

View File

@@ -1,57 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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.adapter;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.complex.Complex;
import io.github.dsheirer.source.mixer.MixerChannel;
import java.util.List;
/**
* Receives complex samples and send either the left channel or the right
* channel to the short sample listener
*/
public class ComplexToFloatSampleConverter implements Listener<List<Complex>>
{
private MixerChannel mChannel;
private Listener<Float> mListener;
public ComplexToFloatSampleConverter( Listener<Float> listener,
MixerChannel channel )
{
mListener = listener;
mChannel = channel;
}
@Override
public void receive( List<Complex> samples )
{
for( Complex sample: samples )
{
mListener.receive( mChannel == MixerChannel.LEFT ?
sample.left() :
sample.right() );
}
}
public Listener<Float> getListener()
{
return mListener;
}
}

View File

@@ -1,61 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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.adapter;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.complex.Complex;
public class FloatArrayToComplexAdapter implements Listener<Float[]>
{
private Listener<Complex> mListener;
@Override
public void receive( Float[] samples )
{
if( samples != null )
{
for( int x = 0; x < samples.length; x += 2 )
{
if( mListener != null &&
samples[ x ] != null &&
samples[ x + 1 ] != null )
{
mListener.receive( new Complex( samples[ x ],
samples[ x + 1 ] ) );
}
}
samples = null;
}
}
public void setListener( Listener<Complex> listener )
{
mListener = listener;
}
public void removeListener( Listener<Complex> listener )
{
mListener = null;
}
public void dispose()
{
mListener = null;
}
}

View File

@@ -1,27 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014,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.adapter;
/*
* Adapter to convert byte data received from a data stream into float[]
* samples
*/
public interface ISampleAdapter
{
public abstract float[] convert( byte[] samples );
}

View File

@@ -0,0 +1,91 @@
/*******************************************************************************
* 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.adapter;
import io.github.dsheirer.sample.buffer.ReusableBuffer;
import io.github.dsheirer.source.mixer.MixerChannel;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Adapter for converting stereo/2-channel short sample data to single channel float samples.
*/
public class RealChannelShortAdapter extends RealSampleAdapter
{
private final static Logger mLog = LoggerFactory.getLogger(RealChannelShortAdapter.class);
private ShortToFloatMap mMap = new ShortToFloatMap();
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
private MixerChannel mMixerChannel;
private ByteBuffer mByteBuffer;
public RealChannelShortAdapter(MixerChannel channel, String debugName)
{
super(debugName);
/* Only use with LEFT/RIGHT channels */
Validate.isTrue(channel != MixerChannel.MONO);
mMixerChannel = channel;
}
@Override
public ReusableBuffer convert(byte[] samples)
{
ReusableBuffer reusableBuffer = getBuffer(samples.length / 4);
float[] convertedSamples = reusableBuffer.getSamples();
mByteBuffer = ByteBuffer.wrap(samples);
/* Set endian to correct byte ordering */
mByteBuffer.order(mByteOrder);
int pointer = 0;
while(mByteBuffer.hasRemaining())
{
if(mMixerChannel == MixerChannel.LEFT)
{
convertedSamples[pointer++] = mMap.get(mByteBuffer.getShort());
//Throw away the right channel
mByteBuffer.getShort();
}
else
{
//Throw away the left channel
mByteBuffer.getShort();
convertedSamples[pointer++] = mMap.get(mByteBuffer.getShort());
}
}
reusableBuffer.incrementUserCount();
return reusableBuffer;
}
/**
* Set byte interpretation to little or big endian. Defaults to LITTLE
* endian
*/
public void setByteOrder(ByteOrder order)
{
mByteOrder = order;
}
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
* 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.adapter;
import io.github.dsheirer.sample.buffer.ReusableBuffer;
import io.github.dsheirer.sample.buffer.ReusableBufferQueue;
public abstract class RealSampleAdapter extends AbstractSampleAdapter<ReusableBuffer>
{
private ReusableBufferQueue mReusableBufferQueue;
/**
* Constructs a real sample adapter
*
* @param debugName to use for debug logging
*/
public RealSampleAdapter(String debugName)
{
mReusableBufferQueue = new ReusableBufferQueue(debugName);
}
protected ReusableBuffer getBuffer(int size)
{
return mReusableBufferQueue.getBuffer(size);
}
}

View File

@@ -0,0 +1,73 @@
/*******************************************************************************
* 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.adapter;
import io.github.dsheirer.sample.buffer.ReusableBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Converts 16-bit/2-byte little endian byte data into a reusable buffer of real float sample data
*/
public class RealShortAdapter extends RealSampleAdapter
{
private ByteBuffer mByteBuffer;
private ShortToFloatMap mMap = new ShortToFloatMap();
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
/**
* Constructs a real sample adapter
*
* @param debugName to use for debug logging
*/
public RealShortAdapter(String debugName)
{
super(debugName);
}
@Override
public ReusableBuffer convert(byte[] samples)
{
ReusableBuffer reusableBuffer = getBuffer(samples.length / 2);
float[] convertedSamples = reusableBuffer.getSamples();
int pointer = 0;
mByteBuffer = ByteBuffer.wrap(samples);
/* Set endian to correct byte ordering */
mByteBuffer.order(mByteOrder);
while(mByteBuffer.hasRemaining())
{
convertedSamples[pointer] = mMap.get(mByteBuffer.getShort());
pointer++;
}
reusableBuffer.incrementUserCount();
return reusableBuffer;
}
/**
* Set byte interpretation to little or big endian. Defaults to LITTLE
* endian
*/
public void setByteOrder(ByteOrder order)
{
mByteOrder = order;
}
}

View File

@@ -1,62 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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.adapter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Converts 16-bit little endian byte data into an array of floats
*/
public class ShortAdapter implements ISampleAdapter
{
private ShortToFloatMap mMap = new ShortToFloatMap();
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
@Override
public float[] convert( byte[] samples )
{
float[] processed = new float[ samples.length / 2 ];
int pointer = 0;
/* Wrap byte array in a byte buffer so we can process them as shorts */
ByteBuffer buffer = ByteBuffer.wrap( samples );
/* Set endian to correct byte ordering */
buffer.order( mByteOrder );
while( buffer.hasRemaining() )
{
processed[ pointer ] = mMap.get( buffer.getShort() );
pointer++;
}
return processed;
}
/**
* Set byte interpretation to little or big endian. Defaults to LITTLE
* endian
*/
public void setByteOrder( ByteOrder order )
{
mByteOrder = order;
}
}

View File

@@ -1,25 +0,0 @@
package io.github.dsheirer.sample.adapter;
import io.github.dsheirer.source.tuner.hackrf.HackRFTunerController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test
{
private final static Logger mLog =
LoggerFactory.getLogger( HackRFTunerController.class );
public static void main( String[] args )
{
mLog.debug( "Starting" );
ShortToFloatMap map1 = new ShortToFloatMap();
for( short x = -32768; x < -32758; x++ )
{
mLog.debug( "X:" + x + " value:" + map1.get( x ) );
}
mLog.debug( "Finished" );
}
}