Compare commits

...

5 Commits

18 changed files with 301 additions and 249 deletions

21
bin/aqua.cfg Normal file
View File

@ -0,0 +1,21 @@
AQuA:
mode: files
# src: file test_audio/jane_8k.wav
# tstf: test_audio/jane_8k_40.wav
avlp: off
smtnrm: off
decor: off
mprio: off
acr: auto
npnt: auto
voip: on
enorm: rms
g711: off
spfrcor: on
grad: off
tmc: on
miter: 1
ratem: "%%m"
trim: "r 15"
output: json

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
This pjsua requires 10.14 at least!

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,226 +1,232 @@
BOF Common Common:
IntervalLength = 0.68 IntervalLength: 0.68
IsUseUncertain = false IsUseUncertain: no
IsUseMixMode = true IsUseMixMode: yes
IsUseDistance = false IsUseDistance: no
AllWeight = 1.0 AllWeight: 1.0
SilWeight = 1 SilWeight: 1.0
VoiWeight = 1 VoiWeight: 1.0
AllCoefficient = 1.0 AllCoefficient: 1.0
SilCoefficient = 1.0 SilCoefficient: 1.0
VoiCoefficient = 1.0 VoiCoefficient: 1.0
SilThreshold = -37.50 SilThreshold: -37.50
IsOnePointSil = false IsOnePointSil: no
IsNormResult = true IsNormResult: yes
IsMapScore = true IsMapScore: yes
EOF Common NormalizeByRms: yes
BOF Detector SilenceEraser:
Name = SNR Enabled: no
DetectorType = SNR Options:
IntThresh = 0.10
FrameThresh = 14
DetThresh = 0.10
PVQA-Flag = true
PVQA-Weight = 1.0
DetMode = Both
EOF Detector
BOF Detector Detector:
Name = DeadAir-00 - Name: SNR
DetectorType = DeadAir DetectorType: SNR
IntThresh = 0.60 IntThresh: 0.10
DetThresh = 0.60 FrameThresh: 14
PVQA-Flag = true DetThresh: 0.10
PVQA-Weight = 1.0 PVQA-Flag: yes
DetMode = Both PVQA-Weight: 1.0
EOF Detector DetMode: both
BOF Detector - Name: Noise
Name = DeadAir-01 DetectorType: Noise
DetectorType = DeadAir IntThresh: 0.99
IntThresh = 0.5 DetThresh: 0.99
DetThresh = 0.5 # This is still experimental detector so its values are not participating in MOS calculation
PVQA-Flag = true PVQA-Flag: false
PVQA-Weight = 1.0 PVQA-Weight: 1.0
DetMode = Both DetMode: both
EOF Detector
BOF Detector - Name: DTMF
Name = Click DetectorType: DTMF
DetectorType = Clicking IntThresh: 0.99
IntThresh = 0.10 DetThresh: 0.99
DetThresh = 0.10
PVQA-Flag = true
PVQA-Weight = 1.0
DetMode = Both
EOF Detector
BOF Detector # There is no sense to use detected DTMF signal in MOS calculation in the current config
Name = VAD-Clipping PVQA-Flag: no
DetectorType = VADClipping PVQA-Weight: 0.0
IntThresh = 0.0 DetMode: both
FrameThresh = 0.0
DetThresh = 0.0
PVQA-Flag = true
PVQA-Weight = 1.0
DetMode = Both
EOF Detector
BOF Detector - Name: DeadAir-00
Name = Amplitude-Clipping DetectorType: DeadAir
DetectorType = AmpClipping IntThresh: 0.60
IntThresh = 0.00 DetThresh: 0.60
FrameThresh = 1.00 PVQA-Flag: true
DetThresh = 0.00 PVQA-Weight: 1.0
PVQA-Flag = true DetMode: both
PVQA-Weight = 1.00
DetMode = Both
EOF Detector
BOF Detector - Name: DeadAir-01
Name = Dynamic-Clipping DetectorType: DeadAir
DetectorType = AmpClipping IntThresh: 0.5
IntThresh = 0.05 DetThresh: 0.5
FrameThresh = 1.50 PVQA-Flag: yes
DetThresh = 0 PVQA-Weight: 1.0
PVQA-Flag = true DetMode: both
PVQA-Weight = 0.0 Override:
DetMode = Voice MinLevelThreshold: 0
EOF Detector
BOF Base EchoMono - Name: Click
SamplesType = UnKnownCodec DetectorType: Clicking
StepLengthSec = 0.5 IntThresh: 0.10
MinDelayMs = 50 DetThresh: 0.10
MaxLengthMs = 2800 PVQA-Flag: true
WindowFunckID = 0 PVQA-Weight: 1.0
SpanLengthMs = 50 DetMode: both
EOF Base EchoMono
BOF Detector - Name: VAD-Clipping
Name = ECHO DetectorType: VADClipping
DetectorType = EchoMono IntThresh: 0.0
IntThresh = 0.00 FrameThresh: 0.0
FrameThresh = -40.0 DetThresh: 0.0
DetThresh = 0.00 PVQA-Flag: true
PVQA-Flag = true PVQA-Weight: 1.0
PVQA-Weight = 1.0 DetMode: both
DetMode = Voice
STAT-Flag = true
SpanLengthMs = 50
EOF Detector
BOF Detector - Name: AmpClipping
Name = Silent-Call-Detection DetectorType: AmpClipping
DetectorType = DeadAir IntThresh: 0.00
IntThresh = 0.99 FrameThresh: 1.00
DetThresh = 0.99 DetThresh: 0.00
PVQA-Flag = false PVQA-Flag: true
PVQA-Weight = 1.0 PVQA-Weight: 1.00
EOF Detector DetMode: both
BOF Base SNR - Name: DynClipping
MinPowerThresh = 1.0000 DetectorType: AmpClipping
LogEnergyCoefficient = 10.0000 IntThresh: 0.05
MinSignalLevel = 40.0000 FrameThresh: 1.50
MinSNRDelta = 0.0001 DetThresh: 0
MinEnergyDisp = 3.0000 PVQA-Flag: true
MinEnergyDelta = 1.0000 PVQA-Weight: 0.0
SamplesType = UnKnownCodec DetMode: voice
EOF Base SNR Override:
FlyAddingCoefficient: 0.1000
SamplesType: UnKnownCodec
IsUseDynamicClipping: yes
BOF Base AmpClipping - Name: Echo
FlyAddingCoefficient = 0.1000 DetectorType: EchoMono
IsUseDynamicClipping = false IntThresh: 0.00
SamplesType = UnKnownCodec FrameThresh: -40.0
EOF Base AmpClipping DetThresh: 0.00
PVQA-Flag: true
PVQA-Weight: 1.0
DetMode: voice
STAT-Flag: true
SpanLengthMs: 50
BOF Base Clicking - Name: SilentCall
SamplesType = UnKnownCodec DetectorType: DeadAir
EOF Base Clicking IntThresh: 0.99
DetThresh: 0.99
PVQA-Flag: false
PVQA-Weight: 1.0
Override:
MinLevelThreshold: 0
IsUseRMSPower: yes
MinRMSThreshold: -70
BOF Base DeadAir
StuckDeltaThreshold = 6
MinNonStuckTime = 80
MinStuckTime = 80
MinStartNonStuckTime = 1920
MinLevelThreshold = 256
SamplesType = UnKnownCodec
EOF Base DeadAir
BOF Base VADClipping
SamplesType = UnKnownCodec
EOF Base VADClipping
BOF DeadAir-01 Base EchoMono:
MinLevelThreshold = 0 SamplesType: UnKnownCodec
EOF DeadAir-01 StepLengthSec: 0.5
MinDelayMs: 50
MaxLengthMs: 2800
WindowFunckID: 0
SpanLengthMs: 50
BOF Silent-Call-Detection Base SNR:
MinLevelThreshold = 0 MinPowerThresh: 1.0000
IsUseRMSPower = true LogEnergyCoefficient: 10.0000
MinRMSThreshold = -70 MinSignalLevel: 40.0000
EOF Silent-Call-Detection MinSNRDelta: 0.0001
MinEnergyDisp: 3.0000
MinEnergyDelta: 1.0000
SamplesType: UnKnownCodec
BOF Dynamic-Clipping Base DTMF:
FlyAddingCoefficient = 0.1000 SamplesType: UnKnownCodec
SamplesType = UnKnownCodec
IsUseDynamicClipping = true
EOF Dynamic-Clipping
BOF Correction Base AmpClipping:
IntStart = 5.0 FlyAddingCoefficient: 0.1000
IntEnd = 4.2 IsUseDynamicClipping: no
Mult = 1.0 SamplesType: UnKnownCodec
#Shift = -1.7
Shift = 0
EOF Correction
BOF Correction Base Clicking:
IntStart = 4.2 SamplesType: UnKnownCodec
IntEnd = 3.5
Mult = 1.0
#Shift = -0.85
Shift = 0
EOF Correction
BOF SR Correction Base DeadAir:
SampleRate = 11000.0 StuckDeltaThreshold: 6
Shift = 0.05 MinNonStuckTime: 80
EOF SR Correction MinStuckTime: 80
MinStartNonStuckTime: 1920
MinLevelThreshold: 256
SamplesType: UnKnownCodec
BOF SR Correction Base VADClipping:
SampleRate = 16000.0 SamplesType: UnKnownCodec
Shift = 0.1
EOF SR Correction
BOF SR Correction Base Noise:
SampleRate = 22000.0 Interval: 0.1 # Seconds
Shift = 0.2 DetectorType: RMS # This can be FFT as well
EOF SR Correction NoiseThreshold: 20
SignalThreshold: 80
Normalize: no
RemoveBias: no
ResultDb: yes
WindowType: Hann
WindowWidth: 3
BOF SR Correction # Moved to Override: sections
SampleRate = 32000.0 # DeadAir-01:
Shift = 0.3 # MinLevelThreshold: 0
EOF SR Correction
BOF SR Correction # SilentCall:
SampleRate = 48000.0 # MinLevelThreshold: 0
Shift = 0.45 # IsUseRMSPower: yes
EOF SR Correction # MinRMSThreshold: -70
BOF SR Correction # Dynamic-Clipping:
SampleRate = 96000.0 # FlyAddingCoefficient: 0.1000
Shift = 0.5 # SamplesType: UnKnownCodec
EOF SR Correction # IsUseDynamicClipping: yes
BOF SR Correction Correction:
SampleRate = 192000.0 - IntStart: 5.0
Shift = 0.6 IntEnd: 4.2
EOF SR Correction Mult: 1.0
Shift: 0
BOF Scores Map - IntStart: 4.2
ScoresLine = 4;3.027000;2.935000;2.905000;2.818000;2.590000;2.432000;2.310000;1.665000;1.000000; IntEnd: 3.5
EOF Scores Map Mult: 1.0
Shift: 0
SR Correction:
- SampleRate: 11000.0
Shift: 0.05
- SampleRate: 16000.0
Shift: 0.1
- SampleRate: 22000.0
Shift: 0.2
- SampleRate: 32000.0
Shift: 0.3
- SampleRate: 48000.0
Shift: 0.45
- SampleRate: 96000.0
Shift: 0.5
- SampleRate: 192000.0
Shift: 0.6
Scores Map:
ScoresLine: 4;3.027000;2.935000;2.905000;2.818000;2.590000;2.432000;2.310000;1.665000;1.000000;

