rxseger / rx_tools

rx_fm, rx_power, and rx_sdr tools for receiving data from SDRs, based on rtl_fm, rtl_power, and rtl_sdr from librtlsdr, but using the SoapySDR vendor-neutral SDR support library instead, intended to support a wider range of devices than RTL-SDR
GNU General Public License v2.0
358 stars 69 forks source link

rx_fm tuning problem with SDRplay RSP2 #75

Open farlies opened 5 years ago

farlies commented 5 years ago

I'm having difficulty tuning in (any) strong local broadcast FM station using rx_fm (rx_tools f562c5d8829bafebfb5a5204c0e89a9b5a8ddc1f) and an SDRplay RSP2. The audio is somewhat copyable, but sounds like its just off freq. with a bit of a background whistle. Have tried fiddling with various parameters with little success. The station comes in very clear in CubicSDR using this same hardware. Possibly I'm missing some critical parameter? The trace below indicates it is tuning to 91.371M when the command line argument specifies 91.1M, which is perplexing. ("Tuned to 91371000 Hz."). Suggestions?

FREQ=91.1M
# Output device: USB card (aplay -L)
ADEV=plughw:CARD=Audio,DEV=0

./rx_fm -v -f $FREQ -M wbfm -a'Antenna A' - | \
  aplay --device=$ADEV -c 1 -t raw -r 32000 -f S16_LE

verbosity set to 1
Using device 1811000021: mir_sdr_api_version=2.130000 mir_sdr_hw_version=2 
Found 1 channel(s) :
Channel 0 :
  Found 3 antenna(s): Antenna A Antenna B Hi-Z 
  Found 2 gain(s): IFGR RFGR 
  Found 2 frequencies: RF CORR 
  Found 13 sample rates: 250000 500000 1000000 2000000 2048000 3000000 4000000 5000000 6000000 7000000 8000000 9000000 10000000 
  Found 8 bandwidths: 200000 300000 600000 1536000 5000000 6000000 7000000 8000000 
