mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
#1351 Restores semi-accurate timestamps of sample buffers to ensure P25 & DMR decoded messages have accurate timestamps and MBE recording voice frames have accurate timestamps. (#1357)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 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.buffer;
|
||||
|
||||
/**
|
||||
* Base native buffer class.
|
||||
*/
|
||||
public abstract class AbstractNativeBuffer implements INativeBuffer
|
||||
{
|
||||
private long mTimestamp;
|
||||
private float mSamplesPerMillisecond;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param timestamp for the start of this buffer
|
||||
* @param samplesPerMillisecond to calculate the time offset of sub-buffers extracted from this native buffer.
|
||||
*/
|
||||
public AbstractNativeBuffer(long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
mTimestamp = timestamp;
|
||||
mSamplesPerMillisecond = samplesPerMillisecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp for the start of this buffer
|
||||
* @return timestamp in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantity of samples representing one millisecond of sample data, used for calculating fragment timestamp offsets.
|
||||
* @return samples per millisecond count.
|
||||
*/
|
||||
public float getSamplesPerMillisecond()
|
||||
{
|
||||
return mSamplesPerMillisecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the timestamp for a samples buffer fragment based on where it is extracted from relative to the
|
||||
* native buffer starting timestamp.
|
||||
* @param samplesPointer for the start of the fragment. Note: this value will be divided by 2 to account for I/Q sample pairs.
|
||||
* @return timestamp adjusted to the fragment or sub-buffer start sample.
|
||||
*/
|
||||
protected long getFragmentTimestamp(int samplesPointer)
|
||||
{
|
||||
return getTimestamp() + (long)(samplesPointer / 2 / getSamplesPerMillisecond());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 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.buffer;
|
||||
|
||||
/**
|
||||
* Base class for native buffer factories.
|
||||
*/
|
||||
public abstract class AbstractNativeBufferFactory implements INativeBufferFactory
|
||||
{
|
||||
private float mSamplesPerMillisecond = 0.0f;
|
||||
|
||||
@Override
|
||||
public void setSamplesPerMillisecond(float samplesPerMillisecond)
|
||||
{
|
||||
mSamplesPerMillisecond = samplesPerMillisecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantity of I/Q sample pairs per milli-second at the current sample rate to use in calculating an accurate
|
||||
* timestamp for sub-buffer that are generated from the native buffer.
|
||||
* @return samples per millisecond.
|
||||
*/
|
||||
public float getSamplesPerMillisecond()
|
||||
{
|
||||
return mSamplesPerMillisecond;
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import java.util.Iterator;
|
||||
* Native buffer sample array wrapper class that provides access to a stream of either interleaved or
|
||||
* non-interleaved complex sample buffers converted from the raw byte sample array.
|
||||
*/
|
||||
public class ByteNativeBuffer implements INativeBuffer
|
||||
public class ByteNativeBuffer extends AbstractNativeBuffer
|
||||
{
|
||||
private static final int FRAGMENT_SIZE = 2048;
|
||||
private final static float[] LOOKUP_VALUES;
|
||||
@@ -46,16 +46,17 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
private byte[] mSamples;
|
||||
private long mTimestamp;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param samples to process
|
||||
* @param timestamp of the samples
|
||||
* @param averageDc measured from sample stream
|
||||
* @param samplesPerMillisecond to calculate derivative timestamps for sub-buffers.
|
||||
*/
|
||||
public ByteNativeBuffer(byte[] samples, long timestamp, float averageDc)
|
||||
public ByteNativeBuffer(byte[] samples, long timestamp, float averageDc, float samplesPerMillisecond)
|
||||
{
|
||||
super(timestamp, samplesPerMillisecond);
|
||||
//Ensure we're an even multiple of the fragment size. Typically, this will be 64k or 128k
|
||||
if(samples.length % FRAGMENT_SIZE != 0)
|
||||
{
|
||||
@@ -63,7 +64,6 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mSamples = samples;
|
||||
mTimestamp = timestamp;
|
||||
mAverageDc = averageDc;
|
||||
}
|
||||
|
||||
@@ -73,12 +73,6 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
return mSamples.length / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ComplexSamples> iterator()
|
||||
{
|
||||
@@ -104,6 +98,8 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
@Override
|
||||
public ComplexSamples next()
|
||||
{
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
float[] i = new float[FRAGMENT_SIZE];
|
||||
float[] q = new float[FRAGMENT_SIZE];
|
||||
int samplesOffset = mSamplesPointer;
|
||||
@@ -115,8 +111,7 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mSamplesPointer = samplesOffset;
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +131,8 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
@Override
|
||||
public InterleavedComplexSamples next()
|
||||
{
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
float[] converted = new float[FRAGMENT_SIZE * 2];
|
||||
|
||||
int samplesPointer = mSamplesPointer;
|
||||
@@ -147,7 +144,7 @@ public class ByteNativeBuffer implements INativeBuffer
|
||||
|
||||
mSamplesPointer = samplesPointer;
|
||||
|
||||
return new InterleavedComplexSamples(converted, mTimestamp);
|
||||
return new InterleavedComplexSamples(converted, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.nio.ByteBuffer;
|
||||
/**
|
||||
* Implements a factory for creating ByteNativeBuffer instances
|
||||
*/
|
||||
public class ByteNativeBufferFactory implements INativeBufferFactory
|
||||
public class ByteNativeBufferFactory extends AbstractNativeBufferFactory
|
||||
{
|
||||
private DcCorrectionManager mDcCorrectionManager = new DcCorrectionManager();
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ByteNativeBufferFactory implements INativeBufferFactory
|
||||
calculateDc(copy);
|
||||
}
|
||||
|
||||
return new ByteNativeBuffer(copy, timestamp, mDcCorrectionManager.getAverageDc());
|
||||
return new ByteNativeBuffer(copy, timestamp, mDcCorrectionManager.getAverageDc(), getSamplesPerMillisecond());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,35 +22,24 @@ package io.github.dsheirer.buffer;
|
||||
import io.github.dsheirer.sample.SampleUtils;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Simple native buffer implementation that simply wraps a single, existing, non-native sample buffer.
|
||||
*/
|
||||
public class FloatNativeBuffer implements INativeBuffer
|
||||
public class FloatNativeBuffer extends AbstractNativeBuffer
|
||||
{
|
||||
private float[] mInterleavedComplexSamples;
|
||||
private long mTimestamp;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param complexSamples to wrap
|
||||
* @param complexSamples interleaved to wrap
|
||||
* @param timestamp for the buffer
|
||||
*/
|
||||
public FloatNativeBuffer(float[] complexSamples, long timestamp)
|
||||
public FloatNativeBuffer(float[] complexSamples, long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(timestamp, samplesPerMillisecond);
|
||||
mInterleavedComplexSamples = complexSamples;
|
||||
mTimestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param complexSamples to wrap
|
||||
*/
|
||||
public FloatNativeBuffer(float[] complexSamples)
|
||||
{
|
||||
this(complexSamples, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,9 +47,9 @@ public class FloatNativeBuffer implements INativeBuffer
|
||||
* @param samples to wrap
|
||||
* @param timestamp for the buffer
|
||||
*/
|
||||
public FloatNativeBuffer(ComplexSamples samples, long timestamp)
|
||||
public FloatNativeBuffer(ComplexSamples samples)
|
||||
{
|
||||
this(SampleUtils.interleave(samples), timestamp);
|
||||
this(SampleUtils.interleave(samples), samples.timestamp(), 0.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +58,7 @@ public class FloatNativeBuffer implements INativeBuffer
|
||||
*/
|
||||
public FloatNativeBuffer(InterleavedComplexSamples samples)
|
||||
{
|
||||
this(samples.samples(), samples.timestamp());
|
||||
this(samples.samples(), samples.timestamp(), 0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,12 +79,6 @@ public class FloatNativeBuffer implements INativeBuffer
|
||||
return mInterleavedComplexSamples.length / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
private class ComplexSamplesIterator implements Iterator<ComplexSamples>
|
||||
{
|
||||
private boolean mEmpty;
|
||||
@@ -115,7 +98,7 @@ public class FloatNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mEmpty = true;
|
||||
return SampleUtils.deinterleave(mInterleavedComplexSamples);
|
||||
return SampleUtils.deinterleave(mInterleavedComplexSamples, getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +122,7 @@ public class FloatNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mEmpty = true;
|
||||
return new InterleavedComplexSamples(mInterleavedComplexSamples, mTimestamp);
|
||||
return new InterleavedComplexSamples(mInterleavedComplexSamples, getTimestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,15 @@ public interface INativeBufferFactory
|
||||
*
|
||||
* @param samples byte array copied from native memory
|
||||
* @param timestamp of the samples
|
||||
* @param samplesPerMillisecond to calculate timestamp offset for child buffers.
|
||||
* @return instance
|
||||
*/
|
||||
INativeBuffer getBuffer(ByteBuffer samples, long timestamp);
|
||||
|
||||
/**
|
||||
* Sets the samples per millisecond rate based on the current sample rate.
|
||||
*
|
||||
* @param samplesPerMillisecond to calculate timestamp offset for child buffers.
|
||||
*/
|
||||
void setSamplesPerMillisecond(float samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@@ -21,14 +21,13 @@ package io.github.dsheirer.buffer;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Native buffer sample array wrapper class that provides access to a stream of either interleaved or
|
||||
* non-interleaved complex sample buffers converted from the raw byte sample array.
|
||||
*/
|
||||
public class SignedByteNativeBuffer implements INativeBuffer
|
||||
public class SignedByteNativeBuffer extends AbstractNativeBuffer
|
||||
{
|
||||
private static final int FRAGMENT_SIZE = 2048;
|
||||
private final static float[] LOOKUP_VALUES;
|
||||
@@ -47,7 +46,6 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
private byte[] mSamples;
|
||||
private long mTimestamp;
|
||||
private float mIAverageDc;
|
||||
private float mQAverageDc;
|
||||
|
||||
@@ -57,9 +55,12 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
* @param timestamp of the samples
|
||||
* @param iAverageDc of the sample stream
|
||||
* @param qAverageDc of the sample stream
|
||||
* @param samplesPerMillisecond to calculate sub-buffer timestamps
|
||||
*/
|
||||
public SignedByteNativeBuffer(byte[] samples, long timestamp, float iAverageDc, float qAverageDc)
|
||||
public SignedByteNativeBuffer(byte[] samples, long timestamp, float iAverageDc, float qAverageDc, float samplesPerMillisecond)
|
||||
{
|
||||
super(timestamp, samplesPerMillisecond);
|
||||
|
||||
//Ensure we're an even multiple of the fragment size. Typically, this will be 64k or 128k
|
||||
if(samples.length % FRAGMENT_SIZE != 0)
|
||||
{
|
||||
@@ -67,17 +68,10 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mSamples = samples;
|
||||
mTimestamp = timestamp;
|
||||
mIAverageDc = iAverageDc;
|
||||
mQAverageDc = qAverageDc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sampleCount()
|
||||
{
|
||||
@@ -112,6 +106,8 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
@Override
|
||||
public ComplexSamples next()
|
||||
{
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
float[] i = new float[FRAGMENT_SIZE];
|
||||
float[] q = new float[FRAGMENT_SIZE];
|
||||
int samplesOffset = mSamplesPointer;
|
||||
@@ -123,7 +119,7 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
}
|
||||
|
||||
mSamplesPointer = samplesOffset;
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +139,8 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
@Override
|
||||
public InterleavedComplexSamples next()
|
||||
{
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
float[] converted = new float[FRAGMENT_SIZE * 2];
|
||||
|
||||
int samplesOffset = mSamplesPointer;
|
||||
@@ -155,7 +153,7 @@ public class SignedByteNativeBuffer implements INativeBuffer
|
||||
|
||||
mSamplesPointer = samplesOffset;
|
||||
|
||||
return new InterleavedComplexSamples(converted, mTimestamp);
|
||||
return new InterleavedComplexSamples(converted, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Implements a factory for creating SignedByteNativeBuffer instances
|
||||
*/
|
||||
public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
||||
public class SignedByteNativeBufferFactory extends AbstractNativeBufferFactory
|
||||
{
|
||||
/**
|
||||
* DC removal calculations will run once a minute
|
||||
@@ -78,7 +78,7 @@ public class SignedByteNativeBufferFactory implements INativeBufferFactory
|
||||
calculateDc(copy);
|
||||
}
|
||||
|
||||
return new SignedByteNativeBuffer(copy, timestamp, mIAverageDc, mQAverageDc);
|
||||
return new SignedByteNativeBuffer(copy, timestamp, mIAverageDc, mQAverageDc, getSamplesPerMillisecond());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.hilbert.HilbertTransform;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
@@ -42,8 +41,9 @@ public abstract class AirspyBufferIterator<T> implements Iterator<T>
|
||||
protected float[] mQBuffer = new float[FRAGMENT_SIZE + Q_OVERLAP];
|
||||
protected short[] mSamples;
|
||||
protected int mSamplesPointer = 0;
|
||||
protected long mTimestamp;
|
||||
protected float mAverageDc;
|
||||
private long mTimestamp;
|
||||
private float mSamplesPerMillisecond;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
@@ -52,8 +52,10 @@ public abstract class AirspyBufferIterator<T> implements Iterator<T>
|
||||
* @param residualQ samples from previous buffer
|
||||
* @param averageDc as measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIterator(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIterator(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp,
|
||||
float samplesPerMillisecond)
|
||||
{
|
||||
if(residualI.length != I_OVERLAP || residualQ.length != Q_OVERLAP)
|
||||
{
|
||||
@@ -73,6 +75,7 @@ public abstract class AirspyBufferIterator<T> implements Iterator<T>
|
||||
mAverageDc = averageDc;
|
||||
mSamples = samples;
|
||||
mTimestamp = timestamp;
|
||||
mSamplesPerMillisecond = samplesPerMillisecond;
|
||||
|
||||
//Transfer and scale the residual I & Q samples from the previous buffer
|
||||
for(int i = 0; i < residualI.length; i++)
|
||||
@@ -86,6 +89,17 @@ public abstract class AirspyBufferIterator<T> implements Iterator<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the timestamp for a samples buffer fragment based on where it is extracted from relative to the
|
||||
* native buffer starting timestamp.
|
||||
* @param samplesPointer for the start of the fragment. Note: this value will be divided by 2 to account for I/Q sample pairs.
|
||||
* @return timestamp adjusted to the fragment or sub-buffer start sample.
|
||||
*/
|
||||
protected long getFragmentTimestamp(int samplesPointer)
|
||||
{
|
||||
return mTimestamp + (long)(samplesPointer / 2 / mSamplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@@ -36,10 +35,11 @@ public class AirspyBufferIteratorScalar extends AirspyBufferIterator<ComplexSamp
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIteratorScalar(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIteratorScalar(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,6 +50,8 @@ public class AirspyBufferIteratorScalar extends AirspyBufferIterator<ComplexSamp
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
int offset = mSamplesPointer;
|
||||
|
||||
for(int x = 0; x < FRAGMENT_SIZE; x++)
|
||||
@@ -91,6 +93,6 @@ public class AirspyBufferIteratorScalar extends AirspyBufferIterator<ComplexSamp
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Vector SIMD implementation for non-packed Airspy native buffers
|
||||
*/
|
||||
@@ -41,10 +40,12 @@ public class AirspyBufferIteratorVector128Bits extends AirspyBufferIterator<Comp
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIteratorVector128Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIteratorVector128Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +56,7 @@ public class AirspyBufferIteratorVector128Bits extends AirspyBufferIterator<Comp
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -121,6 +123,6 @@ public class AirspyBufferIteratorVector128Bits extends AirspyBufferIterator<Comp
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Vector SIMD implementation for non-packed Airspy native buffers
|
||||
*/
|
||||
@@ -41,10 +40,12 @@ public class AirspyBufferIteratorVector256Bits extends AirspyBufferIterator<Comp
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIteratorVector256Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIteratorVector256Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +56,7 @@ public class AirspyBufferIteratorVector256Bits extends AirspyBufferIterator<Comp
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -115,6 +117,6 @@ public class AirspyBufferIteratorVector256Bits extends AirspyBufferIterator<Comp
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Vector SIMD implementation for non-packed Airspy native buffers
|
||||
*/
|
||||
@@ -42,10 +41,12 @@ public class AirspyBufferIteratorVector512Bits extends AirspyBufferIterator<Comp
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIteratorVector512Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIteratorVector512Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
//Arrange the last 8 taps of the filter into the higher indices of an array to align for SIMD
|
||||
mFilterPart2 = new float[16];
|
||||
System.arraycopy(COEFFICIENTS, 16, mFilterPart2, 8, 8);
|
||||
@@ -59,6 +60,8 @@ public class AirspyBufferIteratorVector512Bits extends AirspyBufferIterator<Comp
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -117,6 +120,6 @@ public class AirspyBufferIteratorVector512Bits extends AirspyBufferIterator<Comp
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import java.util.Arrays;
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.VectorOperators;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Vector SIMD implementation for non-packed Airspy native buffers
|
||||
*/
|
||||
@@ -41,10 +40,12 @@ public class AirspyBufferIteratorVector64Bits extends AirspyBufferIterator<Compl
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyBufferIteratorVector64Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc, long timestamp)
|
||||
public AirspyBufferIteratorVector64Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +56,8 @@ public class AirspyBufferIteratorVector64Bits extends AirspyBufferIterator<Compl
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -133,6 +136,6 @@ public class AirspyBufferIteratorVector64Bits extends AirspyBufferIterator<Compl
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new ComplexSamples(i, q);
|
||||
return new ComplexSamples(i, q, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,12 @@ public class AirspyInterleavedBufferIteratorScalar extends AirspyBufferIterator<
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyInterleavedBufferIteratorScalar(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp)
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,6 +50,7 @@ public class AirspyInterleavedBufferIteratorScalar extends AirspyBufferIterator<
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
|
||||
for(int x = 0; x < FRAGMENT_SIZE; x++)
|
||||
@@ -89,6 +91,6 @@ public class AirspyInterleavedBufferIteratorScalar extends AirspyBufferIterator<
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new InterleavedComplexSamples(samples, mTimestamp);
|
||||
return new InterleavedComplexSamples(samples, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ public class AirspyInterleavedBufferIteratorVector128Bits extends AirspyBufferIt
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyInterleavedBufferIteratorVector128Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp)
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,6 +55,7 @@ public class AirspyInterleavedBufferIteratorVector128Bits extends AirspyBufferIt
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -118,6 +120,6 @@ public class AirspyInterleavedBufferIteratorVector128Bits extends AirspyBufferIt
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new InterleavedComplexSamples(samples, mTimestamp);
|
||||
return new InterleavedComplexSamples(samples, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ public class AirspyInterleavedBufferIteratorVector256Bits extends AirspyBufferIt
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyInterleavedBufferIteratorVector256Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp)
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,6 +55,7 @@ public class AirspyInterleavedBufferIteratorVector256Bits extends AirspyBufferIt
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -112,6 +114,6 @@ public class AirspyInterleavedBufferIteratorVector256Bits extends AirspyBufferIt
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new InterleavedComplexSamples(samples, mTimestamp);
|
||||
return new InterleavedComplexSamples(samples, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,12 @@ public class AirspyInterleavedBufferIteratorVector512Bits extends AirspyBufferIt
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyInterleavedBufferIteratorVector512Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp)
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
|
||||
//Arrange the last 8 taps of the filter into the higher indices of an array to align for SIMD
|
||||
mFilterPart2 = new float[16];
|
||||
@@ -59,6 +60,7 @@ public class AirspyInterleavedBufferIteratorVector512Bits extends AirspyBufferIt
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -115,6 +117,6 @@ public class AirspyInterleavedBufferIteratorVector512Bits extends AirspyBufferIt
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new InterleavedComplexSamples(samples, mTimestamp);
|
||||
return new InterleavedComplexSamples(samples, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ public class AirspyInterleavedBufferIteratorVector64Bits extends AirspyBufferIte
|
||||
* @param residualQ samples from last buffer
|
||||
* @param averageDc measured
|
||||
* @param timestamp of the buffer
|
||||
* @param samplesPerMillisecond to calculate sub-buffer fragment timestamps
|
||||
*/
|
||||
public AirspyInterleavedBufferIteratorVector64Bits(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp)
|
||||
long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(samples, residualI, residualQ, averageDc, timestamp);
|
||||
super(samples, residualI, residualQ, averageDc, timestamp, samplesPerMillisecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,6 +55,7 @@ public class AirspyInterleavedBufferIteratorVector64Bits extends AirspyBufferIte
|
||||
throw new IllegalStateException("End of buffer exceeded");
|
||||
}
|
||||
|
||||
long timestamp = getFragmentTimestamp(mSamplesPointer);
|
||||
int offset = mSamplesPointer;
|
||||
int fragmentPointer = 0;
|
||||
float[] scaledSamples = new float[VECTOR_SPECIES.length()];
|
||||
@@ -130,6 +132,6 @@ public class AirspyInterleavedBufferIteratorVector64Bits extends AirspyBufferIte
|
||||
System.arraycopy(mIBuffer, FRAGMENT_SIZE, mIBuffer, 0, I_OVERLAP);
|
||||
System.arraycopy(mQBuffer, FRAGMENT_SIZE, mQBuffer, 0, Q_OVERLAP);
|
||||
|
||||
return new InterleavedComplexSamples(samples, mTimestamp);
|
||||
return new InterleavedComplexSamples(samples, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,23 +19,21 @@
|
||||
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.buffer.INativeBuffer;
|
||||
import io.github.dsheirer.buffer.AbstractNativeBuffer;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||
import io.github.dsheirer.vector.calibrate.Implementation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Native buffer scalar implementation for Airspy non-packed samples.
|
||||
*/
|
||||
public class AirspyNativeBuffer implements INativeBuffer
|
||||
public class AirspyNativeBuffer extends AbstractNativeBuffer
|
||||
{
|
||||
private short[] mSamples;
|
||||
private short[] mResidualI;
|
||||
private short[] mResidualQ;
|
||||
private float mAverageDc;
|
||||
private long mTimestamp;
|
||||
private Implementation mInterleavedImplementation;
|
||||
private Implementation mNonInterleavedImplementation;
|
||||
|
||||
@@ -48,11 +46,14 @@ public class AirspyNativeBuffer implements INativeBuffer
|
||||
* @param timestamp of the buffer
|
||||
* @param interleavedImplementation optimal, scalar vs vector SIMD
|
||||
* @param nonInterleavedImplementation optimal, scalar vs vector SIMD
|
||||
* @param samplesPerMillisecond used to calculate sub-buffer fragment timestamp offsets from the start of this buffer.
|
||||
*/
|
||||
public AirspyNativeBuffer(short[] samples, short[] residualI, short[] residualQ, float averageDc,
|
||||
long timestamp, Implementation interleavedImplementation,
|
||||
Implementation nonInterleavedImplementation)
|
||||
Implementation nonInterleavedImplementation, float samplesPerMillisecond)
|
||||
{
|
||||
super(timestamp, samplesPerMillisecond);
|
||||
|
||||
//Ensure we're an even multiple of the fragment size. Typically, this will be 64k or 128k
|
||||
if(samples.length % AirspyBufferIterator.FRAGMENT_SIZE != 0)
|
||||
{
|
||||
@@ -64,7 +65,6 @@ public class AirspyNativeBuffer implements INativeBuffer
|
||||
mResidualI = residualI;
|
||||
mResidualQ = residualQ;
|
||||
mAverageDc = averageDc;
|
||||
mTimestamp = timestamp;
|
||||
mInterleavedImplementation = interleavedImplementation;
|
||||
mNonInterleavedImplementation = nonInterleavedImplementation;
|
||||
}
|
||||
@@ -75,22 +75,16 @@ public class AirspyNativeBuffer implements INativeBuffer
|
||||
return mSamples.length / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ComplexSamples> iterator()
|
||||
{
|
||||
return switch(mInterleavedImplementation)
|
||||
{
|
||||
case VECTOR_SIMD_512 -> new AirspyBufferIteratorVector512Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_256-> new AirspyBufferIteratorVector256Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_128-> new AirspyBufferIteratorVector128Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_64 ->new AirspyBufferIteratorVector64Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
default -> new AirspyBufferIteratorScalar(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_512 -> new AirspyBufferIteratorVector512Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_256-> new AirspyBufferIteratorVector256Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_128-> new AirspyBufferIteratorVector128Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_64 ->new AirspyBufferIteratorVector64Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
default -> new AirspyBufferIteratorScalar(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -99,11 +93,11 @@ public class AirspyNativeBuffer implements INativeBuffer
|
||||
{
|
||||
return switch(mInterleavedImplementation)
|
||||
{
|
||||
case VECTOR_SIMD_512 -> new AirspyInterleavedBufferIteratorVector512Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_256-> new AirspyInterleavedBufferIteratorVector256Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_128-> new AirspyInterleavedBufferIteratorVector128Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_64 ->new AirspyInterleavedBufferIteratorVector64Bits(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
default -> new AirspyInterleavedBufferIteratorScalar(mSamples, mResidualI, mResidualQ, mAverageDc, mTimestamp);
|
||||
case VECTOR_SIMD_512 -> new AirspyInterleavedBufferIteratorVector512Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_256-> new AirspyInterleavedBufferIteratorVector256Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_128-> new AirspyInterleavedBufferIteratorVector128Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
case VECTOR_SIMD_64 ->new AirspyInterleavedBufferIteratorVector64Bits(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
default -> new AirspyInterleavedBufferIteratorScalar(mSamples, mResidualI, mResidualQ, mAverageDc, getTimestamp(), getSamplesPerMillisecond());
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -19,19 +19,18 @@
|
||||
|
||||
package io.github.dsheirer.buffer.airspy;
|
||||
|
||||
import io.github.dsheirer.buffer.AbstractNativeBufferFactory;
|
||||
import io.github.dsheirer.buffer.INativeBuffer;
|
||||
import io.github.dsheirer.buffer.INativeBufferFactory;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationManager;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationType;
|
||||
import io.github.dsheirer.vector.calibrate.Implementation;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Implements a factory for creating SignedByteNativeBuffer instances
|
||||
*/
|
||||
public class AirspyNativeBufferFactory implements INativeBufferFactory
|
||||
public class AirspyNativeBufferFactory extends AbstractNativeBufferFactory
|
||||
{
|
||||
private boolean mSamplePacking = false;
|
||||
private short[] mResidualI = new short[AirspyBufferIterator.I_OVERLAP];
|
||||
@@ -106,7 +105,7 @@ public class AirspyNativeBufferFactory implements INativeBufferFactory
|
||||
INativeBuffer nativeBuffer = new AirspyNativeBuffer(samples,
|
||||
Arrays.copyOf(mResidualI, mResidualI.length),
|
||||
Arrays.copyOf(mResidualQ, mResidualQ.length), mConverter.getAverageDc(), timestamp,
|
||||
mInterleavedIteratorImplementation, mNonInterleavedIteratorImplementation);
|
||||
mInterleavedIteratorImplementation, mNonInterleavedIteratorImplementation, getSamplesPerMillisecond());
|
||||
|
||||
extractResidual(samples);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user