Binary file not shown.

Binary file not shown.

View File

@ -36,8 +36,8 @@ class AgentConfig:
# Should the first task run immediately ? # Should the first task run immediately ?
ForceRun = False ForceRun = False
# Use silence eraser or not (speech detector is used in this case) # Use external speech detector if needed
UseSilenceEraser = True UseSpeechDetector = False
# Path to log file # Path to log file
LogPath : Path = None LogPath : Path = None
@ -90,7 +90,7 @@ class AgentConfig:
if 'speech_detector' in config: if 'speech_detector' in config:
if config['speech_detector']: if config['speech_detector']:
self.UseSilenceEraser = False self.UseSpeechDetector = True
if 'audio' in config: if 'audio' in config:
audio = config['audio'] audio = config['audio']

View File

@ -68,7 +68,10 @@ def detect_degraded_signal(file_test: Path, file_reference: Path) -> SignalBound
# Seems some problem with recording, return zero boundaries # Seems some problem with recording, return zero boundaries
return SignalBoundaries() return SignalBoundaries()
r = bt_signal.find_reference_signal(file_test) if CONFIG.UseSpeechDetector:
r = bt_signal.find_reference_signal_via_speechdetector(file_test)
else:
r = bt_signal.find_reference_signal(file_test)
if r.offset_start == 0.0 and is_caller: if r.offset_start == 0.0 and is_caller:
r.offset_start = 5.0 # Skip ringing tones r.offset_start = 5.0 # Skip ringing tones
@ -78,7 +81,10 @@ def detect_degraded_signal(file_test: Path, file_reference: Path) -> SignalBound
def detect_reference_signal(file_reference: Path) -> SignalBoundaries: def detect_reference_signal(file_reference: Path) -> SignalBoundaries:
# Run silence eraser on reference file as well # Run silence eraser on reference file as well
result = bt_signal.find_reference_signal(file_reference) if CONFIG.UseSpeechDetector:
result = bt_signal.find_reference_signal_via_speechdetector(file_reference)
else:
result = bt_signal.find_reference_signal(file_reference)
return result return result
@ -146,17 +152,20 @@ def run_analyze(file_test: str, file_reference: str, number: str) -> bool:
return False return False
try: try:
bounds_signal : SignalBoundaries = detect_degraded_signal(Path(file_test), Path(file_reference)) bounds_signal = SignalBoundaries()
# bounds_signal.offset_start = 0 if is_caller:
# bounds_signal.offset_finish = 0 bounds_signal.offset_start = 10.0 # Skip ringtones
print(f'Found signal bounds: {bounds_signal}') bounds_signal.offset_finish = 1.0 # Eat possible end tone
elif is_answerer:
bounds_signal.offset_start = 0.0
bounds_signal.offset_finish = 1.0 # Eat possible end tone
# PVQA report # PVQA report
pvqa_mos, pvqa_report, pvqa_rfactor = utils_sevana.find_pvqa_mos(file_test, bounds_signal.offset_start, bounds_signal.offset_finish) pvqa_mos, pvqa_report, pvqa_rfactor = utils_sevana.find_pvqa_mos(file_test, bounds_signal.offset_start, bounds_signal.offset_finish)
utils.log(f'PVQA MOS: {pvqa_mos}, PVQA R-factor: {pvqa_rfactor}') utils.log(f'PVQA MOS: {pvqa_mos}, PVQA R-factor: {pvqa_rfactor}')
# AQuA report # AQuA report
bounds_reference : SignalBoundaries = detect_reference_signal(Path(file_reference)) bounds_reference : SignalBoundaries = SignalBoundaries()
bounds_reference.offset_start = 0 bounds_reference.offset_start = 0
bounds_reference.offset_finish = 0 bounds_reference.offset_finish = 0
@ -252,7 +261,7 @@ def make_call(target: str):
timelimit_seconds=ref_time_length, timelimit_seconds=ref_time_length,
target=target) target=target)
run_analyze(CONFIG.RecordFile, CONFIG.ReferenceAudio, target) run_analyze(CONFIG.RecordFile, CONFIG.PreparedReferenceAudio, target)
except Exception as e: except Exception as e:
utils.log_error(f'BT I/O failed finally. Error: {str(e)}') utils.log_error(f'BT I/O failed finally. Error: {str(e)}')
@ -288,7 +297,7 @@ def perform_answerer():
break break
# Call analyzer script # Call analyzer script
run_analyze(CONFIG.RecordFile, CONFIG.ReferenceAudio, '') run_analyze(CONFIG.RecordFile, CONFIG.PreparedReferenceAudio, '')
# Increase counter of attempts # Increase counter of attempts
attempt_idx += 1 attempt_idx += 1

