created a static radio player

This commit is contained in:
2024-02-12 19:05:17 -05:00
parent 49d36a017a
commit a922b8db3f
2 changed files with 860 additions and 0 deletions

641
ex 1.grc Normal file
View File

@ -0,0 +1,641 @@
options:
parameters:
author: ''
catch_exceptions: 'True'
category: '[GRC Hier Blocks]'
cmake_opt: ''
comment: ''
copyright: ''
description: ''
gen_cmake: 'On'
gen_linking: dynamic
generate_options: qt_gui
hier_block_src_path: '.:'
id: ex1
max_nouts: '0'
output_language: python
placement: (0,0)
qt_qss_theme: ''
realtime_scheduling: ''
run: 'True'
run_command: '{python} -u {filename}'
run_options: prompt
sizing_mode: fixed
thread_safe_setters: ''
title: fm radio example
window_size: (1000,1000)
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [8, 8]
rotation: 0
state: enabled
blocks:
- name: center_freq
id: variable
parameters:
comment: ''
value: 97.9e6
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [168, 784.0]
rotation: 0
state: enabled
- name: channel_freq
id: variable
parameters:
comment: ''
value: '96100000.0'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [48, 864.0]
rotation: 0
state: enabled
- name: channel_width
id: variable
parameters:
comment: ''
value: 200e3
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [168, 864.0]
rotation: 0
state: enabled
- name: samp_rate
id: variable
parameters:
comment: ''
value: 20e6
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [64, 784.0]
rotation: 0
state: enabled
- name: volume_adjust
id: variable_qtgui_range
parameters:
comment: ''
gui_hint: ''
label: ''
min_len: '200'
orient: QtCore.Qt.Horizontal
rangeType: float
start: '0'
step: '.01'
stop: '5'
value: '1'
widget: counter_slider
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [984, 872.0]
rotation: 0
state: enabled
- name: analog_sig_source_x_0
id: analog_sig_source_x
parameters:
affinity: ''
alias: ''
amp: '1'
comment: ''
freq: center_freq - channel_freq
maxoutbuf: '0'
minoutbuf: '0'
offset: '0'
phase: '0'
samp_rate: samp_rate
showports: 'False'
type: complex
waveform: analog.GR_COS_WAVE
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [128, 616.0]
rotation: 0
state: enabled
- name: analog_wfm_rcv_0
id: analog_wfm_rcv
parameters:
affinity: ''
alias: ''
audio_decimation: '10'
comment: ''
maxoutbuf: '0'
minoutbuf: '0'
quad_rate: '48000'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [816, 608.0]
rotation: 0
state: enabled
- name: audio_sink_0
id: audio_sink
parameters:
affinity: ''
alias: ''
comment: ''
device_name: ''
num_inputs: '1'
ok_to_block: 'True'
samp_rate: '48000'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1080, 504.0]
rotation: 0
state: enabled
- name: blocks_multiply_const_vxx_0
id: blocks_multiply_const_vxx
parameters:
affinity: ''
alias: ''
comment: ''
const: volume_adjust
maxoutbuf: '0'
minoutbuf: '0'
type: float
vlen: '1'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1048, 672.0]
rotation: 0
state: enabled
- name: blocks_multiply_xx_0
id: blocks_multiply_xx
parameters:
affinity: ''
alias: ''
comment: ''
maxoutbuf: '0'
minoutbuf: '0'
num_inputs: '2'
type: complex
vlen: '1'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [440, 552.0]
rotation: 0
state: enabled
- name: low_pass_filter_0
id: low_pass_filter
parameters:
affinity: ''
alias: ''
beta: '6.76'
comment: ''
cutoff_freq: 75e3
decim: int(samp_rate/channel_width)
gain: '1'
interp: '1'
maxoutbuf: '0'
minoutbuf: '0'
samp_rate: samp_rate
type: fir_filter_ccf
width: 25e3
win: window.WIN_HAMMING
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [488, 748.0]
rotation: 0
state: enabled
- name: osmosdr_source_0
id: osmosdr_source
parameters:
affinity: ''
alias: ''
ant0: ''
ant1: ''
ant10: ''
ant11: ''
ant12: ''
ant13: ''
ant14: ''
ant15: ''
ant16: ''
ant17: ''
ant18: ''
ant19: ''
ant2: ''
ant20: ''
ant21: ''
ant22: ''
ant23: ''
ant24: ''
ant25: ''
ant26: ''
ant27: ''
ant28: ''
ant29: ''
ant3: ''
ant30: ''
ant31: ''
ant4: ''
ant5: ''
ant6: ''
ant7: ''
ant8: ''
ant9: ''
args: '""'
bb_gain0: '20'
bb_gain1: '20'
bb_gain10: '20'
bb_gain11: '20'
bb_gain12: '20'
bb_gain13: '20'
bb_gain14: '20'
bb_gain15: '20'
bb_gain16: '20'
bb_gain17: '20'
bb_gain18: '20'
bb_gain19: '20'
bb_gain2: '20'
bb_gain20: '20'
bb_gain21: '20'
bb_gain22: '20'
bb_gain23: '20'
bb_gain24: '20'
bb_gain25: '20'
bb_gain26: '20'
bb_gain27: '20'
bb_gain28: '20'
bb_gain29: '20'
bb_gain3: '20'
bb_gain30: '20'
bb_gain31: '20'
bb_gain4: '20'
bb_gain5: '20'
bb_gain6: '20'
bb_gain7: '20'
bb_gain8: '20'
bb_gain9: '20'
bw0: '0'
bw1: '0'
bw10: '0'
bw11: '0'
bw12: '0'
bw13: '0'
bw14: '0'
bw15: '0'
bw16: '0'
bw17: '0'
bw18: '0'
bw19: '0'
bw2: '0'
bw20: '0'
bw21: '0'
bw22: '0'
bw23: '0'
bw24: '0'
bw25: '0'
bw26: '0'
bw27: '0'
bw28: '0'
bw29: '0'
bw3: '0'
bw30: '0'
bw31: '0'
bw4: '0'
bw5: '0'
bw6: '0'
bw7: '0'
bw8: '0'
bw9: '0'
clock_source0: ''
clock_source1: ''
clock_source2: ''
clock_source3: ''
clock_source4: ''
clock_source5: ''
clock_source6: ''
clock_source7: ''
comment: ''
corr0: '0'
corr1: '0'
corr10: '0'
corr11: '0'
corr12: '0'
corr13: '0'
corr14: '0'
corr15: '0'
corr16: '0'
corr17: '0'
corr18: '0'
corr19: '0'
corr2: '0'
corr20: '0'
corr21: '0'
corr22: '0'
corr23: '0'
corr24: '0'
corr25: '0'
corr26: '0'
corr27: '0'
corr28: '0'
corr29: '0'
corr3: '0'
corr30: '0'
corr31: '0'
corr4: '0'
corr5: '0'
corr6: '0'
corr7: '0'
corr8: '0'
corr9: '0'
dc_offset_mode0: '0'
dc_offset_mode1: '0'
dc_offset_mode10: '0'
dc_offset_mode11: '0'
dc_offset_mode12: '0'
dc_offset_mode13: '0'
dc_offset_mode14: '0'
dc_offset_mode15: '0'
dc_offset_mode16: '0'
dc_offset_mode17: '0'
dc_offset_mode18: '0'
dc_offset_mode19: '0'
dc_offset_mode2: '0'
dc_offset_mode20: '0'
dc_offset_mode21: '0'
dc_offset_mode22: '0'
dc_offset_mode23: '0'
dc_offset_mode24: '0'
dc_offset_mode25: '0'
dc_offset_mode26: '0'
dc_offset_mode27: '0'
dc_offset_mode28: '0'
dc_offset_mode29: '0'
dc_offset_mode3: '0'
dc_offset_mode30: '0'
dc_offset_mode31: '0'
dc_offset_mode4: '0'
dc_offset_mode5: '0'
dc_offset_mode6: '0'
dc_offset_mode7: '0'
dc_offset_mode8: '0'
dc_offset_mode9: '0'
freq0: center_freq
freq1: 100e6
freq10: 100e6
freq11: 100e6
freq12: 100e6
freq13: 100e6
freq14: 100e6
freq15: 100e6
freq16: 100e6
freq17: 100e6
freq18: 100e6
freq19: 100e6
freq2: 100e6
freq20: 100e6
freq21: 100e6
freq22: 100e6
freq23: 100e6
freq24: 100e6
freq25: 100e6
freq26: 100e6
freq27: 100e6
freq28: 100e6
freq29: 100e6
freq3: 100e6
freq30: 100e6
freq31: 100e6
freq4: 100e6
freq5: 100e6
freq6: 100e6
freq7: 100e6
freq8: 100e6
freq9: 100e6
gain0: '0'
gain1: '10'
gain10: '10'
gain11: '10'
gain12: '10'
gain13: '10'
gain14: '10'
gain15: '10'
gain16: '10'
gain17: '10'
gain18: '10'
gain19: '10'
gain2: '10'
gain20: '10'
gain21: '10'
gain22: '10'
gain23: '10'
gain24: '10'
gain25: '10'
gain26: '10'
gain27: '10'
gain28: '10'
gain29: '10'
gain3: '10'
gain30: '10'
gain31: '10'
gain4: '10'
gain5: '10'
gain6: '10'
gain7: '10'
gain8: '10'
gain9: '10'
gain_mode0: 'False'
gain_mode1: 'False'
gain_mode10: 'False'
gain_mode11: 'False'
gain_mode12: 'False'
gain_mode13: 'False'
gain_mode14: 'False'
gain_mode15: 'False'
gain_mode16: 'False'
gain_mode17: 'False'
gain_mode18: 'False'
gain_mode19: 'False'
gain_mode2: 'False'
gain_mode20: 'False'
gain_mode21: 'False'
gain_mode22: 'False'
gain_mode23: 'False'
gain_mode24: 'False'
gain_mode25: 'False'
gain_mode26: 'False'
gain_mode27: 'False'
gain_mode28: 'False'
gain_mode29: 'False'
gain_mode3: 'False'
gain_mode30: 'False'
gain_mode31: 'False'
gain_mode4: 'False'
gain_mode5: 'False'
gain_mode6: 'False'
gain_mode7: 'False'
gain_mode8: 'False'
gain_mode9: 'False'
if_gain0: '20'
if_gain1: '20'
if_gain10: '20'
if_gain11: '20'
if_gain12: '20'
if_gain13: '20'
if_gain14: '20'
if_gain15: '20'
if_gain16: '20'
if_gain17: '20'
if_gain18: '20'
if_gain19: '20'
if_gain2: '20'
if_gain20: '20'
if_gain21: '20'
if_gain22: '20'
if_gain23: '20'
if_gain24: '20'
if_gain25: '20'
if_gain26: '20'
if_gain27: '20'
if_gain28: '20'
if_gain29: '20'
if_gain3: '20'
if_gain30: '20'
if_gain31: '20'
if_gain4: '20'
if_gain5: '20'
if_gain6: '20'
if_gain7: '20'
if_gain8: '20'
if_gain9: '20'
iq_balance_mode0: '0'
iq_balance_mode1: '0'
iq_balance_mode10: '0'
iq_balance_mode11: '0'
iq_balance_mode12: '0'
iq_balance_mode13: '0'
iq_balance_mode14: '0'
iq_balance_mode15: '0'
iq_balance_mode16: '0'
iq_balance_mode17: '0'
iq_balance_mode18: '0'
iq_balance_mode19: '0'
iq_balance_mode2: '0'
iq_balance_mode20: '0'
iq_balance_mode21: '0'
iq_balance_mode22: '0'
iq_balance_mode23: '0'
iq_balance_mode24: '0'
iq_balance_mode25: '0'
iq_balance_mode26: '0'
iq_balance_mode27: '0'
iq_balance_mode28: '0'
iq_balance_mode29: '0'
iq_balance_mode3: '0'
iq_balance_mode30: '0'
iq_balance_mode31: '0'
iq_balance_mode4: '0'
iq_balance_mode5: '0'
iq_balance_mode6: '0'
iq_balance_mode7: '0'
iq_balance_mode8: '0'
iq_balance_mode9: '0'
maxoutbuf: '0'
minoutbuf: '0'
nchan: '1'
num_mboards: '1'
sample_rate: samp_rate
sync: sync
time_source0: ''
time_source1: ''
time_source2: ''
time_source3: ''
time_source4: ''
time_source5: ''
time_source6: ''
time_source7: ''
type: fc32
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [96, 380.0]
rotation: 0
state: enabled
- name: qtgui_sink_x_0_0
id: qtgui_sink_x
parameters:
affinity: ''
alias: ''
bw: samp_rate
comment: ''
fc: channel_freq
fftsize: '32768'
gui_hint: ''
maxoutbuf: '0'
minoutbuf: '0'
name: '""'
plotconst: 'True'
plotfreq: 'True'
plottime: 'True'
plotwaterfall: 'True'
rate: '10'
showports: 'False'
showrf: 'True'
type: complex
wintype: window.WIN_BLACKMAN_hARRIS
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [800, 280.0]
rotation: 0
state: enabled
- name: rational_resampler_xxx_0
id: rational_resampler_xxx
parameters:
affinity: ''
alias: ''
comment: ''
decim: '5'
fbw: '0'
interp: '12'
maxoutbuf: '0'
minoutbuf: '0'
taps: '[]'
type: ccc
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [608, 560.0]
rotation: 0
state: enabled
connections:
- [analog_sig_source_x_0, '0', blocks_multiply_xx_0, '1']
- [analog_wfm_rcv_0, '0', blocks_multiply_const_vxx_0, '0']
- [blocks_multiply_const_vxx_0, '0', audio_sink_0, '0']
- [blocks_multiply_xx_0, '0', low_pass_filter_0, '0']
- [blocks_multiply_xx_0, '0', qtgui_sink_x_0_0, '0']
- [low_pass_filter_0, '0', rational_resampler_xxx_0, '0']
- [osmosdr_source_0, '0', blocks_multiply_xx_0, '0']
- [rational_resampler_xxx_0, '0', analog_wfm_rcv_0, '0']
metadata:
file_format: 1
grc_version: 3.10.9.2

