discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] USRP Audio Rate versus Sample Rate of Soundcard


From: Michael Dickens
Subject: Re: [Discuss-gnuradio] USRP Audio Rate versus Sample Rate of Soundcard
Date: Wed, 13 Feb 2008 11:08:11 -0500

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, address@hidden 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 = (2*3*5*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":

0) 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.

1) 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.

2) 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.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]