View File

@ -3,33 +3,22 @@
import sys import sys
import os import os
import pathlib import pathlib
from utils_types import SignalBoundaries
from utils_sevana import speech_detector
from pydub import silence, AudioSegment from pydub import silence, AudioSegment
class SignalBoundaries: SILENCE_DELTA = 16
# Offset from start (in seconds)
offset_start: float
# Offset from finish (in seconds)
offset_finish: float
def __init__(self, offset_start = 0.0, offset_finish = 0.0) -> None:
self.offset_start = offset_start
self.offset_finish = offset_finish
def __repr__(self) -> str:
return f'[offset_start: {round(self.offset_start, 3)}, offset_finish : {round(self.offset_finish, 3)}]'
def find_reference_signal(input_file: pathlib.Path, output_file: pathlib.Path = None, use_end_offset: bool = True) -> SignalBoundaries: def find_reference_signal(input_file: pathlib.Path, output_file: pathlib.Path = None, use_end_offset: bool = True) -> SignalBoundaries:
myaudio = AudioSegment.from_wav(str(input_file)) myaudio = AudioSegment.from_wav(str(input_file))
dBFS = myaudio.dBFS dBFS = myaudio.dBFS
# Find silence intervals # Find silence intervals
intervals = silence.detect_nonsilent(myaudio, min_silence_len=1000, silence_thresh=dBFS-17, seek_step=50) intervals = silence.detect_nonsilent(myaudio, min_silence_len=1000, silence_thresh=dBFS-SILENCE_DELTA, seek_step=50)
# Translate to seconds # Translate to seconds
intervals = [((start/1000),(stop/1000)) for start,stop in intervals] #in sec intervals = [((start/1000),(stop/1000)) for start,stop in intervals] # in sec
# print(intervals) # print(intervals)
@ -48,6 +37,12 @@ def find_reference_signal(input_file: pathlib.Path, output_file: pathlib.Path =
return SignalBoundaries() return SignalBoundaries()
def find_reference_signal_via_speechdetector(input_file: pathlib.Path) -> SignalBoundaries:
bounds = speech_detector(str(input_file))
r = SignalBoundaries(bounds[0], bounds[1])
return bounds
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) < 2: if len(sys.argv) < 2:
print(f'Please specify input filename.') print(f'Please specify input filename.')

