Added gnuradio flowgraph in case people are curious.

Added the start script which controls the flow of the server application.
Still need to add functionality to listen to audio in the client side.
They will need to listen to serverip:6003
This commit is contained in:
Brandon Rozek 2019-06-02 10:46:00 -04:00
parent 9b58120dfd
commit b2dbe95d2f
3 changed files with 1872 additions and 50 deletions

1774
radio_tuner.grc Normal file

File diff suppressed because it is too large Load diff

24
start Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
compress=1
function cleanup() {
echo "Shutting Down"
rm ./raw_audio_pipe
kill $child_pid
}
mkfifo ./raw_audio_pipe
# Run Radio Server Program in Background
./tuner.py &
child_pid=$!
if [ $compress -eq 1 ]
then
ffmpeg -f f32le -ar 48k -ac 1 -i pipe:0 -f ogg -ab 32k pipe:1 < ./raw_audio_pipe | nc -kl 127.0.0.1 6003
else
tail -f raw_audio_pipe | nc -kl 127.0.0.1 6003
fi
cleanup

122
tuner.py
View file

@ -3,12 +3,11 @@
################################################## ##################################################
# GNU Radio Python Flow Graph # GNU Radio Python Flow Graph
# Title: Top Block # Title: Top Block
# Generated: Sun May 12 22:10:45 2019 # Generated: Sat Jun 1 12:54:09 2019
################################################## ##################################################
from gnuradio import analog from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks from gnuradio import blocks
from gnuradio import eng_notation from gnuradio import eng_notation
from gnuradio import filter from gnuradio import filter
@ -21,6 +20,7 @@ import time
import socket import socket
import re import re
class top_block(gr.top_block): class top_block(gr.top_block):
def __init__(self): def __init__(self):
@ -29,15 +29,17 @@ class top_block(gr.top_block):
################################################## ##################################################
# Variables # Variables
################################################## ##################################################
self.samp_rate = samp_rate = 1536000 self.samp_rate = samp_rate = 2.2e6
self.frequency = frequency = 96900000 self.freq = freq = 101.5e6
self.audio_rate = audio_rate = 48000
self.audio_interp = audio_interp = 4
################################################## ##################################################
# Blocks # Blocks
################################################## ##################################################
self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + '' ) self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + '' )
self.rtlsdr_source_0.set_sample_rate(samp_rate) self.rtlsdr_source_0.set_sample_rate(samp_rate)
self.rtlsdr_source_0.set_center_freq(frequency, 0) self.rtlsdr_source_0.set_center_freq(freq, 0)
self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_freq_corr(0, 0)
self.rtlsdr_source_0.set_dc_offset_mode(2, 0) self.rtlsdr_source_0.set_dc_offset_mode(2, 0)
self.rtlsdr_source_0.set_iq_balance_mode(2, 0) self.rtlsdr_source_0.set_iq_balance_mode(2, 0)
@ -48,22 +50,25 @@ class top_block(gr.top_block):
self.rtlsdr_source_0.set_antenna('', 0) self.rtlsdr_source_0.set_antenna('', 0)
self.rtlsdr_source_0.set_bandwidth(0, 0) self.rtlsdr_source_0.set_bandwidth(0, 0)
self.low_pass_filter_0 = filter.fir_filter_ccf(4, firdes.low_pass( self.rational_resampler_xxx_0 = filter.rational_resampler_ccc(
1, samp_rate, 500000, 60000, firdes.WIN_KAISER, 6.76)) interpolation=audio_rate * audio_interp,
self.blocks_udp_sink_0 = blocks.udp_sink(gr.sizeof_float*1, '127.0.0.1', 7654, 1472, True) decimation=int(samp_rate),
self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) taps=None,
fractional_bw=None,
)
self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_float*1, 'raw_audio_pipe', False)
self.blocks_file_sink_0.set_unbuffered(False)
self.analog_wfm_rcv_0 = analog.wfm_rcv( self.analog_wfm_rcv_0 = analog.wfm_rcv(
quad_rate=384000, quad_rate=audio_rate * audio_interp,
audio_decimation=8, audio_decimation=audio_interp,
) )
################################################## ##################################################
# Connections # Connections
################################################## ##################################################
self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_udp_sink_0, 0)) self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_file_sink_0, 0))
self.connect((self.blocks_throttle_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.analog_wfm_rcv_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.rational_resampler_xxx_0, 0))
self.connect((self.rtlsdr_source_0, 0), (self.blocks_throttle_0, 0))
def get_samp_rate(self): def get_samp_rate(self):
return self.samp_rate return self.samp_rate
@ -71,20 +76,64 @@ class top_block(gr.top_block):
def set_samp_rate(self, samp_rate): def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate self.samp_rate = samp_rate
self.rtlsdr_source_0.set_sample_rate(self.samp_rate) self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 500000, 60000, firdes.WIN_KAISER, 6.76))
self.blocks_throttle_0.set_sample_rate(self.samp_rate)
def get_frequency(self): def get_freq(self):
return self.frequency return self.freq
def set_frequency(self, frequency): def set_freq(self, freq):
self.frequency = frequency self.freq = freq
self.rtlsdr_source_0.set_center_freq(self.frequency, 0) self.rtlsdr_source_0.set_center_freq(self.freq, 0)
def get_audio_rate(self):
return self.audio_rate
def set_audio_rate(self, audio_rate):
self.audio_rate = audio_rate
def get_audio_interp(self):
return self.audio_interp
def set_audio_interp(self, audio_interp):
self.audio_interp = audio_interp
def is_valid_frequency(frequency):
return frequency >= 87500000 and frequency <= 108000000
def parse_commands(conn, tb, commands):
quit = False
for command in commands:
if command == "":
continue
elif command[0] == '?': # Query Section
if command[1:] == "VER":
conn.sendall("Version 0.1\n")
elif command[1:] == "FREQ":
conn.sendall(str(tb.get_freq()) + '\n')
else:
print("UNKNOWN COMMAND: ", command)
elif command[0] == ':': # Setter Section
if command[1:5] == "FREQ":
print("FREQUENCY SET")
frequency = float(command[6:])
if is_valid_frequency(frequency):
tb.set_freq(frequency)
else:
print("ERROR: Invalid Frequency ", frequency)
elif command[1:] == "QUIT":
print("QUITTING")
quit = True
else:
print("UNKNOWN COMMAND: ", command)
else:
print("UNKNOWN COMMAND", command)
# Return state back to application
return {'quit': quit}
def main(top_block_cls=top_block, options=None): def main(top_block_cls=top_block, options=None):
tb = top_block_cls() tb = top_block_cls()
tb.start() tb.start()
HOST = '127.0.0.1' # Loopback Address (Localhost) HOST = '127.0.0.1' # Loopback Address (Localhost)
PORT = 65432 # Semi-Random Port that is non-priviledged (> 1023) PORT = 65432 # Semi-Random Port that is non-priviledged (> 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -103,34 +152,9 @@ def main(top_block_cls=top_block, options=None):
commands = re.split(";", data) commands = re.split(";", data)
if data == "": if data == "":
break break
for command in commands: state = parse_commands(conn, tb, commands)
if command == "": if state['quit']:
continue
elif command[0] == '?':
# Query Section
if command[1:] == "VER":
conn.sendall("Version 0.1\n")
elif command[1:] == "FREQ":
conn.sendall(str(tb.get_frequency()) + '\n')
else:
print("UNKNOWN COMMAND: ", command)
elif command[0] == ':':
# Setter Section
if command[1:5] == "FREQ":
print("FREQUENCY SET")
frequency = float(command[6:])
if frequency >= 87500000 and frequency <= 108000000:
tb.set_frequency(frequency)
else:
print("ERROR: Invalid Frequency ", frequency)
elif command[1:] == "QUIT":
print("QUITTING")
quit = True quit = True
else:
print("UNKNOWN COMMAND: ", command)
else:
print("UNKNOWN COMMAND", command)
conn.close() conn.close()
s.close() s.close()