[INFO] Using format CS16.
using wbfm deemphasis filter with time constant 75 us
Using antenna 'Antenna A' on channel 0
Bandwidth set to automatic resulted in 0 Hz.
wbfm: adding 16000 Hz to every input frequency
downsample_passes = 0 (= # of fifth_order() iterations), downsample = 6
capture_rate = dm->downsample * dm->rate_in = 6 * 170000 = 1020000
optimal_settings(freq = 91116000): capture_freq = freq + capture_rate/4 = 91371000
optimal_settings(freq = 91116000): capture_freq +=  cs->edge * dm->rate_in / 2 = 0 * 170000 / 2 = 91371000
optimal_settings(freq = 91116000) delivers freq 91371000, rate 1020000
verbose_set_frequency(91371000 Hz)
  frequency is away from parametrized one, to avoid negative impact from dc
Tuned to 91371000 Hz.
Oversampling input by: 6x.
Oversampling output by: 1x.
Buffer size: 8.03ms
verbose_set_sample_rate(1020000 Hz)
Sampling at 1020000 S/s.
Output at 170000 Hz.
Playing raw data 'stdin' : Signed 16 bit Little Endian, Rate 32000 Hz, Mono
rrobinett commented 5 years ago

I have the same problem and hear only complete silence using an RTL-SDR attached to my Raspberry Pi. No one has yet commented on my November post on this problem, but I see recent checkins so there is hope.

rx_fm would be so useful for my WSPR receive projects. If I get it working I would like to contribute a feature to rx_fm which will generate a series of 2 minute long wav files synchronized to start at each even 2 minute. That feature is available in the kiwirecorder utility I use for LF/MF/HF WSPR recording with the KiwiSDR, and rx_fm will allow me to support many more SDRs.

farlies commented 5 years ago

rx_fm would be so useful for my WSPR receive projects.

Sorry my search missed your earlier post, rrobinett. Agreed about usefulness.

I have since looked for alternative applications, but without luck. At this point I would consider trading the nice RSP2 for less capable hardware if I could identify a product that worked correctly for this simple use case. Is there an RTL or other model that known to work correctly with the current rx_fm?

Briefly: I need a way for a microcomputer to control the receiver frequency for commercial North American FM broadcasts, sending demodulated output to an audio amplifier. This is an aid of a paraplegic patient who cannot use any conventional controls. Something like Silicon Labs Si47xx radio chips would do the job nicely, but I discovered this hardware is not so easy to work with. SDR seemed like a natural fit.

rrobinett commented 5 years ago

The excellent $20 RTl_SDR should work perfectly for your application using the rtl-tools: https://github.com/n1gp/librtlsdr That library supports only the RTl-SDR HW and I would prefer the access to SDRP2 and other Soapy devices provided by this library, but In guess it too will stop waiting for feedback on this library ;=(

guruofquality commented 5 years ago

rx_tools definitely needs some community help. It was basically a hack job of rtl sdr tools ported for soapysdr, but the code was never very good quality to begin with :-/ I'm not the maintainer, but I have been trying to fix warnings, report errors better, improve use of the API, and keep up with pull requests.

I suppose something has been wrong with the FM demod for most of the life of this program at least for certain devices? Or perhaps new and exciting bugs have crept in. If anyone wants a fun weekend project, or is familiar with rtl_fm, its just an FM demod, and a lot of people seem to want to use it. Perhaps we could get a pull request? I would be happy to merge it. I bet its just some stupid casting thing, or a number is off by a factor of two.

guruofquality commented 5 years ago

I found this snippet here and it works out of the box:

rx_fm -M wbfm -f 90.1M | play -r 32k -t raw -e s -b 16 -c 1 -V1 -

The audio is clear enough, could be better. I tested on an RSPDuo with a wire shoved into the SMA port.

PS aplay did not work for me, but play from the sox package was fine

rrobinett commented 5 years ago

Thanks for looking at this, On what platform are you testing? On my Pi 3b running Stretch, this line plays fine:

rtl_fm -d 0 -M wbfm -f 88.5M | sox -r 32k -t raw -e s -b 16 -c 1 - -d

This line runs and seems to think it is playing, but I hear (and see) only silence: rx_fm -d 0 -M wbfm -f 88.5M | sox -r 32k -t raw -e s -b 16 -c 1 - -d

Here is the complete output of the rx_fm session which shows no error messages I can discern until I press ^C to terminate the session:

pi@PiB83:~/wsprdaemon $ rx_fm -d 0 -M wbfm -f 88.5M | sox -r 32k -t raw -e s -b 16 -c 1 - -d

-: (raw)

Encoding: Signed PCM Channels: 1 @ 16-bit Samplerate: 32000Hz Replaygain: off Duration: unknown

In:0.00% 00:00:00.00 [00:00:00.00] Out:0 [ | ] Clip:0 Found Rafael Micro R820T tuner Found Rafael Micro R820T tuner Using device R820T: origin=https://github.com/pothosware/SoapyRTLSDR rtl=0 Found 1 antenna(s): RX Found 1 gain(s): TUNER Found 2 frequencies: RF CORR Found 10 sample rates: 250000 1024000 1536000 1792000 1920000 2048000 2160000 2560000 2880000 3200000 Found 0 bandwidths: [INFO] Using format CS16. Tuner gain semi-automatically set to 40 dB Bandwidth set to automatic resulted in 0 Hz. Tuned to 88771000 Hz. Oversampling input by: 6x. Oversampling output by: 1x. Buffer size: 8.03ms Exact sample rate is: 1020000.026345 Hz Allocating 15 zero-copy buffers Sampling at 1020000 S/s. Output at 170000 Hz. In:0.00% 00:00:06.14 [00:00:00.00] Out:188k [ | ] Clip:0 ^CSignal caught, exiting!

User cancel, exiting... readStream read failed: -1 dongle_thread_fn terminated In:0.00% 00:00:06.30 [00:00:00.00] Out:197k [ | ] Clip:0 Aborted. pi@PiB83:~/wsprdaemon $

guruofquality commented 5 years ago

On what platform are you testing?

lsb_release -a
LSB Version:    core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:core-4.1-amd64:core-4.1-noarch
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:        18.04
Codename:       bionic

On my Pi 3b running Stretch, this line plays fine: rtl_fm -d 0 -M wbfm -f 88.5M | sox -r 32k -t raw -e s -b 16 -c 1 - -d This line runs and seems to think it is playing, but I hear (and see) only silence: rx_fm -d 0 -M wbfm -f 88.5M | sox -r 32k -t raw -e s -b 16 -c 1 - -d

I dont see the difference between these commands, why does one work and one is silent?

If this is an issue with the audio player, can you test with a audio wave capture that works?

rrobinett commented 5 years ago

I am trying to run on a Raspberry Pi 3b with vanilla Raspbian Stretch OS:

pi@PiB83:~/wsprdaemon $ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.6 (stretch) Release: 9.6 Codename: stretch pi@PiB83:~/wsprdaemon $

The difference is the first command runs 'rtl_fm' and feeds its raw output to sox which plays it fine on my speakers. The second command is running 'rx_fm' with the same command line arguments outputting raw to the same sox command line, but there is only silence on the speakers.

I have tried writing the output of rx_fm to wav file and playing that wav file with sox and other utilities. All of them report that rx_fm created a valid wav file at the rate and format I specified, but all of them report only silent audio in that file.

guruofquality commented 5 years ago

Ahh, I missed the rx vs rtl, I was thinking different arguments.

So one thing that bothers me about rx_fm is this line: https://github.com/rxseger/rx_tools/blob/master/src/rtl_fm.c#L844

for (i=0; i<(int)len; i++) {
        s->buf16[i] = ( (int16_t)buf[i] / 32767.0 * 128.0 + 0.4);
        // TODO: remove downconversion from 16-bit to 8-bit
}

https://github.com/keenerd/rtl-sdr/blob/master/src/rtl_fm.c#L984

    for (i=0; i<(int)len; i++) {
s->buf16[i] = (int16_t)buf[i] - 127;}

The rtl one is just converting from its 8-bit format to signed 16 bit, but the RX tools one should not need to do this, and it appears to be throwing out a lot of precision with the big divide. Thats a divide by 255, so if the rtl samples were 8 bit, and were not scaled up to msb, this would entirely throw them out. Can you try and change this line to just copy the samples without scale into s->buf16[i]?

rrobinett commented 5 years ago

thanks so much!
i'm very busy today but I'll try that ASAP

farlies commented 5 years ago

Thanks GoQ for looking into this. And thanks rrobinett for the hardware suggestion-I should receive one this week. Unlike rrobinett, I get plenty of audio output, its just seems to be the wrong frequency--or mangled in some fashion suggesting this. I'm also on RPi-3 and using the SDRPlay image (0.5) as the base system. RPi native sound is not that great, so i'm using a USB audio dongle.

My attempts to coax rx_fm onto the right frequency have been inadequate.
E.g. to get 91.1M, the closest I've been able to get is to specify 90.845M on the command line. Runtime trace (-v) then prints out "Tuned to 91116000 Hz.". Audio output is a screech.

I experimented with the scaling patch mentioned above--this actually helped noticeably! The desired station (a very strong one) can now just be made out, albeit weak and distorted.

That GoQ is able to make this work fairly well on Debian (x86?) with Sox/play is trying to tell us something. I will see if I can duplicate that configuration.

BTW, if having another code reviewer would help at some point, I have decades of C language experience. (Unfortunately, my modulation theory is decades rusty.)

rrobinett commented 3 years ago

Thanks GoQ.
Changing the scaling did produce good audio from rtl_fm, although the output would overload without a divide by 2. I wonder if this change would improve the quality of FM and other modes? Next I will try other SDRs lie the SDRPlay to see if the same scaling is needed.

++++++++++++++

pi@Wsprdaemon-Pi:~/rx_tools/src $ diff rtl_fm.c save/ 846c846 < s->buf16[i] = ( ( (int16_t)buf[i] / 2) ); / / 32767.0 128.0 + 0.4); */

  s->buf16[i] = ( (int16_t)buf[i] / 32767.0 * 128.0 + 0.4);

pi@Wsprdaemon-Pi:~/rx_tools/src $

TrentCats commented 2 months ago

rrobinett's code reviewer wrote a multi-page PDF outlining the GNU Radio approach:

https://github.com/LoekVeeger/My-whisperdaemon-rspdevices

TrentCats commented 2 months ago

rx_fm would be so useful for my WSPR receive projects. If I get it working I would like to contribute a feature to rx_fm which will generate a series of 2 minute long wav files synchronized to start at each even 2 minute.

https://github.com/LoekVeeger/My-whisperdaemon-rspdevices