View File

@ -12,8 +12,6 @@ import time
import urllib import urllib
from pathlib import Path from pathlib import Path
from colorama import Fore, Style
from utils_cache import InfoCache
PVQA_CMD = "{pvqa} --license {pvqa_lic} --config {pvqa_cfg} --mode analysis --channel 0 " \ PVQA_CMD = "{pvqa} --license {pvqa_lic} --config {pvqa_cfg} --mode analysis --channel 0 " \
"--report {output} --input {input} --cut-begin {cut_begin} --cut-end {cut_end}" "--report {output} --input {input} --cut-begin {cut_begin} --cut-end {cut_end}"
@ -21,10 +19,8 @@ PVQA_CMD = "{pvqa} --license {pvqa_lic} --config {pvqa_cfg} --mode analysis --ch
PVQA_CMD_LIC_SERVER = "{pvqa} --license-server {pvqa_lic} --config {pvqa_cfg} --mode analysis --channel 0 " \ PVQA_CMD_LIC_SERVER = "{pvqa} --license-server {pvqa_lic} --config {pvqa_cfg} --mode analysis --channel 0 " \
"--report {output} --input {input}" "--report {output} --input {input}"
AQUA_CMD = ("{aqua} {aqua_lic} -mode files -src file \"{reference}\" -tstf \"{input}\" -avlp off -smtnrm on " AQUA_CMD = ("{aqua} {aqua_lic} -mode files -src file \"{reference}\" -tstf \"{input}\" -config {aqua_config} "
"-decor off -mprio off -acr auto -npnt auto -voip on -enorm rms -g711 off " "-specp 32 {spectrum} -fau {faults} -cut-tst {cut_begin} {cut_end} -cut-src {cut_begin_src} {cut_end_src}")
"-spfrcor on -grad off -tmc on -hist-pitch on on -hist-levels on on on -miter 1 -specp 32 {spectrum} "
"-ratem %%m -fau {faults} -output json -trim r 15 -cut-tst {cut_begin} {cut_end} -cut-src {cut_begin_src} {cut_end_src}")
PVQA_PATH = "" PVQA_PATH = ""
PVQA_LIC_PATH = "pvqa.lic" PVQA_LIC_PATH = "pvqa.lic"
@ -32,6 +28,7 @@ PVQA_CFG_PATH = "pvqa.cfg"
AQUA_PATH = "" AQUA_PATH = ""
AQUA_LIC_PATH = "aqua-wb.lic" AQUA_LIC_PATH = "aqua-wb.lic"
AQUA_CFG_PATH = "aqua.cfg"
SILER_PATH = "" SILER_PATH = ""
@ -78,12 +75,16 @@ def load_config_and_licenses(server: str):
load_file(utils.join_host_and_path(server, '/deploy/pvqa.cfg'), PVQA_CFG_PATH) load_file(utils.join_host_and_path(server, '/deploy/pvqa.cfg'), PVQA_CFG_PATH)
load_file(utils.join_host_and_path(server, '/deploy/pvqa.lic'), PVQA_LIC_PATH) load_file(utils.join_host_and_path(server, '/deploy/pvqa.lic'), PVQA_LIC_PATH)
load_file(utils.join_host_and_path(server, '/deploy/aqua-wb.lic'), AQUA_LIC_PATH) load_file(utils.join_host_and_path(server, '/deploy/aqua-wb.lic'), AQUA_LIC_PATH)
load_file(utils.join_host_and_path(server, '/deploy/aqua.cfg'), AQUA_CFG_PATH)
except Exception as e: except Exception as e:
utils.log_error(f'Failed to fetch new licenses and config. Skipping it.') utils.log_error(f'Failed to fetch new licenses and config. Skipping it.')
def find_binaries(bin_directory: Path, license_server: str = None) -> bool: def find_binaries(bin_directory: Path, license_server: str = None) -> bool:
# Update path to pvqa/aqua-wb # Update path to pvqa/aqua-wb
global PVQA_CFG_PATH, PVQA_LIC_PATH, AQUA_LIC_PATH, PVQA_PATH, AQUA_PATH, PVQA_CMD, AQUA_CMD, SILER_PATH, SPEECH_DETECTOR_PATH global PVQA_CFG_PATH, PVQA_LIC_PATH, AQUA_LIC_PATH, AQUA_CFG_PATH
global PVQA_PATH, AQUA_PATH, PVQA_CMD, AQUA_CMD
global SILER_PATH, SPEECH_DETECTOR_PATH
# Find platform prefix # Find platform prefix
platform_prefix = platform.system().lower() platform_prefix = platform.system().lower()
@ -94,8 +95,9 @@ def find_binaries(bin_directory: Path, license_server: str = None) -> bool:
PVQA_LIC_PATH = bin_directory / PVQA_LIC_PATH PVQA_LIC_PATH = bin_directory / PVQA_LIC_PATH
PVQA_CFG_PATH = bin_directory / PVQA_CFG_PATH PVQA_CFG_PATH = bin_directory / PVQA_CFG_PATH
AQUA_PATH = bin_directory / platform_prefix / AQUA_PATH AQUA_PATH = bin_directory / platform_prefix / AQUA_PATH
AQUA_CFG_PATH = bin_directory / AQUA_CFG_PATH
AQUA_LIC_PATH = bin_directory / AQUA_LIC_PATH AQUA_LIC_PATH = bin_directory / AQUA_LIC_PATH
SILER_PATH = bin_directory / platform_prefix / SILER_PATH # SILER_PATH = bin_directory / platform_prefix / SILER_PATH
SPEECH_DETECTOR_PATH = bin_directory / platform_prefix / SPEECH_DETECTOR_PATH SPEECH_DETECTOR_PATH = bin_directory / platform_prefix / SPEECH_DETECTOR_PATH
utils.log(f'Looking for binaries/licenses/configs at {bin_directory}...') utils.log(f'Looking for binaries/licenses/configs at {bin_directory}...')
@ -109,16 +111,23 @@ def find_binaries(bin_directory: Path, license_server: str = None) -> bool:
PVQA_CFG_PATH = Path(utils.get_script_path()) / 'pvqa.cfg' PVQA_CFG_PATH = Path(utils.get_script_path()) / 'pvqa.cfg'
if not PVQA_CFG_PATH.exists(): if not PVQA_CFG_PATH.exists():
utils.log_error(f'Failed to find pvqa config.') utils.log_error(f'Failed to find PVQA config file.')
return False
if not AQUA_CFG_PATH.exists():
AQUA_CFG_PATH = Path(utils.get_script_path()) / 'aqua.cfg'
if not AQUA_CFG_PATH.exists():
utils.log_error(f'Failed to find AQuA config file.')
return False return False
if not AQUA_PATH.exists(): if not AQUA_PATH.exists():
utils.log_error(f'Failed to find aqua-wb binary.') utils.log_error(f'Failed to find aqua-wb binary.')
return False return False
if not SILER_PATH.exists(): # if not SILER_PATH.exists():
utils.log_error(f'Failed to find silence_eraser binary..') # utils.log_error(f'Failed to find silence_eraser binary..')
return False # return False
if license_server is not None: if license_server is not None:
AQUA_LIC_PATH = '"license://' + license_server + '"' AQUA_LIC_PATH = '"license://' + license_server + '"'
@ -238,7 +247,7 @@ def find_aqua_mos(good_path, test_path, test_file_offset_begin: float = 0.0, tes
good_file_offset_begin: float = 0.0, good_file_offset_end: float = 0.0): good_file_offset_begin: float = 0.0, good_file_offset_end: float = 0.0):
try: try:
out_data = "" out_data = ""
cmd = AQUA_CMD.format(aqua=AQUA_PATH, aqua_lic=AQUA_LIC_PATH, cmd = AQUA_CMD.format(aqua=AQUA_PATH, aqua_lic=AQUA_LIC_PATH, aqua_config = AQUA_CFG_PATH,
reference=good_path, input=test_path, spectrum=AQUA_SPECTRUM, reference=good_path, input=test_path, spectrum=AQUA_SPECTRUM,
faults=AQUA_FAULTS, faults=AQUA_FAULTS,
cut_begin=int(test_file_offset_begin * 1000), cut_end=int(test_file_offset_end * 1000), cut_begin=int(test_file_offset_begin * 1000), cut_end=int(test_file_offset_end * 1000),

View File

@ -6,12 +6,25 @@ import utils
import json import json
from crontab import CronTab from crontab import CronTab
# Exit codes # Exit codes
EXIT_OK = 0 EXIT_OK = 0
EXIT_ERROR = 1 EXIT_ERROR = 1
class SignalBoundaries:
# Offset from start (in seconds)
offset_start: float
# Offset from finish (in seconds)
offset_finish: float
def __init__(self, offset_start = 0.0, offset_finish = 0.0) -> None:
self.offset_start = offset_start
self.offset_finish = offset_finish
def __repr__(self) -> str:
return f'[offset_start: {round(self.offset_start, 3)}, offset_finish : {round(self.offset_finish, 3)}]'
class Phone: class Phone:
identifier: int = 0 identifier: int = 0
name: str = "" name: str = ""