[WIP] The 2 channel synthesizer appears to be working after restructuring.

Check-point commit.  I'm going to optimize the code so that it can
leverage SIMD instructions.
This commit is contained in:
Denny
2018-05-06 07:37:24 -04:00
parent 488b2e02ce
commit cbc228d798
3 changed files with 51 additions and 33 deletions

View File

@@ -15,11 +15,8 @@
******************************************************************************/
package io.github.dsheirer.dsp.filter.channelizer;
import io.github.dsheirer.buffer.RealCircularBuffer;
import io.github.dsheirer.dsp.filter.FilterFactory;
import io.github.dsheirer.dsp.filter.Window;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter;
import io.github.dsheirer.dsp.mixer.IOscillator;
import io.github.dsheirer.dsp.mixer.LowPhaseNoiseOscillator;
import org.jtransforms.fft.FloatFFT_1D;
@@ -32,11 +29,15 @@ public class TwoChannelSynthesizerM2
{
private final static Logger mLog = LoggerFactory.getLogger(TwoChannelSynthesizerM2.class);
private ComplexFIRFilter mFilter1;
private ComplexFIRFilter mFilter2;
private float[] mData1i;
private float[] mData1q;
private float[] mData2i;
private float[] mData2q;
private float[] mFilter1;
private float[] mFilter2;
private float mAccumulator;
private FloatFFT_1D mFFT = new FloatFFT_1D(2);
private boolean mFlag = false;
private boolean mFlag = true;
/**
* Polyphase synthesizer for mixing two M2 oversampled channels into a composite channel using
@@ -63,24 +64,26 @@ public class TwoChannelSynthesizerM2
{
int length = (filter.length / 2) + (filter.length % 2);
float[] filter1 = new float[length];
float[] filter2 = new float[length];
mFilter1 = new float[length];
mFilter2 = new float[length];
mData1i = new float[length];
mData1q = new float[length];
mData2i = new float[length];
mData2q = new float[length];
for(int x = 0; x < filter.length; x += 2)
{
//Load the filter in reverse to facilitate convolution
int index = length - (x / 2) - 1;
filter1[index] = filter[x];
mFilter1[index] = filter[x];
if(x + 1 < filter.length)
{
filter2[index] = filter[x + 1];
mFilter2[index] = filter[x + 1];
}
}
mFilter1 = new ComplexFIRFilter(filter1, 1.0f);
mFilter2 = new ComplexFIRFilter(filter2, 1.0f);
}
/**
@@ -98,6 +101,7 @@ public class TwoChannelSynthesizerM2
throw new IllegalArgumentException("Channel 1 and 2 array length must be equal");
}
//TODO: make this a reusable buffer
float[] output = new float[channel1.length];
float[] buffer = new float[4];
@@ -111,15 +115,29 @@ public class TwoChannelSynthesizerM2
mFFT.complexInverse(buffer, true);
System.arraycopy(mData1i, 0, mData1i, 1, mData1i.length - 1);
System.arraycopy(mData1q, 0, mData1q, 1, mData1q.length - 1);
System.arraycopy(mData2i, 0, mData2i, 1, mData2i.length - 1);
System.arraycopy(mData2q, 0, mData2q, 1, mData2q.length - 1);
mData1i[0] = buffer[0];
mData1q[0] = buffer[1];
mData2i[0] = buffer[2];
mData2q[0] = buffer[3];
if(mFlag)
{
output[x] = mFilter1.filterInphase(buffer[0]) + mFilter2.filterInphase(buffer[2]);
output[x + 1] = mFilter1.filterQuadrature(buffer[1]) + mFilter2.filterQuadrature(buffer[3]);
// output[x] = filter(mFilter1, mData1i);
// output[x + 1] = filter(mFilter1, mData1q);
output[x] = filter(mFilter1, mData1i) + filter(mFilter2, mData2i);
output[x + 1] = filter(mFilter1, mData1q) + filter(mFilter2, mData2q);
}
else
{
output[x] = mFilter1.filterInphase(buffer[2]) + mFilter2.filterInphase(buffer[0]);
output[x + 1] = mFilter1.filterQuadrature(buffer[3]) + mFilter2.filterQuadrature(buffer[1]);
// output[x] = filter(mFilter1, mData2i);
// output[x + 1] = filter(mFilter1, mData2q);
output[x] = filter(mFilter1, mData2i) + filter(mFilter2, mData1i);
output[x + 1] = filter(mFilter1, mData2q) + filter(mFilter2, mData1q);
}
mFlag = !mFlag;
@@ -128,27 +146,27 @@ public class TwoChannelSynthesizerM2
return output;
}
private static float filter(float[] taps, RealCircularBuffer dataBlock)
private float filter(float[] coefficients, float[] data)
{
float accumulator = 0;
mAccumulator = 0.0f;
for(int x = 0; x < taps.length; x++)
for(int x = 0; x < coefficients.length; x++)
{
accumulator += (taps[x] * dataBlock.get(x));
mAccumulator += coefficients[x] * data[x];
}
return accumulator;
return mAccumulator;
}
public static void main(String[] args)
{
mLog.debug("Starting");
int sampleCount = 10;
int sampleCount = 30;
try
{
float[] taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 19, Window.WindowType.BLACKMAN_HARRIS_7, true);
float[] taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 8, Window.WindowType.BLACKMAN_HARRIS_7, true);
TwoChannelSynthesizerM2 synthesizer = new TwoChannelSynthesizerM2(taps);
@@ -162,7 +180,7 @@ public class TwoChannelSynthesizerM2
mLog.debug("1:" + Arrays.toString(channel1));
mLog.debug("X:" + Arrays.toString(synthesized));
}
catch(FilterDesignException fde)
catch(Exception fde)
{
mLog.error("Filter design error", fde);
}

View File

@@ -76,8 +76,8 @@ public class FilterViewer extends Application
try
{
// taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 19, Window.WindowType.BLACKMAN_HARRIS_7, true);
taps = FilterFactory.getSincFilter(25000.0, 12500.0, 2, 19, Window.WindowType.BLACKMAN_HARRIS_7, true);
taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 19, Window.WindowType.BLACKMAN_HARRIS_7, true);
// taps = FilterFactory.getSincFilter(25000.0, 12500.0, 2, 19, Window.WindowType.BLACKMAN_HARRIS_7, true);
}
catch(FilterDesignException fde)
{

View File

@@ -66,7 +66,7 @@ public class SynthesizerViewer extends JFrame
private ChannelPanel mChannel2Panel;
private ChannelControlPanel mChannel1ControlPanel;
private ChannelControlPanel mChannel2ControlPanel;
private DFTSize mMainPanelDFTSize = DFTSize.FFT32768;
private DFTSize mMainPanelDFTSize = DFTSize.FFT08192;
private DFTSize mChannelPanelDFTSize = DFTSize.FFT08192;
/**
@@ -152,7 +152,7 @@ public class SynthesizerViewer extends JFrame
{
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
mSpectrumPanel = new SpectrumPanel(settingsManager);
mSpectrumPanel.setSampleSize(22);
mSpectrumPanel.setSampleSize(16);
add(mSpectrumPanel);
mDFTProcessor.addConverter(mComplexDecibelConverter);
@@ -193,7 +193,7 @@ public class SynthesizerViewer extends JFrame
{
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill][]"));
mSpectrumPanel = new SpectrumPanel(settingsManager);
mSpectrumPanel.setSampleSize(22);
mSpectrumPanel.setSampleSize(16);
add(mSpectrumPanel, "wrap");
add(channelControlPanel);
@@ -282,7 +282,7 @@ public class SynthesizerViewer extends JFrame
{
try
{
float[] taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 19,
float[] taps = FilterFactory.getSincM2Synthesizer(12500.0, 2, 12,
Window.WindowType.BLACKMAN_HARRIS_7, true);
mSynthesizer = new TwoChannelSynthesizerM2(taps);
}
@@ -302,8 +302,8 @@ public class SynthesizerViewer extends JFrame
getChannel2ControlPanel().getOscillator().generateComplex(channel2Buffer);
float[] synthesized = mSynthesizer.process(channel1Buffer.getSamples(), channel2Buffer.getSamples());
mFS4DownConverter.mixComplex(synthesized);
ReusableComplexBuffer synthesizedBuffer = mReusableComplexBufferQueue.getBuffer(synthesized.length);
System.arraycopy(synthesized, 0, synthesizedBuffer.getSamples(), 0, synthesized.length);
channel1Buffer.incrementUserCount();
getChannel1Panel().receive(channel1Buffer);