OP25 OP25 different audio on left and right channels?

jtlyles

Member
Joined
Jun 14, 2010
Messages
6
I am running a raspberry pi 3 and have 2 instances of OP25 running using 2 SDR dongles, commands below. Currently, the audio from both instances is output on both the left and right audio channels when using the RPi's 3.5 jack. Is there a way to have the first OP25 audio on the left channel and the 2nd OP25only on the right channel when listening locally? How about if listening remotely?

Current commands:
./rx.py --args 'rtl=0' -N 'LNA:35' -S 2400000 -f 771.98125e6 -o 25000 -q 0 -T trunk_nfulton.tsv -V -2 -U 2> stderr.2
./rx.py --args 'rtl=1' -N 'LNA:35' -S 2400000 -f 854.6125e6 -o 25000 -q 0 -T trunk_dekalb.tsv -V -u 23460 -2 -U 2> stderr.2.1

Thank you,

James
 

boatbod

Member
Joined
Mar 3, 2007
Messages
2,410
Location
Talbot Co, MD
I am running a raspberry pi 3 and have 2 instances of OP25 running using 2 SDR dongles, commands below. Currently, the audio from both instances is output on both the left and right audio channels when using the RPi's 3.5 jack. Is there a way to have the first OP25 audio on the left channel and the 2nd OP25only on the right channel when listening locally? How about if listening remotely?

Current commands:
./rx.py --args 'rtl=0' -N 'LNA:35' -S 2400000 -f 771.98125e6 -o 25000 -q 0 -T trunk_nfulton.tsv -V -2 -U 2> stderr.2
./rx.py --args 'rtl=1' -N 'LNA:35' -S 2400000 -f 854.6125e6 -o 25000 -q 0 -T trunk_dekalb.tsv -V -u 23460 -2 -U 2> stderr.2.1

Thank you,

James
op25 does support playing separate left and right channel audio when running one of the two-slot protocols such as DMR, but it's not going to let you do that with P25 due to the way the udp ports are handles internally. Likely the only way to achieve what you'd like to do is either via ALSA mixing or (more easily) by writing a liquidsoap script to capture the two separate streams, drop the left and right channels respectively and then mix them together. If you read enough of the Savonet liquidsoap docs you should be able to figure it out.
 

jtlyles

Member
Joined
Jun 14, 2010
Messages
6
Thank you for the reply.

Would it be possible to use a second sound card (USB dongle type, etc) and then have each instance of OP25 output to a different audio device? Or will there still be an issue with the UDP ports? I could probably get that working faster than a liquidsoap script.
 

boatbod

Member
Joined
Mar 3, 2007
Messages
2,410
Location
Talbot Co, MD
Thank you for the reply.

Would it be possible to use a second sound card (USB dongle type, etc) and then have each instance of OP25 output to a different audio device? Or will there still be an issue with the UDP ports? I could probably get that working faster than a liquidsoap script.
It's totally possible to have multiple sound card (or no sound cards at all if using liquidsoap streaming) but when you run multiple instances of op25 you have to define different UDP ports using the -u parameter. Internally the ports are used in pairs, so I usually just increment in 10's to make life easy.

Examples of a three-instance setup
Code:
./rx.py -l http:192.168.1.7:8081 -M meta-fire.json --args "rtl=0" --gains 'lna:36' -S 960000 -T trunk-fire.tsv -q 0 -d 0 -v 1 -2 -u 23456 -V -w 2> stderr-fire.2
./rx.py -l http:192.168.1.7:8082 -M meta-leo.json --args "rtl=1" --gains 'lna:36' -S 960000 -T trunk-leo.tsv -q 0 -d 0 -v 1 -2 -u 23466 -V -w 2> stderr-leo.2
./rx.py -l http:192.168.1.7:8083 -M meta-dorc.json --args "rtl=2" --gains 'lna:49' -o 15000 -S 960000 -T trunk-dorc.tsv -X -q -1 -v 1 -2 -u 23476 -V -w 2> stderr-dorc.2
 

wgbecks

