Omer - You should really read through a few “how to do DSP” books - as
well as review the GNU Radio code for filtering ( gnuradio-core/src/
lib/filter ) - since all of those books I’ve ever heard of cover
changes in sampling rate. That said, here’s some info that will
hopefully be useful to the list. These techniques have worked for me
for other sample rate changes, though I hope I remembered them
correctly here … someone please correct me if I didn’t. - MLD
On Feb 12, 2008, at 9:33 PM, [email protected] wrote:
self.fg = gr.flow_graph()
src = audio.source(44100, options.audio_input)
fmtx = blks.wfm_tx(self.fg, self.audio_rate,
self.usrp_rate)
self.fg.connect(src, fmtx, gain, self.u)"
The input sample rate must be 44100 = (235*7)^2
The output sample rate must be any one of 128M/[4:4:512].
Stream must be resampled in software somewhere along the DSP chain.
3 possible solutions or approximations … listed roughly in order of
“goodness” or “precision”:
- rational resampler: There’s a resampling block that can do up then
down resampling by integer values. You’ll need to find:
hw_interp=[4:4:512];
usb_tx_rate =128e+6./hw_interp;
% find just the integer usb_rate’s:
ff=find(abs(usb_tx_rate - round(usb_tx_rate)) < eps);
X=lcm(44100*ones(size(ff)), usb_tx_rate(ff));
[Y,ndx]=min(X);
sw_interp_up=Y / 44100
sw_interp_down=Y / usb_tx_rate(ff(ndx))
hw_interp=hw_interp(ff(ndx))
usb_tx_rate=usb_tx_rate(ff(ndx))
From the above script, it looks like:
hw_interp = 512
usb_tx_rate = 250000
sw_interp_up = 2500
sw_interp_down = 441
I have no idea if these parameters will work with the rational
resampler block, but you can try them and see. I have no idea what
the CPU load of this block will be, but if you are running on an Intel
CPU with SSE then that will help reduce the load.
- fractional resampler: Provides samples between the inputs.
Probably best to keep the sample rates at a minimum for filtering
purposes:
hw_interp=512
usb_tx_rate=128e+6 / hw_interp
sw_interp= usb_tx_rate / 44100
which results in a fractional interpolation rate of sw_interp =
5.6689. I think the output samples will be the MMSE estimate to the
nearest 32nd of a time-slot to the actual sample - which is hopefully
good enough. I have no idea what the CPU load of this block will be,
but if you are running on an Intel CPU with SSE then that will help
reduce the load.
- Get “close enough” … note that because the sample rates are not
exact, there will be an occasional overflow or underrun. in my
experience, these have no real impact except an audio glitch.
hw_interp=[4:4:512];
usb_tx_rate =128e+6./hw_interp;
X= usb_tx_rate./44100;
[Y,ndx]=min(abs(X-round(X)));
sw_interp=round(X(ndx))
hw_interp=hw_interp(ndx)
usb_tx_rate=usb_tx_rate(ndx)
fg_rate=usb_tx_rate/sw_interp
then use the resulting ‘sw_interp’ in a software up-sampling block,
and ‘hw_interp’ for the USRP sink block.
Running this through MATLAB, I get:
sw_interp = 6
hw_interp = 484
usb_tx_rate = 264462.81
fg_rate = 44077.135
The output signal will be off by a little bit, but maybe it would be
close enough. For integer rates:
hw_interp=[4:4:512];
usb_tx_rate =128e+6./hw_interp;
% find just the integer usb_rate’s:
ff=find(abs(usb_tx_rate - round(usb_tx_rate)) < eps);
X=usb_tx_rate(ff)./44100;
[Y,ndx]=min(abs(X-round(X)));
sw_interp=round(X(ndx))
hw_interp=hw_interp(ndx)
usb_tx_rate=usb_tx_rate(ff(ndx))
fg_rate=usb_tx_rate/sw_interp
and I get:
sw_interp = 29
hw_interp = 36
usb_tx_rate = 1280000
fg_rate = 44138
Again, the output signal will be off by a little bit, but maybe it
would be close enough.