discuss-gnuradio
[Top][All Lists]
Advanced

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

[Discuss-gnuradio] bug in wfm_rcv_pll and fix, who has stereo FM specs


From: Martin Dvh
Subject: [Discuss-gnuradio] bug in wfm_rcv_pll and fix, who has stereo FM specs/info and noise and gain issues
Date: Sun, 17 Jun 2007 17:14:13 +0200
User-agent: Debian Thunderbird 1.0.2 (X11/20070113)

Hi,
I found a nasty bug in the wfm_rcv_pll.py code.

The pilot tone pll should return the recovered carrier,
For this you should use gr.pll_refout_cc, not gr.pll_carriertracking_cc.
pll_carriertracking returns the input transformed to baseband using the 
recovered carrier.
pll_refout returns the recovered carrier.

With the fixed code I now actually get stereo.
(Before you would get a kind of attenuated, distorted, spectrum inverted stereo)

I tested it with a stereo-coder I wrote in gnuradio, and now I seem to actually 
get stereo seperation.
(stereo modulater is attached)

But now I do get a lot of noise when decoding stereo.

I also don't quite understand why double side band suppressed carrier 
Left-Right audio is attenuated and needs a factor 20 for gain.
(It seems to be correct or at least close)

The code comments say 10 dB
The actual code uses a factor 20 which corresponds to 20 *log10(20)= 26 dB.
This 26 dB seems to be quite accurate, but where is this number based on?

can you give me a link to more info or the stereo FM specs on this.

            # Pick off the double side band suppressed carrier Left-Right 
audio. It is attenuated 10 dB so apply 10 dB gain

            stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0,


Greetings,
Martin

fix for wrong pll is below:
--- gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py   2007-06-11 
18:12:55.000000000 +0200
+++ gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll_fixed.py     
2007-06-17 08:07:43.000000000 +0200
@@ -131,8 +131,8 @@
             max_freq = -2.0*math.pi*18990/audio_rate;
             min_freq = -2.0*math.pi*19010/audio_rate;

-            self.stereo_carrier_pll_recovery = 
gr.pll_carriertracking_cc(alpha,beta,max_freq,min_freq);
-            self.stereo_carrier_pll_recovery.squelch_enable(False);
+            self.stereo_carrier_pll_recovery = 
gr.pll_refout_cc(alpha,beta,max_freq,min_freq);
+            #self.stereo_carrier_pll_recovery.squelch_enable(False) 
#pll_refout does not have squelch yet, so disabled for now


             # set up mixer (multiplier) to get the L-R signal at baseband


import math
from gnuradio import gr, optfir
from gnuradio.blksimpl.fm_emph import fm_preemph

class wfm_tx_stereo(gr.hier_block):
    def __init__(self, fg, input_rate, 
freq_tone_left=1.0e3,level_tone_left=1.0,freq_tone_right=3.0e3, 
level_tone_right=1.0,tau=75e-6, max_dev=75e3):
        """
        Wide Band FM Stereo test Transmitter.

        Generates a 1kHz tone on left and 3 kHz tone on right channel
        and produces a single stereo FM modulated complex baseband output.
        Stereo seperation can be tested by setting one of the tone_levels to 
zero

        @param fg: flow graph
        @param input_rate: sample rate of audio stream and output_stream  >= 55k
        @type input_rate: integer
        @param freq_tone_left: frequency of test tone on left channel in the 
range [0.0,15.0e3] (0 to 15 kHz) 
        @type freq_tone_left: float
        @param level_tone_left: level of test tone on left channel in the range 
[0.0, 1.0]
        @type level_tone_left: float
        @param freq_tone_right:frequency of test tone on right channel in the 
range [0,15e3] (0 to 15 kHz) 
        @type freq_tone_right: float
        @param level_tone_right: level of test tone on right channel in the 
range [0.0, 1.0]
        @type freq_tone_right: float
        @param tau: preemphasis time constant (default 75e-6) This is not used 
yet (not implemented yet)
        @type tau: float
        @param max_dev: maximum deviation in Hz (default 75e3)
        @type max_dev: float

        """

        self.input_rate=input_rate
        self.interpolation=1 #must be 1 for now
        self.mod_rate=self.input_rate*self.interpolation
        
        #do_interp = self.input_rate != self.mod_rate
        #
        #if do_interp:
        #    interp_taps = optfir.low_pass (interpolation,   # gain
        #                                   self.mod_rate,       # Fs
        #                                   16000,           # passband cutoff
        #                                   18000,           # stopband cutoff
        #                                   0.1,            # passband ripple dB
        #                                   60)              # stopband atten dB
        #
        #    print "len(interp_taps) =", len(interp_taps)
        #    self.interpolator = gr.interp_fir_filter_fcc (interpolation, 
