I'd like to pull a narrowband signal out of ADC samples, where the ADC rate is much higher than the bandwidth/central frequency of the narrowband signal. I'd like to feed the narrowband signal into a software package that want I/Q samples, so I'd like to know if a code snippet is doing the right thing. There are lots of descriptions online, which seem to be ambiguous about factors of 2, and I've so far failed at finding a code example.
Let's say the ADC operates at sampling frequency $f_{samp}$, and the narrowband signal has central frequency and bandwidth $f_0$ and $bw$. I think what I'm supposed to do is take my ADC samples, multiply by cos/sin($2\pi f_0 t$), then lowpass/downsample that to get I/Q. What exactly does that lowpass/downsampling look like, though? I would have naively expected to set the output sample frequency to be the Nyquist rate for the desired bandwidth for both I and Q. But... that just seems crazy? I can't imagine people would carry around two Nyquist-sampled timestreams for one signal, so I have to be missing something. Since nothing is as concrete as code, here's a snippet (ignoring edge effects, windowing, etc.) that does what I think I've read but which I firmly believe must be wrong. Any suggestions on what it should actually look like would be most appreciated!
import numpy as np
def adc2iq(samples,f_samp,f0,bw):
#Convert real ADC samples taken at sampling frequency f_samp to I/Q
#data with full bandwidth bw centered at f0
n=len(samples)
#make vectors of sin/cos at frequency f0
t=np.arange(n)/f_samp
mycos=np.cos(t*f0*2*np.pi)
mysin=np.sin(t*f0*2*np.pi)
#take the Fourier transform of the samples times the sin/cos vectors
ift=np.fft.rfft(samples*mycos)
qft=np.fft.rfft(samples*mysin)
#low-pass/downsample by inverse FFTing a suitable number of samples
keep_frac=2*bw/f_samp #is this right?
kmax=np.int(keep_frac*len(ift))
i=np.fft.irfft(ift[:kmax])
q=np.fft.irfft(qft[:kmax])
return i,q
(In case anyone is curious, my motivation is trying to process GPS signals inside 550 MHz worth of L-band radio astronomy data, and the GPS software seems happiest with I/Q samples)