sonusai 1.0.11__tar.gz → 1.0.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sonusai-1.0.11 → sonusai-1.0.13}/PKG-INFO +1 -1
- {sonusai-1.0.11 → sonusai-1.0.13}/pyproject.toml +1 -1
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/genmetrics.py +4 -6
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/__init__.py +1 -0
- sonusai-1.0.13/sonusai/metrics/calculate_metrics.py +395 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/mixdb.py +22 -551
- {sonusai-1.0.11 → sonusai-1.0.13}/README.rst +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/aawscd_probwrite.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/audiofe.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/calc_metric_spenh.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/config/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/config/config.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/config/config.yml +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/config/constants.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/constants.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/genmixdb.yml +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/silero_vad_v5.1.jit +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/silero_vad_v5.1.onnx +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/speech_ma01_01.wav +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/data/whitenoise.wav +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/datatypes.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/deprecated/gentcst.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/deprecated/plot.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/deprecated/tplot.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/doc/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/doc/doc.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/doc.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/genft.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/genmix.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/genmixdb.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/ir_metric.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/lsdb.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/main.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_audio_stats.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_class_weights.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_optimal_thresholds.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_pcm.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_pesq.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_phase_distance.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_sa_sdr.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_sample_weights.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_segsnr_f.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_speech.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_wer.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/calc_wsdr.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/class_summary.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/confusion_matrix_summary.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/one_hot.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics/snr_summary.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/metrics_summary.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/audio.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/class_balancing.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/config.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/constants.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/data_io.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/db.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/db_datatypes.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/effects.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/feature.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/generation.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/helpers.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/ir_delay.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/ir_effects.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/log_duration_and_sizes.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/pad_audio.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/parse.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/resample.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/sox_effects.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/sox_help.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/spectral_mask.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/crm.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/energy.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/file.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/metadata.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/metrics.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/phoneme.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/sed.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mixture/truth_functions/target.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/mkwav.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/onnx_predict.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/queries/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/queries/queries.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/l2arctic.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/librispeech.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/mcgill.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/textgrid.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/timit.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/types.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/vctk.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/speech/voxceleb.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/asl_p56.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/asr.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/asr_functions/__init__.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/asr_functions/aaware_whisper.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/audio_devices.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/braced_glob.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/calculate_input_shape.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/choice.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/compress.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/convert_string_to_number.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/create_timestamp.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/create_ts_name.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/dataclass_from_dict.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/db.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/docstring.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/energy_f.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/engineering_number.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/evaluate_random_rule.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/get_frames_per_batch.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/get_label_names.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/grouper.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/human_readable_size.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/keyboard_interrupt.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/load_object.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/max_text_width.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/model_utils.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/numeric_conversion.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/onnx_utils.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/parallel.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/path_info.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/print_mixture_details.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/rand.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/ranges.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/read_predict_data.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/reshape.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/seconds_to_hms.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/stacked_complex.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/stratified_shuffle_split.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/tokenized_shell_vars.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/write_audio.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/utils/yes_or_no.py +0 -0
- {sonusai-1.0.11 → sonusai-1.0.13}/sonusai/vars.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "sonusai"
|
3
|
-
version = "1.0.
|
3
|
+
version = "1.0.13"
|
4
4
|
description = "Framework for building deep neural network models for sound, speech, and voice AI"
|
5
5
|
authors = ["Chris Eddington <chris@aaware.com>", "Jason Calderwood <jason@aaware.com>"]
|
6
6
|
maintainers = ["Chris Eddington <chris@aaware.com>", "Jason Calderwood <jason@aaware.com>"]
|
@@ -147,12 +147,10 @@ def main() -> None:
|
|
147
147
|
logger.info("")
|
148
148
|
logger.info(f"Found {len(mixids):,} mixtures to process")
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
no_par = False
|
155
|
-
num_proc = int(num_proc) # TBD add support for 'auto'
|
150
|
+
no_par = num_proc == 1 or len(mixids) == 1
|
151
|
+
|
152
|
+
if num_proc is not None:
|
153
|
+
num_proc = int(num_proc)
|
156
154
|
|
157
155
|
progress = track(total=len(mixids), desc="genmetrics")
|
158
156
|
results = par_track(
|
@@ -15,6 +15,7 @@ from .calc_segsnr_f import calc_segsnr_f_bin
|
|
15
15
|
from .calc_speech import calc_speech
|
16
16
|
from .calc_wer import calc_wer
|
17
17
|
from .calc_wsdr import calc_wsdr
|
18
|
+
from .calculate_metrics import calculate_metrics
|
18
19
|
from .class_summary import class_summary
|
19
20
|
from .confusion_matrix_summary import confusion_matrix_summary
|
20
21
|
from .one_hot import one_hot
|
@@ -0,0 +1,395 @@
|
|
1
|
+
import functools
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from pystoi import stoi
|
6
|
+
|
7
|
+
from ..constants import SAMPLE_RATE
|
8
|
+
from ..datatypes import AudioF
|
9
|
+
from ..datatypes import AudioStatsMetrics
|
10
|
+
from ..datatypes import AudioT
|
11
|
+
from ..datatypes import Segsnr
|
12
|
+
from ..datatypes import SpeechMetrics
|
13
|
+
from ..mixture.mixdb import MixtureDatabase
|
14
|
+
from ..utils.asr import calc_asr
|
15
|
+
from ..utils.db import linear_to_db
|
16
|
+
from .calc_audio_stats import calc_audio_stats
|
17
|
+
from .calc_pesq import calc_pesq
|
18
|
+
from .calc_phase_distance import calc_phase_distance
|
19
|
+
from .calc_segsnr_f import calc_segsnr_f
|
20
|
+
from .calc_segsnr_f import calc_segsnr_f_bin
|
21
|
+
from .calc_speech import calc_speech
|
22
|
+
from .calc_wer import calc_wer
|
23
|
+
from .calc_wsdr import calc_wsdr
|
24
|
+
|
25
|
+
|
26
|
+
def calculate_metrics(mixdb: MixtureDatabase, m_id: int, metrics: list[str], force: bool = False) -> dict[str, Any]:
|
27
|
+
"""Get metrics data for the given mixture ID
|
28
|
+
|
29
|
+
:param mixdb: Mixture database object
|
30
|
+
:param m_id: Zero-based mixture ID
|
31
|
+
:param metrics: List of metrics to get
|
32
|
+
:param force: Force computing data from original sources regardless of whether cached data exists
|
33
|
+
:return: Dictionary of metric data
|
34
|
+
"""
|
35
|
+
|
36
|
+
# Define cached functions for expensive operations
|
37
|
+
@functools.lru_cache(maxsize=1)
|
38
|
+
def mixture_sources() -> dict[str, AudioT]:
|
39
|
+
return mixdb.mixture_sources(m_id)
|
40
|
+
|
41
|
+
@functools.lru_cache(maxsize=1)
|
42
|
+
def mixture_source() -> AudioT:
|
43
|
+
return mixdb.mixture_source(m_id)
|
44
|
+
|
45
|
+
@functools.lru_cache(maxsize=1)
|
46
|
+
def mixture_source_f() -> AudioF:
|
47
|
+
return mixdb.mixture_source_f(m_id)
|
48
|
+
|
49
|
+
@functools.lru_cache(maxsize=1)
|
50
|
+
def mixture_noise() -> AudioT:
|
51
|
+
return mixdb.mixture_noise(m_id)
|
52
|
+
|
53
|
+
@functools.lru_cache(maxsize=1)
|
54
|
+
def mixture_noise_f() -> AudioF:
|
55
|
+
return mixdb.mixture_noise_f(m_id)
|
56
|
+
|
57
|
+
@functools.lru_cache(maxsize=1)
|
58
|
+
def mixture_mixture() -> AudioT:
|
59
|
+
return mixdb.mixture_mixture(m_id)
|
60
|
+
|
61
|
+
@functools.lru_cache(maxsize=1)
|
62
|
+
def mixture_mixture_f() -> AudioF:
|
63
|
+
return mixdb.mixture_mixture_f(m_id)
|
64
|
+
|
65
|
+
@functools.lru_cache(maxsize=1)
|
66
|
+
def mixture_segsnr() -> Segsnr:
|
67
|
+
return mixdb.mixture_segsnr(m_id)
|
68
|
+
|
69
|
+
@functools.lru_cache(maxsize=1)
|
70
|
+
def calculate_pesq() -> dict[str, float]:
|
71
|
+
return {category: calc_pesq(mixture_mixture(), audio) for category, audio in mixture_sources().items()}
|
72
|
+
|
73
|
+
@functools.lru_cache(maxsize=1)
|
74
|
+
def calculate_speech() -> dict[str, SpeechMetrics]:
|
75
|
+
return {
|
76
|
+
category: calc_speech(mixture_mixture(), audio, calculate_pesq()[category])
|
77
|
+
for category, audio in mixture_sources().items()
|
78
|
+
}
|
79
|
+
|
80
|
+
@functools.lru_cache(maxsize=1)
|
81
|
+
def mixture_stats() -> AudioStatsMetrics:
|
82
|
+
return calc_audio_stats(mixture_mixture(), mixdb.fg_info.ft_config.length / SAMPLE_RATE)
|
83
|
+
|
84
|
+
@functools.lru_cache(maxsize=1)
|
85
|
+
def sources_stats() -> dict[str, AudioStatsMetrics]:
|
86
|
+
return {
|
87
|
+
category: calc_audio_stats(audio, mixdb.fg_info.ft_config.length / SAMPLE_RATE)
|
88
|
+
for category, audio in mixture_sources().items()
|
89
|
+
}
|
90
|
+
|
91
|
+
@functools.lru_cache(maxsize=1)
|
92
|
+
def source_stats() -> AudioStatsMetrics:
|
93
|
+
return calc_audio_stats(mixture_source(), mixdb.fg_info.ft_config.length / SAMPLE_RATE)
|
94
|
+
|
95
|
+
@functools.lru_cache(maxsize=1)
|
96
|
+
def noise_stats() -> AudioStatsMetrics:
|
97
|
+
return calc_audio_stats(mixture_noise(), mixdb.fg_info.ft_config.length / SAMPLE_RATE)
|
98
|
+
|
99
|
+
# Cache ASR configurations
|
100
|
+
@functools.lru_cache(maxsize=32)
|
101
|
+
def get_asr_config(asr_name: str) -> dict:
|
102
|
+
value = mixdb.asr_configs.get(asr_name, None)
|
103
|
+
if value is None:
|
104
|
+
raise ValueError(f"Unrecognized ASR name: '{asr_name}'")
|
105
|
+
return value
|
106
|
+
|
107
|
+
# Cache ASR results for sources, source and mixture
|
108
|
+
@functools.lru_cache(maxsize=16)
|
109
|
+
def sources_asr(asr_name: str) -> dict[str, str]:
|
110
|
+
return {
|
111
|
+
category: calc_asr(audio, **get_asr_config(asr_name)).text for category, audio in mixture_sources().items()
|
112
|
+
}
|
113
|
+
|
114
|
+
@functools.lru_cache(maxsize=16)
|
115
|
+
def source_asr(asr_name: str) -> str:
|
116
|
+
return calc_asr(mixture_source(), **get_asr_config(asr_name)).text
|
117
|
+
|
118
|
+
@functools.lru_cache(maxsize=16)
|
119
|
+
def mixture_asr(asr_name: str) -> str:
|
120
|
+
return calc_asr(mixture_mixture(), **get_asr_config(asr_name)).text
|
121
|
+
|
122
|
+
def get_asr_name(m: str) -> str:
|
123
|
+
parts = m.split(".")
|
124
|
+
if len(parts) != 2:
|
125
|
+
raise ValueError(f"Unrecognized format: '{m}'; must be of the form: '<metric>.<name>'")
|
126
|
+
asr_name = parts[1]
|
127
|
+
return asr_name
|
128
|
+
|
129
|
+
def calc(m: str) -> Any:
|
130
|
+
if m == "mxsnr":
|
131
|
+
return {category: source.snr for category, source in mixdb.mixture(m_id).all_sources.items()}
|
132
|
+
|
133
|
+
# Get cached data first, if exists
|
134
|
+
if not force:
|
135
|
+
value = mixdb.read_mixture_data(m_id, m)[m]
|
136
|
+
if value is not None:
|
137
|
+
return value
|
138
|
+
|
139
|
+
# Otherwise, generate data as needed
|
140
|
+
if m.startswith("mxwer"):
|
141
|
+
asr_name = get_asr_name(m)
|
142
|
+
|
143
|
+
if mixdb.mixture(m_id).is_noise_only:
|
144
|
+
# noise only, ignore/reset target asr
|
145
|
+
return float("nan")
|
146
|
+
|
147
|
+
if source_asr(asr_name):
|
148
|
+
return calc_wer(mixture_asr(asr_name), source_asr(asr_name)).wer * 100
|
149
|
+
|
150
|
+
# TODO: should this be NaN like above?
|
151
|
+
return float(0)
|
152
|
+
|
153
|
+
if m.startswith("basewer"):
|
154
|
+
asr_name = get_asr_name(m)
|
155
|
+
|
156
|
+
text = mixdb.mixture_speech_metadata(m_id, "text")
|
157
|
+
return {
|
158
|
+
category: calc_wer(source, str(text[category])).wer * 100 if isinstance(text[category], str) else 0
|
159
|
+
for category, source in sources_asr(asr_name).items()
|
160
|
+
}
|
161
|
+
|
162
|
+
if m.startswith("mxasr"):
|
163
|
+
return mixture_asr(get_asr_name(m))
|
164
|
+
|
165
|
+
if m == "mxssnr_avg":
|
166
|
+
return calc_segsnr_f(mixture_segsnr()).avg
|
167
|
+
|
168
|
+
if m == "mxssnr_std":
|
169
|
+
return calc_segsnr_f(mixture_segsnr()).std
|
170
|
+
|
171
|
+
if m == "mxssnr_avg_db":
|
172
|
+
val = calc_segsnr_f(mixture_segsnr()).avg
|
173
|
+
if val is not None:
|
174
|
+
return linear_to_db(val)
|
175
|
+
return None
|
176
|
+
|
177
|
+
if m == "mxssnr_std_db":
|
178
|
+
val = calc_segsnr_f(mixture_segsnr()).std
|
179
|
+
if val is not None:
|
180
|
+
return linear_to_db(val)
|
181
|
+
return None
|
182
|
+
|
183
|
+
if m == "mxssnrdb_avg":
|
184
|
+
return calc_segsnr_f(mixture_segsnr()).db_avg
|
185
|
+
|
186
|
+
if m == "mxssnrdb_std":
|
187
|
+
return calc_segsnr_f(mixture_segsnr()).db_std
|
188
|
+
|
189
|
+
if m == "mxssnrf_avg":
|
190
|
+
return calc_segsnr_f_bin(mixture_source_f(), mixture_noise_f()).avg
|
191
|
+
|
192
|
+
if m == "mxssnrf_std":
|
193
|
+
return calc_segsnr_f_bin(mixture_source_f(), mixture_noise_f()).std
|
194
|
+
|
195
|
+
if m == "mxssnrdbf_avg":
|
196
|
+
return calc_segsnr_f_bin(mixture_source_f(), mixture_noise_f()).db_avg
|
197
|
+
|
198
|
+
if m == "mxssnrdbf_std":
|
199
|
+
return calc_segsnr_f_bin(mixture_source_f(), mixture_noise_f()).db_std
|
200
|
+
|
201
|
+
if m == "mxpesq":
|
202
|
+
if mixdb.mixture(m_id).is_noise_only:
|
203
|
+
return dict.fromkeys(calculate_pesq(), 0)
|
204
|
+
return calculate_pesq()
|
205
|
+
|
206
|
+
if m == "mxcsig":
|
207
|
+
if mixdb.mixture(m_id).is_noise_only:
|
208
|
+
return dict.fromkeys(calculate_speech(), 0)
|
209
|
+
return {category: s.csig for category, s in calculate_speech().items()}
|
210
|
+
|
211
|
+
if m == "mxcbak":
|
212
|
+
if mixdb.mixture(m_id).is_noise_only:
|
213
|
+
return dict.fromkeys(calculate_speech(), 0)
|
214
|
+
return {category: s.cbak for category, s in calculate_speech().items()}
|
215
|
+
|
216
|
+
if m == "mxcovl":
|
217
|
+
if mixdb.mixture(m_id).is_noise_only:
|
218
|
+
return dict.fromkeys(calculate_speech(), 0)
|
219
|
+
return {category: s.covl for category, s in calculate_speech().items()}
|
220
|
+
|
221
|
+
if m == "mxwsdr":
|
222
|
+
mixture = mixture_mixture()[:, np.newaxis]
|
223
|
+
target = mixture_source()[:, np.newaxis]
|
224
|
+
noise = mixture_noise()[:, np.newaxis]
|
225
|
+
return calc_wsdr(
|
226
|
+
hypothesis=np.concatenate((mixture, noise), axis=1),
|
227
|
+
reference=np.concatenate((target, noise), axis=1),
|
228
|
+
with_log=True,
|
229
|
+
)[0]
|
230
|
+
|
231
|
+
if m == "mxpd":
|
232
|
+
return calc_phase_distance(hypothesis=mixture_mixture_f(), reference=mixture_source_f())[0]
|
233
|
+
|
234
|
+
if m == "mxstoi":
|
235
|
+
return stoi(
|
236
|
+
x=mixture_source(),
|
237
|
+
y=mixture_mixture(),
|
238
|
+
fs_sig=SAMPLE_RATE,
|
239
|
+
extended=False,
|
240
|
+
)
|
241
|
+
|
242
|
+
if m == "mxdco":
|
243
|
+
return mixture_stats().dco
|
244
|
+
|
245
|
+
if m == "mxmin":
|
246
|
+
return mixture_stats().min
|
247
|
+
|
248
|
+
if m == "mxmax":
|
249
|
+
return mixture_stats().max
|
250
|
+
|
251
|
+
if m == "mxpkdb":
|
252
|
+
return mixture_stats().pkdb
|
253
|
+
|
254
|
+
if m == "mxlrms":
|
255
|
+
return mixture_stats().lrms
|
256
|
+
|
257
|
+
if m == "mxpkr":
|
258
|
+
return mixture_stats().pkr
|
259
|
+
|
260
|
+
if m == "mxtr":
|
261
|
+
return mixture_stats().tr
|
262
|
+
|
263
|
+
if m == "mxcr":
|
264
|
+
return mixture_stats().cr
|
265
|
+
|
266
|
+
if m == "mxfl":
|
267
|
+
return mixture_stats().fl
|
268
|
+
|
269
|
+
if m == "mxpkc":
|
270
|
+
return mixture_stats().pkc
|
271
|
+
|
272
|
+
if m == "sdco":
|
273
|
+
return {category: s.dco for category, s in sources_stats().items()}
|
274
|
+
|
275
|
+
if m == "smin":
|
276
|
+
return {category: s.min for category, s in sources_stats().items()}
|
277
|
+
|
278
|
+
if m == "smax":
|
279
|
+
return {category: s.max for category, s in sources_stats().items()}
|
280
|
+
|
281
|
+
if m == "spkdb":
|
282
|
+
return {category: s.pkdb for category, s in sources_stats().items()}
|
283
|
+
|
284
|
+
if m == "slrms":
|
285
|
+
return {category: s.lrms for category, s in sources_stats().items()}
|
286
|
+
|
287
|
+
if m == "spkr":
|
288
|
+
return {category: s.pkr for category, s in sources_stats().items()}
|
289
|
+
|
290
|
+
if m == "str":
|
291
|
+
return {category: s.tr for category, s in sources_stats().items()}
|
292
|
+
|
293
|
+
if m == "scr":
|
294
|
+
return {category: s.cr for category, s in sources_stats().items()}
|
295
|
+
|
296
|
+
if m == "sfl":
|
297
|
+
return {category: s.fl for category, s in sources_stats().items()}
|
298
|
+
|
299
|
+
if m == "spkc":
|
300
|
+
return {category: s.pkc for category, s in sources_stats().items()}
|
301
|
+
|
302
|
+
if m == "mxsdco":
|
303
|
+
return source_stats().dco
|
304
|
+
|
305
|
+
if m == "mxsmin":
|
306
|
+
return source_stats().min
|
307
|
+
|
308
|
+
if m == "mxsmax":
|
309
|
+
return source_stats().max
|
310
|
+
|
311
|
+
if m == "mxspkdb":
|
312
|
+
return source_stats().pkdb
|
313
|
+
|
314
|
+
if m == "mxslrms":
|
315
|
+
return source_stats().lrms
|
316
|
+
|
317
|
+
if m == "mxspkr":
|
318
|
+
return source_stats().pkr
|
319
|
+
|
320
|
+
if m == "mxstr":
|
321
|
+
return source_stats().tr
|
322
|
+
|
323
|
+
if m == "mxscr":
|
324
|
+
return source_stats().cr
|
325
|
+
|
326
|
+
if m == "mxsfl":
|
327
|
+
return source_stats().fl
|
328
|
+
|
329
|
+
if m == "mxspkc":
|
330
|
+
return source_stats().pkc
|
331
|
+
|
332
|
+
if m.startswith("sasr"):
|
333
|
+
return sources_asr(get_asr_name(m))
|
334
|
+
|
335
|
+
if m.startswith("mxsasr"):
|
336
|
+
return source_asr(get_asr_name(m))
|
337
|
+
|
338
|
+
if m == "ndco":
|
339
|
+
return noise_stats().dco
|
340
|
+
|
341
|
+
if m == "nmin":
|
342
|
+
return noise_stats().min
|
343
|
+
|
344
|
+
if m == "nmax":
|
345
|
+
return noise_stats().max
|
346
|
+
|
347
|
+
if m == "npkdb":
|
348
|
+
return noise_stats().pkdb
|
349
|
+
|
350
|
+
if m == "nlrms":
|
351
|
+
return noise_stats().lrms
|
352
|
+
|
353
|
+
if m == "npkr":
|
354
|
+
return noise_stats().pkr
|
355
|
+
|
356
|
+
if m == "ntr":
|
357
|
+
return noise_stats().tr
|
358
|
+
|
359
|
+
if m == "ncr":
|
360
|
+
return noise_stats().cr
|
361
|
+
|
362
|
+
if m == "nfl":
|
363
|
+
return noise_stats().fl
|
364
|
+
|
365
|
+
if m == "npkc":
|
366
|
+
return noise_stats().pkc
|
367
|
+
|
368
|
+
if m == "sedavg":
|
369
|
+
return 0
|
370
|
+
|
371
|
+
if m == "sedcnt":
|
372
|
+
return 0
|
373
|
+
|
374
|
+
if m == "sedtop3":
|
375
|
+
return np.zeros(3, dtype=np.float32)
|
376
|
+
|
377
|
+
if m == "sedtopn":
|
378
|
+
return 0
|
379
|
+
|
380
|
+
if m == "ssnr":
|
381
|
+
return mixture_segsnr()
|
382
|
+
|
383
|
+
raise AttributeError(f"Unrecognized metric: '{m}'")
|
384
|
+
|
385
|
+
result: dict[str, Any] = {}
|
386
|
+
for metric in metrics:
|
387
|
+
result[metric] = calc(metric)
|
388
|
+
|
389
|
+
# Check for metrics dependencies and add them even if not explicitly requested.
|
390
|
+
if metric.startswith("mxwer"):
|
391
|
+
dependencies = ("mxasr." + metric[6:], "sasr." + metric[6:])
|
392
|
+
for dependency in dependencies:
|
393
|
+
result[dependency] = calc(dependency)
|
394
|
+
|
395
|
+
return result
|