interp_taps)
        #if do_interp:
        #  self.input_fc=self.interpolator
        #else:
        #  self.input_fc=gr.float_to_complex()


        #self.preemph = fm_preemph (fg, self.mod_rate, tau=tau) 
        #fm_preemph cannot be used yet because the fm_preemph block is not 
implemented yet, it is just a stub
        
        k = 2 * math.pi * max_dev / self.mod_rate
        self.modulator = gr.frequency_modulator_fc (k)

        self.pilot_c=gr.sig_source_c(self.mod_rate,gr.GR_SIN_WAVE 
,19.0e3,1.0,0.0)
        self.pilotx2_cc=gr.multiply_cc()
        self.pilot_gain_cc=gr.multiply_const_cc(1.0/20.0)#/40.0)
        self.lplusr_ff=gr.add_ff()
        self.lplusr_gain_ff=gr.multiply_const_ff(1.0/10.0) #1.0
        self.lplusr_fc=gr.float_to_complex()
        self.lminr_ff=gr.sub_ff()
        self.lminr_gain_ff=gr.multiply_const_ff(1.0/10.0)
        self.lminr_fc=gr.float_to_complex()

        self.input_l_f=gr.sig_source_f(self.mod_rate,gr.GR_SIN_WAVE 
,freq_tone_left,0.5*level_tone_left,0.0)
        self.input_r_f=gr.sig_source_f(self.mod_rate,gr.GR_SIN_WAVE 
,freq_tone_right,0.5*level_tone_right,0.0)

        self.dsbsc_gen_cc=gr.multiply_cc()
        self.baseband_cc=gr.add_cc()
        self.baseband_cf=gr.complex_to_float()
        fg.connect(self.input_l_f,(self.lplusr_ff,0))
        fg.connect(self.input_r_f,(self.lplusr_ff,1))
        fg.connect(self.input_l_f,(self.lminr_ff,0))
        fg.connect(self.input_r_f,(self.lminr_ff,1))

        
fg.connect(self.lminr_ff,self.lminr_gain_ff,self.lminr_fc,(self.dsbsc_gen_cc,0))
        fg.connect(self.pilot_c,(self.pilotx2_cc,0))
        fg.connect(self.pilot_c,(self.pilotx2_cc,1))
        fg.connect(self.pilotx2_cc,(self.dsbsc_gen_cc,1))

        fg.connect(self.dsbsc_gen_cc,(self.baseband_cc,0))
        fg.connect(self.pilot_c,self.pilot_gain_cc,(self.baseband_cc,1))
        nullsink=gr.null_sink(gr.sizeof_float)
        fg.connect(self.lplusr_ff,nullsink)
        
fg.connect(self.lplusr_ff,self.lplusr_gain_ff,self.lplusr_fc,(self.baseband_cc,2))
 
        fg.connect(self.baseband_cc,self.baseband_cf)

        fg.connect(self.baseband_cf, self.modulator)  
        gr.hier_block.__init__(self, fg, None, self.modulator)

reply via email to

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