#39 WIP - adds support for timestamped complex buffers so that decoded

messages and events can be accurately timestamped, and more importantly,
allocated traffic channels can request to be pre-loaded with buffered
samples to ensure that traffic channels don't miss any samples that
are currently missed due processing latency inherent in current buffer
sizing.  This should reduce the clipping of starting messages or voice
on the traffic channels.

Restructures processing path for tuner frequency and sample rate change
events.  The tuner now embeds these events in the sequence of buffers
that are generated immediately after the event occurs since those are
the buffers that will be impacted by the change.  Previously, the change
event would be broadcast throughout the system and would impact any
buffered/cached buffers.  This also reduces the number of source event
change listeners that have to be managed.  Note: this change is not yet
implemented in all tuners ... only in the TestTuner implementation.

Updates the polyphase channelizer to now buffer channel results and then
dispatch the buffer to the channel output processors to improve efficiency
of using float arrays versus single value complex float processing.
This commit is contained in:
Denny
2018-01-13 09:10:57 -05:00
parent d2e7f008c8
commit 05fa5c25fd
25 changed files with 962 additions and 277 deletions

View File

@@ -42,8 +42,6 @@ public class TunerSourceManager extends AbstractSourceManager
public TunerSourceManager(TunerController tunerController)
{
mTunerController = tunerController;
//Register to receive frequency and sample rate notifications
mTunerController.addListener(this);
mPolyphaseChannelManager = new PolyphaseChannelManager(tunerController);
//Register to receive channel count change notifications for rebroadcasting
@@ -166,6 +164,13 @@ public class TunerSourceManager extends AbstractSourceManager
return currentCenterFrequency;
}
long channelSetBandwidth = getChannelSetBandwidth(channels);
if(channelSetBandwidth > mTunerController.getUsableBandwidth())
{
throw new IllegalArgumentException("Channel set bandwidth is greater than tuner's available bandwidth");
}
long bestIntegralFrequency = getIntegralFrequency(channels);
//See if we can reuse the current frequency
@@ -175,32 +180,42 @@ public class TunerSourceManager extends AbstractSourceManager
return currentCenterFrequency;
}
int integralHalfChannelCount = (int)(mTunerController.getUsableHalfBandwidth() /
mPolyphaseChannelManager.getChannelBandwidth()) + 1;
//Start by placing the first channel at the minimum location within the tuner bandwidth
double usableHalfBandwidth = mTunerController.getUsableHalfBandwidth();
double startFrequency = channels.first().getMinFrequency() + usableHalfBandwidth;
int integralHalfBandwidth = (int)(integralHalfChannelCount * mPolyphaseChannelManager.getChannelBandwidth());
//Align the test frequency to the next greater integral frequency placing to place the first channel at the
// minimum extreme of the available bandwidth as a starting location
double delta = Math.abs(startFrequency - bestIntegralFrequency);
double adjustment = delta % mPolyphaseChannelManager.getChannelBandwidth();
long minimumFrequency = channels.last().getFrequency() - integralHalfBandwidth;
long testFrequency = channels.first().getFrequency() + integralHalfBandwidth;
startFrequency += adjustment;
if(isValidCenterFrequency(channels,testFrequency))
long availableTestBandwidth = mTunerController.getUsableBandwidth() - channelSetBandwidth;
int availableTestChannels = (int)(availableTestBandwidth / mPolyphaseChannelManager.getChannelBandwidth()) + 1;
if(isValidCenterFrequency(channels,(long)startFrequency))
{
return testFrequency;
return (long)startFrequency;
}
while(testFrequency >= minimumFrequency)
int currentChannel = 1;
while(currentChannel <= availableTestChannels)
{
testFrequency -= (long)mPolyphaseChannelManager.getChannelBandwidth();
long testFrequency = (long)(startFrequency - (currentChannel * mPolyphaseChannelManager.getChannelBandwidth()));
if(isValidCenterFrequency(channels, testFrequency))
{
return testFrequency;
}
currentChannel++;
}
//If we can't find an integral center frequency, choose a frequency that will fit the channels
minimumFrequency = channels.last().getFrequency() - mTunerController.getUsableHalfBandwidth();
testFrequency = channels.first().getMinFrequency() + mTunerController.getUsableHalfBandwidth();
long testFrequency = channels.first().getMinFrequency() + mTunerController.getUsableHalfBandwidth();
long minimumFrequency = testFrequency - availableTestBandwidth;
if(isValidCenterFrequency(channels,testFrequency))
{
@@ -220,6 +235,11 @@ public class TunerSourceManager extends AbstractSourceManager
throw new IllegalArgumentException("Can't calculate valid center frequency for the channel set");
}
private long getChannelSetBandwidth(SortedSet<TunerChannel> channels)
{
return channels.last().getMaxFrequency() - channels.first().getMinFrequency();
}
/**
* Indicates if the candidate center frequency is valid to ensure that all of the channels fit within the tuner's
* bandwidth and avoid any center DC spike blocked frequency region
@@ -406,12 +426,6 @@ public class TunerSourceManager extends AbstractSourceManager
//Rebroadcast this event to any registered listeners (ie tuner and tuner controller)
broadcast(sourceEvent);
break;
case NOTIFICATION_FREQUENCY_CHANGE:
mPolyphaseChannelManager.process(sourceEvent);
break;
case NOTIFICATION_SAMPLE_RATE_CHANGE:
mPolyphaseChannelManager.process(sourceEvent);
break;
default:
mLog.info("Received an unrecognized source event: " + sourceEvent);
break;