Member
Joined
Jan 17, 2005
Messages
257
Location
Porterfield, Wisconsin
James,

Using liquidsoap, it's possible to output audio from each of your instances of op25 as separate "left" and "right" audio channels from the earphone (speaker) jack as well as a stereo mp3 stream to your private icecast server, or to a feed on BCFY.

Following @boatbod's advice, you must first configure your rx.py command lines to output audio as PCM using separate UDP audio (ports) steams for input to liquidsoap.

Review README-rpi3-liquidsoap in the ~/op25 folder for installation and configuration instructions. Additionally, its advisable to run
op25 (rx.py) and liquidsoap as services that will auto start at bootup of the Raspberry Pi.

Shown below are example op25.sh and op25.liq scripts to get you up and running. I'd suggest lowering the sampling rate for both
of your SDR's to something list -S 1000000 to reduce CPU and USB bus cycles, and in view of the additional load incurred with the
addition of liquidsoap to to the mix.

Keep in mind that the 3.5 MM audio jack on the RPi is a 4-pole jack that carries composite video on one of the poles that will more
than likely introduce buzzing and noise when plugging in a headphone or amplified speakers with a 3-pole plug. You'll need an adapter
if your audio device doesn't already have a 4-pole plug.

(Example op25.sh)

./rx.py --args 'rtl=0' -N 'LNA:35' -S 2400000 -f 771.98125e6 -o 25000 -q 0 -T trunk_nfulton.tsv -2 -V -u 23450 2> stderr.2
./rx.py --args 'rtl=1' -N 'LNA:35' -S 2400000 -f 854.6125e6 -o 25000 -q 0 -T trunk_dekalb.tsv -2 -V -u 23460 2> stderr.2.1

(Example op25.liq)

#!/usr/bin/liquidsoap

# Example liquidsoap streaming from op25 to icecast
# (c) 2019, 2020 gnorbury@bondcar.com, wllmbecks@gmail.com
#

set("log.stdout", true)
set("log.file.path", "/home/pi/op25/op25/gr-op25_repeater/apps/liquidsoap.log")
set("log.file", true)
set("log.level", 3)

# Make the native sample rate compatible with op25
set("frame.audio.samplerate", 8000)

# Consider increasing the buffer value on slow systems such as RPi3. e.g. buffer=0.25
# Longer buffer results in less choppy audio but at the expense of increased latency.

# Left channel input source
#left = input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -u 23450 -x 2 -s")
#left = audio_to_stereo(left)
#left = stereo.pan(pan=1., left)

# Right channel input source
#right = input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -u 23460 -x 2 -s")
#right = audio_to_stereo(right)
#right = stereo.pan(pan=-1., right)

# OPTIONAL AUDIO SIGNAL PROCESSING BLOCKS
# Uncomment to enable

# High pass filter
left = filter.iir.butterworth.high(frequency = 200.0, order = 4, left)
right = filter.iir.butterworth.high(frequency = 200.0, order = 4, right)

# Low pass filter
left = filter.iir.butterworth.low(frequency = 3250.0, order = 4, left)
right = filter.iir.butterworth.low(frequency = 3250.0, order = 4, right)

# Normalization -- Adjust target gains independently to achieve left/right balance --
left = normalize(left, gain_max = 3.0, gain_min = -3.0, target = -16.0, threshold = -40.0)
right = normalize(right, gain_max = 3.0, gain_min = -3.0, target = -16.0, threshold = -40.0)

input = mksafe(add(normalize=false, [left,right]))

# LOCAL AUDIO OUTPUT
# Uncomment the line below to enable local sound
output.ao(input)

# ICECAST STREAMING
# Uncomment to enable output to an icecast server
# Change the "host", "password", and "mount" strings appropriately first!
# For metadata to work properly, the host address given here MUST MATCH the address in op25's meta.json file
#
output.icecast(%mp3(bitrate=16, samplerate=22050, stereo=true), description="op25", genre="Public Safety", url="", fallible=false, icy_metadata="false", host="localhost", port=8000, mount="op25", password="hackme", input)



