-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove the resampler. #95
Conversation
mink = st->samperr - 10; | ||
maxk = st->samperr + 10; | ||
mink = FFTCP / 2 - 25; | ||
maxk = FFTCP / 2 + 25; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to widen the search range here to account for ppm error. Each invocation of acquire_process
processes 64 * 2160 samples, so 100 ppm error causes a 14-sample offset between invocations.
float phase, slope; | ||
float complex sum; | ||
|
||
sum = 0; | ||
for (int r = 0; r < BLKSZ; r++) | ||
sum += buf[ref * BLKSZ + r] * buf[ref * BLKSZ + r]; | ||
phase = cargf(sum) * 0.5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method of calculating the phase only works when the slope is very small. Error in the sampling frequency increases the slope, so I had to change it to take the slope into account.
sum = 0; | ||
for (int r = 0; r < BLKSZ; r++) | ||
sum += buf[ref * BLKSZ + r] * buf[ref * BLKSZ + r] * cexpf(-I * 2 * slope * r); | ||
phase = cargf(sum) * 0.5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phase calculation now takes place after the slope is calculated, so that the slope can be subtracted out.
I merged calc_phase
into adjust_ref
because this method needs to use the averaged slope. (I tried with the raw slope, but that reduced the receiver's weak-signal performance.)
The changes to acquire.c are simpler to review with whitespace changes ignored: https://github.com/theori-io/nrsc5/pull/95/files?w=1 |
@classicjazz @pclov3r You may be interested in testing this out. It should reduce the acquisition time by about 3 seconds. @mrbubble62 I expect this change will improve ARM performance significantly. |
@argilo This is a great change! When the gain is set or if you set it manually around 6 seconds until actual audio playback. |
Currently nrsc5 uses an arbitrary resampler to maintain time synchronization. This approach has some significant drawbacks:
resamp_q15_execute
.acquire_process
spends more than three seconds estimating the resampling rate before it starts passing samples through tosync_push
.The resampler can be eliminated simply by modifying
acquire_process
to skip or re-use samples as necessary to maintain synchronization. It already carries over one symbol's worth of samples from one invocation to the next, so I modified it to carry over anywhere from 0.5 to 1.5 symbols depending on the value ofsamperr
. It chooses the number of samples so as to target asamperr
value ofFFTCP / 2
on the following invocation.A couple other small changes were necessary to make this work with RTL-SDRs that have ±100 ppm crystals. I'll note those in the code.
I tested this by changing the sample rate in main.c to
1488375 - 200
and1488375 + 200
(thus simulating an error of 134 ppm) and using a couple old non-TCXO RTL-SDR's I had lying around. I also processed about 15 recordings I had made of stations at various signal strengths, and found that the reported MER values were comparable before & after the change.