mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
added rx audio level and moved from linear to dB
This commit is contained in:
parent
3f49b63930
commit
5632310b8c
12 changed files with 118 additions and 39 deletions
|
@ -17,17 +17,22 @@ import {
|
|||
getNewMessagesByDXCallsign,
|
||||
} from "../js/chatHandler";
|
||||
|
||||
import { sendTestFrame, setTxAudioLevel } from "../js/sock.js";
|
||||
import { sendTestFrame, setTxAudioLevel, setRxAudioLevel } from "../js/sock.js";
|
||||
|
||||
function tuneAudio() {
|
||||
sendTestFrame();
|
||||
}
|
||||
|
||||
function set_audio_level() {
|
||||
function set_tx_audio_level() {
|
||||
saveSettingsToFile();
|
||||
setTxAudioLevel(settings.tx_audio_level);
|
||||
}
|
||||
|
||||
function set_rx_audio_level() {
|
||||
saveSettingsToFile();
|
||||
setRxAudioLevel(settings.rx_audio_level);
|
||||
}
|
||||
|
||||
function deleteChat() {
|
||||
//console.log(chat.selectedCallsign)
|
||||
deleteChatByCallsign(chat.selectedCallsign);
|
||||
|
@ -1194,6 +1199,21 @@ const transmissionSpeedChartDataMessageInfo = computed(() => ({
|
|||
Transmit
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text">RX Level</span>
|
||||
<span class="input-group-text">{{ settings.rx_audio_level }}</span>
|
||||
<span class="input-group-text w-75">
|
||||
<input
|
||||
type="range"
|
||||
class="form-range"
|
||||
min="-30"
|
||||
max="20"
|
||||
step="1"
|
||||
id="audioLevelRX"
|
||||
@click="set_rx_audio_level()"
|
||||
v-model="settings.rx_audio_level"
|
||||
/></span>
|
||||
</div>
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text">TX Level</span>
|
||||
<span class="input-group-text">{{ settings.tx_audio_level }}</span>
|
||||
|
@ -1201,11 +1221,11 @@ const transmissionSpeedChartDataMessageInfo = computed(() => ({
|
|||
<input
|
||||
type="range"
|
||||
class="form-range"
|
||||
min="0"
|
||||
max="250"
|
||||
min="-30"
|
||||
max="20"
|
||||
step="1"
|
||||
id="audioLevelTX"
|
||||
@click="set_audio_level()"
|
||||
@click="set_tx_audio_level()"
|
||||
v-model="settings.tx_audio_level"
|
||||
/></span>
|
||||
</div>
|
||||
|
|
|
@ -184,6 +184,7 @@ export function startModem() {
|
|||
tuning_range_fmin: settings.tuning_range_fmin,
|
||||
tuning_range_fmax: settings.tuning_range_fmax,
|
||||
tx_audio_level: settings.tx_audio_level,
|
||||
rx_audio_level: settings.rx_audio_level,
|
||||
respond_to_cq: settings.respond_to_cq,
|
||||
rx_buffer_size: settings.rx_buffer_size,
|
||||
enable_explorer: settings.enable_explorer,
|
||||
|
|
|
@ -55,7 +55,8 @@ const configDefaultSettings =
|
|||
"daemon_port": 3001,\
|
||||
"rx_audio" : "",\
|
||||
"tx_audio" : "",\
|
||||
"tx_audio_level" : 100,\
|
||||
"tx_audio_level" : 0,\
|
||||
"rx_audio_level" : 0,\
|
||||
"mycall": "AA0AA-0",\
|
||||
"myssid": "0",\
|
||||
"mygrid": "JN40aa",\
|
||||
|
|
|
@ -31,6 +31,8 @@ const split_char = "0;1;";
|
|||
// global to keep track of Modem connection error emissions
|
||||
var modemShowConnectStateError = 1;
|
||||
var setTxAudioLevelOnce = true;
|
||||
var setRxAudioLevelOnce = true;
|
||||
|
||||
// network connection Timeout
|
||||
setTimeout(connectModem, 2000);
|
||||
|
||||
|
@ -172,6 +174,7 @@ client.on("data", function (socketdata) {
|
|||
stateStore.mode = data["mode"];
|
||||
stateStore.bandwidth = data["bandwidth"];
|
||||
stateStore.tx_audio_level = data["audio_level"];
|
||||
stateStore.rx_audio_level = data["audio_level"];
|
||||
// if audio level is different from config one, send new audio level to modem
|
||||
//console.log(parseInt(stateStore.tx_audio_level))
|
||||
//console.log(parseInt(settings.tx_audio_level))
|
||||
|
@ -185,6 +188,16 @@ client.on("data", function (socketdata) {
|
|||
setTxAudioLevel(settings.tx_audio_level);
|
||||
}
|
||||
|
||||
if (
|
||||
parseInt(stateStore.rx_audio_level) !==
|
||||
parseInt(settings.rx_audio_level) &&
|
||||
setRxAudioLevelOnce === true
|
||||
) {
|
||||
setRxAudioLevelOnce = false;
|
||||
console.log(setRxAudioLevelOnce);
|
||||
setRxAudioLevel(settings.rx_audio_level);
|
||||
}
|
||||
|
||||
stateStore.dbfs_level = data["audio_dbfs"];
|
||||
stateStore.ptt_state = data["ptt_state"];
|
||||
stateStore.speed_level = data["speed_level"];
|
||||
|
@ -541,6 +554,11 @@ export function setTxAudioLevel(value) {
|
|||
'{"type" : "set", "command" : "tx_audio_level", "value" : "' + value + '"}';
|
||||
writeTncCommand(command);
|
||||
}
|
||||
export function setRxAudioLevel(value) {
|
||||
var command =
|
||||
'{"type" : "set", "command" : "rx_audio_level", "value" : "' + value + '"}';
|
||||
writeTncCommand(command);
|
||||
}
|
||||
|
||||
// Send Message
|
||||
export function sendMessage(obj) {
|
||||
|
|
|
@ -6,6 +6,7 @@ export const useSettingsStore = defineStore("settingsStore", () => {
|
|||
var tx_audio = ref();
|
||||
var rx_audio = ref();
|
||||
var tx_audio_level = ref();
|
||||
var rx_audio_level = ref();
|
||||
|
||||
// network
|
||||
var modem_host = ref("127.0.0.1");
|
||||
|
@ -159,6 +160,7 @@ export const useSettingsStore = defineStore("settingsStore", () => {
|
|||
tx_audio: tx_audio.value,
|
||||
rx_audio: rx_audio.value,
|
||||
tx_audio_level: tx_audio_level.value,
|
||||
rx_audio_level: rx_audio_level.value,
|
||||
};
|
||||
|
||||
return config_export;
|
||||
|
@ -227,5 +229,6 @@ export const useSettingsStore = defineStore("settingsStore", () => {
|
|||
getSerialDevices,
|
||||
serial_devices,
|
||||
tx_audio_level,
|
||||
rx_audio_level,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -41,6 +41,8 @@ export const useStateStore = defineStore("stateStore", () => {
|
|||
|
||||
var hamlib_status = ref("");
|
||||
var tx_audio_level = ref("");
|
||||
var rx_audio_level = ref("");
|
||||
|
||||
var alc = ref("");
|
||||
|
||||
var is_codec2_traffic = ref("");
|
||||
|
@ -159,6 +161,7 @@ export const useStateStore = defineStore("stateStore", () => {
|
|||
audio_recording,
|
||||
hamlib_status,
|
||||
tx_audio_level,
|
||||
rx_audio_level,
|
||||
alc,
|
||||
updateTncState,
|
||||
arq_transmission_percent,
|
||||
|
|
|
@ -58,6 +58,7 @@ class CONFIG:
|
|||
'rx': data[3],
|
||||
'tx': data[4],
|
||||
'txaudiolevel': data[14],
|
||||
'rxaudiolevel': data[26],
|
||||
'auto_tune': data[19]
|
||||
|
||||
}
|
||||
|
|
|
@ -501,6 +501,8 @@ class DAEMON:
|
|||
if data[25] == "True":
|
||||
options.append("--morse")
|
||||
|
||||
options.append("--rx-audio-level")
|
||||
options.append(data[26])
|
||||
|
||||
# safe data to config file
|
||||
config.write_entire_config(data)
|
||||
|
|
|
@ -190,10 +190,17 @@ if __name__ == "__main__":
|
|||
PARSER.add_argument(
|
||||
"--tx-audio-level",
|
||||
dest="tx_audio_level",
|
||||
default=50,
|
||||
default=0,
|
||||
help="Set the tx audio level at an early stage",
|
||||
type=int,
|
||||
)
|
||||
PARSER.add_argument(
|
||||
"--rx-audio-level",
|
||||
dest="rx_audio_level",
|
||||
default=0,
|
||||
help="Set the rx audio level at an early stage",
|
||||
type=int,
|
||||
)
|
||||
PARSER.add_argument(
|
||||
"--rx-buffer-size",
|
||||
dest="rx_buffer_size",
|
||||
|
@ -315,6 +322,7 @@ if __name__ == "__main__":
|
|||
ModemParam.tuning_range_fmin = ARGS.tuning_range_fmin
|
||||
ModemParam.tuning_range_fmax = ARGS.tuning_range_fmax
|
||||
AudioParam.tx_audio_level = ARGS.tx_audio_level
|
||||
AudioParam.rx_audio_level = ARGS.rx_audio_level
|
||||
Modem.respond_to_cq = ARGS.enable_respond_to_cq
|
||||
ARQ.rx_buffer_size = ARGS.rx_buffer_size
|
||||
Modem.enable_explorer = ARGS.enable_explorer
|
||||
|
@ -367,7 +375,8 @@ if __name__ == "__main__":
|
|||
Modem.low_bandwidth_mode = conf.get('Modem', 'narrowband', 'False')
|
||||
ModemParam.tuning_range_fmin = float(conf.get('Modem', 'fmin', '-50.0'))
|
||||
ModemParam.tuning_range_fmax = float(conf.get('Modem', 'fmax', '50.0'))
|
||||
AudioParam.tx_audio_level = int(conf.get('AUDIO', 'txaudiolevel', '100'))
|
||||
AudioParam.tx_audio_level = int(conf.get('AUDIO', 'txaudiolevel', '0'))
|
||||
AudioParam.rx_audio_level = int(conf.get('AUDIO', 'rxaudiolevel', '0'))
|
||||
Modem.respond_to_cq = conf.get('Modem', 'qrv', 'True')
|
||||
ARQ.rx_buffer_size = int(conf.get('Modem', 'rx_buffer_size', '16'))
|
||||
Modem.enable_explorer = conf.get('Modem', 'explorer', 'False')
|
||||
|
|
|
@ -16,19 +16,16 @@ import sys
|
|||
import threading
|
||||
import time
|
||||
from collections import deque
|
||||
import wave
|
||||
import codec2
|
||||
import itertools
|
||||
import numpy as np
|
||||
import sock
|
||||
import sounddevice as sd
|
||||
import static
|
||||
from global_instances import ARQ, AudioParam, Beacon, Channel, Daemon, HamlibParam, ModemParam, Station, Statistics, TCIParam, Modem
|
||||
from static import FRAME_TYPE
|
||||
import structlog
|
||||
import ujson as json
|
||||
import tci
|
||||
# FIXME used for def transmit_morse
|
||||
import cw
|
||||
from queues import DATA_QUEUE_RECEIVED, MODEM_RECEIVED_QUEUE, MODEM_TRANSMIT_QUEUE, RIGCTLD_COMMAND_QUEUE, \
|
||||
AUDIO_RECEIVED_QUEUE, AUDIO_TRANSMIT_QUEUE, MESH_RECEIVED_QUEUE
|
||||
|
@ -462,6 +459,7 @@ class RF:
|
|||
# self.log.debug("[MDM] callback")
|
||||
x = np.frombuffer(data_in48k, dtype=np.int16)
|
||||
x = self.resampler.resample48_to_8(x)
|
||||
x = set_audio_volume(x, AudioParam.rx_audio_level)
|
||||
|
||||
# audio recording for debugging purposes
|
||||
if AudioParam.audio_record:
|
||||
|
@ -815,7 +813,6 @@ class RF:
|
|||
# self.log.debug("[MDM] mod out shorter than audio buffer", delta=delta)
|
||||
self.modoutqueue.append(c)
|
||||
|
||||
|
||||
def demodulate_audio(
|
||||
self,
|
||||
audiobuffer: codec2.audio_buffer,
|
||||
|
@ -848,7 +845,6 @@ class RF:
|
|||
:rtype: int
|
||||
"""
|
||||
|
||||
|
||||
nbytes = 0
|
||||
try:
|
||||
while self.stream.active:
|
||||
|
@ -874,7 +870,7 @@ class RF:
|
|||
if not ModemParam.channel_busy:
|
||||
self.log.debug("[MDM] Setting channel_busy since codec2 data detected")
|
||||
ModemParam.channel_busy=True
|
||||
ModemParam.channel_busy_delay+=10
|
||||
ModemParam.channel_busy_delay += 10
|
||||
self.log.debug(
|
||||
"[MDM] [demod_audio] modem state", mode=mode_name, rx_status=rx_status,
|
||||
sync_flag=codec2.api.rx_sync_flags_to_text[rx_status]
|
||||
|
@ -883,8 +879,6 @@ class RF:
|
|||
ModemParam.is_codec2_traffic = False
|
||||
|
||||
# decrement codec traffic counter for making state smoother
|
||||
|
||||
print(f"{mode_name}: {self.is_codec2_traffic_counter}")
|
||||
if self.is_codec2_traffic_counter > 0:
|
||||
self.is_codec2_traffic_counter -= 1
|
||||
ModemParam.is_codec2_traffic = True
|
||||
|
@ -902,7 +896,6 @@ class RF:
|
|||
# process commands only if Modem.listen = True
|
||||
if Modem.listen:
|
||||
|
||||
|
||||
# ignore data channel opener frames for avoiding toggle states
|
||||
# use case: opener already received, but ack got lost and we are receiving
|
||||
# an opener again
|
||||
|
@ -1144,7 +1137,7 @@ class RF:
|
|||
def get_scatter(self, freedv: ctypes.c_void_p) -> None:
|
||||
"""
|
||||
Ask codec2 for data about the received signal and calculate the scatter plot.
|
||||
Side-effect: sets ModemParam.scatter
|
||||
Side effect: sets ModemParam.scatter
|
||||
|
||||
:param freedv: codec2 instance to query
|
||||
:type freedv: ctypes.c_void_p
|
||||
|
@ -1186,7 +1179,7 @@ class RF:
|
|||
"""
|
||||
Ask codec2 for data about the received signal and calculate
|
||||
the signal-to-noise ratio.
|
||||
Side-effect: sets ModemParam.snr
|
||||
Side effect: sets ModemParam.snr
|
||||
|
||||
:param freedv: codec2 instance to query
|
||||
:type freedv: ctypes.c_void_p
|
||||
|
@ -1232,7 +1225,7 @@ class RF:
|
|||
def update_rig_data(self) -> None:
|
||||
"""
|
||||
Request information about the current state of the radio via hamlib
|
||||
Side-effect: sets
|
||||
Side effect: sets
|
||||
- HamlibParam.hamlib_frequency
|
||||
- HamlibParam.hamlib_mode
|
||||
- HamlibParam.hamlib_bandwidth
|
||||
|
@ -1263,6 +1256,7 @@ class RF:
|
|||
e=e,
|
||||
)
|
||||
threading.Event().wait(1)
|
||||
|
||||
def calculate_fft(self) -> None:
|
||||
"""
|
||||
Calculate an average signal strength of the channel to assess
|
||||
|
@ -1465,31 +1459,39 @@ def get_bytes_per_frame(mode: int) -> int:
|
|||
# get number of bytes per frame for mode
|
||||
return int(codec2.api.freedv_get_bits_per_modem_frame(freedv) / 8)
|
||||
|
||||
|
||||
def set_audio_volume(datalist, volume: float) -> np.int16:
|
||||
def set_audio_volume(datalist: np.ndarray, dB: float) -> np.ndarray:
|
||||
"""
|
||||
Scale values for the provided audio samples by volume,
|
||||
`volume` is clipped to the range of 0-200
|
||||
Scale values for the provided audio samples by dB.
|
||||
|
||||
:param datalist: Audio samples to scale
|
||||
:type datalist: NDArray[np.int16]
|
||||
:param volume: "Percentage" (0-200) to scale samples
|
||||
:type volume: float
|
||||
:type datalist: np.ndarray
|
||||
:param dB: Decibels to scale samples, constrained to the range [-50, 50]
|
||||
:type dB: float
|
||||
:return: Scaled audio samples
|
||||
:rtype: np.int16
|
||||
:rtype: np.ndarray
|
||||
"""
|
||||
# make sure we have float as data type to avoid crash
|
||||
try:
|
||||
volume = float(volume)
|
||||
except Exception as e:
|
||||
print(f"[MDM] changing audio volume failed with error: {e}")
|
||||
volume = 100.0
|
||||
dB = float(dB)
|
||||
except ValueError as e:
|
||||
print(f"[MDM] Changing audio volume failed with error: {e}")
|
||||
dB = 0.0 # 0 dB means no change
|
||||
|
||||
# Clip volume provided to acceptable values
|
||||
volume = np.clip(volume, 0, 200) # limit to max value of 255
|
||||
# Scale samples by the ratio of volume / 100.0
|
||||
data = np.fromstring(datalist, np.int16) * (volume / 100.0) # type: ignore
|
||||
return data.astype(np.int16)
|
||||
# Clip dB value to the range [-50, 50]
|
||||
dB = np.clip(dB, -30, 20)
|
||||
|
||||
# Ensure datalist is an np.ndarray
|
||||
if not isinstance(datalist, np.ndarray):
|
||||
print("[MDM] Invalid data type for datalist. Expected np.ndarray.")
|
||||
return datalist
|
||||
|
||||
# Convert dB to linear scale
|
||||
scale_factor = 10 ** (dB / 20)
|
||||
|
||||
# Scale samples
|
||||
scaled_data = datalist * scale_factor
|
||||
|
||||
# Clip values to int16 range and convert data type
|
||||
return np.clip(scaled_data, -32768, 32767).astype(np.int16)
|
||||
|
||||
|
||||
def get_modem_error_state():
|
||||
|
|
|
@ -256,6 +256,12 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
else:
|
||||
self.modem_set_tx_audio_level(received_json)
|
||||
|
||||
# SET RX AUDIO LEVEL
|
||||
if received_json["type"] == "set" and received_json["command"] == "rx_audio_level":
|
||||
if TESTMODE:
|
||||
ThreadedTCPRequestHandler.modem_set_rx_audio_level(None, received_json)
|
||||
else:
|
||||
self.modem_set_rx_audio_level(received_json)
|
||||
|
||||
# TRANSMIT TEST FRAME
|
||||
if received_json["type"] == "set" and received_json["command"] == "send_test_frame":
|
||||
|
@ -493,6 +499,18 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
|||
command=received_json,
|
||||
)
|
||||
|
||||
def modem_set_rx_audio_level(self, received_json):
|
||||
try:
|
||||
AudioParam.rx_audio_level = int(received_json["value"])
|
||||
command_response("rx_audio_level", True)
|
||||
|
||||
except Exception as err:
|
||||
command_response("rx_audio_level", False)
|
||||
log.warning(
|
||||
"[SCK] TX audio command execution error",
|
||||
e=err,
|
||||
command=received_json,
|
||||
)
|
||||
def modem_set_send_test_frame(self, received_json):
|
||||
try:
|
||||
DATA_QUEUE_TRANSMIT.put(["SEND_TEST_FRAME"])
|
||||
|
|
|
@ -50,7 +50,8 @@ class ARQ:
|
|||
|
||||
@dataclass
|
||||
class AudioParam:
|
||||
tx_audio_level: int = 50
|
||||
tx_audio_level: int = 0
|
||||
rx_audio_level: int = 0
|
||||
audio_input_devices = []
|
||||
audio_output_devices = []
|
||||
audio_input_device: int = -2
|
||||
|
|
Loading…
Reference in a new issue