Good luck,

Bill, WA8WG
 

jtlyles

Member
Joined
Jun 14, 2010
Messages
6
Thank you so much for this! The 4 pin 3.5mm, would explain why I always have a buzzing on the local speakers. I'll give the liquidsoap configurations it a try, but it sounds just like what I needed.

James
 

jtlyles

Member
Joined
Jun 14, 2010
Messages
6
I had to add a -w flag to the op25.sh string to get it to work and uncomment "left" and "right" in the .liq example. The sound is a bit choppy especially with both channels actively decoding, but otherwise, it is working. I'll play with the sampling rate next.

./rx.py --args 'rtl=0' -N 'LNA:35' -S 2400000 -f 771.98125e6 -o 25000 -q 0 -T trunk_nfulton.tsv -2 -V -w -u 23450 2> stderr.2
./rx.py --args 'rtl=1' -N 'LNA:35' -S 2400000 -f 854.6125e6 -o 25000 -q 0 -T trunk_dekalb.tsv -2 -V -w -u 23460 2> stderr.2.1


Thanks,

James
 

jtlyles

Member
Joined
Jun 14, 2010
Messages
6
Uninstalled pulse audio and went back to straight ALAS, then reduced the sampling rate, -S 1000000, for both channels. Now when 2 instances of OP25 are running, the rtl=0 is right channel audio, and the rtl=1 is left channel audio on the local 3.5mm audio jack. Must open 3 terminal windows, the 2 op25 scanners, then liquidsoap last.

Remaining issue- the audio works fine when I start liquidsoap last from a 3rd terminal window. However, when I try to run the same script via a desktop shortcut/shell script liquidsoap just returns errors. Script below.

(3-OP25 liquidsoap)
[Desktop Entry]
Name=3-OP25 liquidsoap
Comment=Run liquidsoap audio so that RTL=0 is right audio and RTL=1 audio is left audio
Icon=/home/pi/op25/icon_speaker.png
Exec=/home/pi/op25/op25/gr-op25_repeater/apps/op25_1.liq
Type=Application
Encoding=UTF-8
Terminal=true
Categories=None;
 

boatbod

Member
Joined
Mar 3, 2007
Messages
2,410
Location
Talbot Co, MD
Remaining issue- the audio works fine when I start liquidsoap last from a 3rd terminal window. However, when I try to run the same script via a desktop shortcut/shell script liquidsoap just returns errors. Script below.
Turn on logging at level 3 or above and see if it helps you see what's failing.
 

wgbecks

Member
Joined
Jan 17, 2005
Messages
257
Location
Porterfield, Wisconsin
Sorry about omitting the (-w) flags in post #5 that was quite likely a result of my hasty cut and paste from your original post. but glad you got it sorted out. You know, it's hard to get good help these days! : )

Now, moving onward and upward my I suggest a solution to resolve startup and permissions issues that will also simplify the entire process by eliminating the need for multiple open terminals and manual execution of your applications. The answer is simply to to start and run them as services.

Open and read ~/op25/README-rpi3-liquidsoap with particular attention to "Making liquidsoap and op25 start automatically at boot".
You'll find that @boatbod (Graham) has thoughtfully crafted, and has included two preconstructed files; op25-rx.service & op25-liq.service that are contained in the ~/op25/op25/gr-op25_repeater/apps folder.

These are both ready to use "as is" assuming user "pi" and the the default path of ~/op25/op25/gr-op25_repeater/apps to your applications. You may otherwise need to edit these files to reflect your actual "user" and application path prior to copying into them /etc/systemd/system folder and subsequent initialization.

Keep in mind op25-rx.service points execution to op25.sh in the default apps folder. When running multiple instances of rx.py you'll need to
address the (prepend) the file path for each instance of rx.py with the assumption they live (reside) in separate folders. You only need to install a single instance of op25.liq for op25-liq.service to start following the liquidsoap configuration script (op25.liq) outlined in post # 5 being sure to include the (-w) flags of course!

Bill
 
Top