219
static_radio_ttf_and_audio.py Executable file
View File

@ -0,0 +1,219 @@
#!/usr/bin/env python3
from PyQt5 import Qt
from gnuradio import qtgui
from PyQt5 import QtCore
from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import filter
from gnuradio.filter import firdes
from gnuradio import gr
from gnuradio.fft import window
import sys
import signal
from PyQt5 import Qt
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
import osmosdr
import time
import sip
class ex1(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "fm radio example", catch_exceptions=True)
Qt.QWidget.__init__(self)
self.setWindowTitle("fm radio example")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except BaseException as exc:
print(f"Qt GUI: Could not set Icon: {str(exc)}", file=sys.stderr)
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "ex1")
try:
geometry = self.settings.value("geometry")
if geometry:
self.restoreGeometry(geometry)
except BaseException as exc:
print(f"Qt GUI: Could not restore geometry: {str(exc)}", file=sys.stderr)
##################################################
# Variables
##################################################
self.volume_adjust = volume_adjust = 1
self.samp_rate = samp_rate = 20e6
self.channel_width = channel_width = 200e3
self.channel_freq = channel_freq = 96100000.0
self.center_freq = center_freq = 97.9e6
##################################################
# Blocks
##################################################
self._volume_adjust_range = qtgui.Range(0, 5, .01, 1, 200)
self._volume_adjust_win = qtgui.RangeWidget(self._volume_adjust_range, self.set_volume_adjust, "'volume_adjust'", "counter_slider", float, QtCore.Qt.Horizontal)
self.top_layout.addWidget(self._volume_adjust_win)
self.rational_resampler_xxx_0 = filter.rational_resampler_ccc(
interpolation=12,
decimation=5,
taps=[],
fractional_bw=0)
self.qtgui_sink_x_0_0 = qtgui.sink_c(
32768, #fftsize
window.WIN_BLACKMAN_hARRIS, #wintype
channel_freq, #fc
samp_rate, #bw
"", #name
True, #plotfreq
True, #plotwaterfall
True, #plottime
True, #plotconst
None # parent
)
self.qtgui_sink_x_0_0.set_update_time(1.0/10)
self._qtgui_sink_x_0_0_win = sip.wrapinstance(self.qtgui_sink_x_0_0.qwidget(), Qt.QWidget)
self.qtgui_sink_x_0_0.enable_rf_freq(True)
self.top_layout.addWidget(self._qtgui_sink_x_0_0_win)
self.osmosdr_source_0 = osmosdr.source(
args="numchan=" + str(1) + " " + ""
)
self.osmosdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t())
self.osmosdr_source_0.set_sample_rate(samp_rate)
self.osmosdr_source_0.set_center_freq(center_freq, 0)
self.osmosdr_source_0.set_freq_corr(0, 0)
self.osmosdr_source_0.set_dc_offset_mode(0, 0)
self.osmosdr_source_0.set_iq_balance_mode(0, 0)
self.osmosdr_source_0.set_gain_mode(False, 0)
self.osmosdr_source_0.set_gain(0, 0)
self.osmosdr_source_0.set_if_gain(20, 0)
self.osmosdr_source_0.set_bb_gain(20, 0)
self.osmosdr_source_0.set_antenna('', 0)
self.osmosdr_source_0.set_bandwidth(0, 0)
self.low_pass_filter_0 = filter.fir_filter_ccf(
(int(samp_rate/channel_width)),
firdes.low_pass(
1,
samp_rate,
75e3,
25e3,
window.WIN_HAMMING,
6.76))
self.blocks_multiply_xx_0 = blocks.multiply_vcc(1)
self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(volume_adjust)
self.audio_sink_0 = audio.sink(48000, '', True)
self.analog_wfm_rcv_0 = analog.wfm_rcv(
quad_rate=48000,
audio_decimation=10,
)
self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, (center_freq - channel_freq), 1, 0, 0)
##################################################
# Connections
##################################################
self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 1))
self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_multiply_const_vxx_0, 0))
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.audio_sink_0, 0))
self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0))
self.connect((self.blocks_multiply_xx_0, 0), (self.qtgui_sink_x_0_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.rational_resampler_xxx_0, 0))
self.connect((self.osmosdr_source_0, 0), (self.blocks_multiply_xx_0, 0))
self.connect((self.rational_resampler_xxx_0, 0), (self.analog_wfm_rcv_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "ex1")
self.settings.setValue("geometry", self.saveGeometry())
self.stop()
self.wait()
event.accept()
def get_volume_adjust(self):
return self.volume_adjust
def set_volume_adjust(self, volume_adjust):
self.volume_adjust = volume_adjust
self.blocks_multiply_const_vxx_0.set_k(self.volume_adjust)
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 75e3, 25e3, window.WIN_HAMMING, 6.76))
self.osmosdr_source_0.set_sample_rate(self.samp_rate)
self.qtgui_sink_x_0_0.set_frequency_range(self.channel_freq, self.samp_rate)
def get_channel_width(self):
return self.channel_width
def set_channel_width(self, channel_width):
self.channel_width = channel_width
def get_channel_freq(self):
return self.channel_freq
def set_channel_freq(self, channel_freq):
self.channel_freq = channel_freq
self.analog_sig_source_x_0.set_frequency((self.center_freq - self.channel_freq))
self.qtgui_sink_x_0_0.set_frequency_range(self.channel_freq, self.samp_rate)
def get_center_freq(self):
return self.center_freq
def set_center_freq(self, center_freq):
self.center_freq = center_freq
self.analog_sig_source_x_0.set_frequency((self.center_freq - self.channel_freq))
self.osmosdr_source_0.set_center_freq(self.center_freq, 0)
def main(top_block_cls=ex1, options=None):
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def sig_handler(sig=None, frame=None):
tb.stop()
tb.wait()
Qt.QApplication.quit()
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
timer = Qt.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
qapp.exec_()
if __name__ == '__main__':
main()