sonusai 0.15.9__py3-none-any.whl → 0.16.1__py3-none-any.whl
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/__init__.py +36 -4
- sonusai/audiofe.py +111 -106
- sonusai/calc_metric_spenh.py +38 -22
- sonusai/genft.py +15 -6
- sonusai/genmix.py +14 -6
- sonusai/genmixdb.py +15 -7
- sonusai/gentcst.py +13 -6
- sonusai/lsdb.py +15 -5
- sonusai/main.py +58 -61
- sonusai/mixture/__init__.py +1 -0
- sonusai/mixture/config.py +1 -2
- sonusai/mkmanifest.py +43 -8
- sonusai/mkwav.py +15 -6
- sonusai/onnx_predict.py +16 -6
- sonusai/plot.py +16 -6
- sonusai/post_spenh_targetf.py +13 -6
- sonusai/summarize_metric_spenh.py +71 -0
- sonusai/tplot.py +14 -6
- sonusai/utils/__init__.py +4 -7
- sonusai/utils/asl_p56.py +3 -3
- sonusai/utils/asr.py +35 -8
- sonusai/utils/asr_functions/__init__.py +0 -5
- sonusai/utils/asr_functions/aaware_whisper.py +2 -2
- sonusai/utils/asr_manifest_functions/__init__.py +1 -0
- sonusai/utils/asr_manifest_functions/mcgill_speech.py +29 -0
- sonusai/utils/{trim_docstring.py → docstring.py} +20 -0
- sonusai/utils/model_utils.py +30 -0
- sonusai/utils/onnx_utils.py +19 -45
- {sonusai-0.15.9.dist-info → sonusai-0.16.1.dist-info}/METADATA +7 -25
- {sonusai-0.15.9.dist-info → sonusai-0.16.1.dist-info}/RECORD +32 -46
- sonusai/data_generator/__init__.py +0 -5
- sonusai/data_generator/dataset_from_mixdb.py +0 -143
- sonusai/data_generator/keras_from_mixdb.py +0 -169
- sonusai/data_generator/torch_from_mixdb.py +0 -122
- sonusai/keras_onnx.py +0 -86
- sonusai/keras_predict.py +0 -231
- sonusai/keras_train.py +0 -334
- sonusai/torchl_onnx.py +0 -216
- sonusai/torchl_predict.py +0 -542
- sonusai/torchl_train.py +0 -223
- sonusai/utils/asr_functions/aixplain_whisper.py +0 -59
- sonusai/utils/asr_functions/data.py +0 -16
- sonusai/utils/asr_functions/deepgram.py +0 -97
- sonusai/utils/asr_functions/fastwhisper.py +0 -90
- sonusai/utils/asr_functions/google.py +0 -95
- sonusai/utils/asr_functions/whisper.py +0 -49
- sonusai/utils/keras_utils.py +0 -226
- {sonusai-0.15.9.dist-info → sonusai-0.16.1.dist-info}/WHEEL +0 -0
- {sonusai-0.15.9.dist-info → sonusai-0.16.1.dist-info}/entry_points.txt +0 -0
sonusai/lsdb.py
CHANGED
@@ -15,11 +15,25 @@ Inputs:
|
|
15
15
|
LOC A SonusAI mixture database directory.
|
16
16
|
|
17
17
|
"""
|
18
|
+
import signal
|
19
|
+
|
18
20
|
from sonusai import logger
|
19
21
|
from sonusai.mixture import GeneralizedIDs
|
20
22
|
from sonusai.mixture import MixtureDatabase
|
21
23
|
|
22
24
|
|
25
|
+
def signal_handler(_sig, _frame):
|
26
|
+
import sys
|
27
|
+
|
28
|
+
from sonusai import logger
|
29
|
+
|
30
|
+
logger.info('Canceled due to keyboard interrupt')
|
31
|
+
sys.exit(1)
|
32
|
+
|
33
|
+
|
34
|
+
signal.signal(signal.SIGINT, signal_handler)
|
35
|
+
|
36
|
+
|
23
37
|
def lsdb(mixdb: MixtureDatabase,
|
24
38
|
mixids: GeneralizedIDs = None,
|
25
39
|
truth_index: int = None,
|
@@ -142,8 +156,4 @@ def main() -> None:
|
|
142
156
|
|
143
157
|
|
144
158
|
if __name__ == '__main__':
|
145
|
-
|
146
|
-
main()
|
147
|
-
except KeyboardInterrupt:
|
148
|
-
logger.info('Canceled due to keyboard interrupt')
|
149
|
-
raise SystemExit(0)
|
159
|
+
main()
|
sonusai/main.py
CHANGED
@@ -3,91 +3,88 @@
|
|
3
3
|
usage: sonusai [--version] [--help] <command> [<args>...]
|
4
4
|
|
5
5
|
The sonusai commands are:
|
6
|
-
|
7
|
-
calc_metric_spenh Run speech enhancement and analysis
|
8
|
-
doc Documentation
|
9
|
-
genft Generate feature and truth data
|
10
|
-
genmix Generate mixture and truth data
|
11
|
-
genmixdb Generate a mixture database
|
12
|
-
gentcst Generate target configuration from a subdirectory tree
|
13
|
-
keras_onnx Convert a trained Keras model to ONNX
|
14
|
-
keras_predict Run Keras predict on a trained model
|
15
|
-
keras_train Train a model using Keras
|
16
|
-
lsdb List information about a mixture database
|
17
|
-
mkmanifest Make ASR manifest JSON file
|
18
|
-
mkwav Make WAV files from a mixture database
|
19
|
-
onnx_predict Run ONNX predict on a trained model
|
20
|
-
plot Plot mixture data
|
21
|
-
post_spenh_targetf Run post-processing for speech enhancement targetf data
|
22
|
-
torchl_onnx Convert a trained Pytorch Lightning model to ONNX
|
23
|
-
torchl_predict Run Lightning predict on a trained model
|
24
|
-
torchl_train Train a model using Lightning
|
25
|
-
tplot Plot truth data
|
26
|
-
vars List custom SonusAI variables
|
6
|
+
<This information is automatically generated.>
|
27
7
|
|
28
8
|
Aaware Sound and Voice Machine Learning Framework. See 'sonusai help <command>'
|
29
9
|
for more information on a specific command.
|
30
10
|
|
31
11
|
"""
|
32
|
-
|
12
|
+
import signal
|
13
|
+
|
14
|
+
|
15
|
+
def signal_handler(_sig, _frame):
|
16
|
+
import sys
|
17
|
+
|
18
|
+
from sonusai import logger
|
19
|
+
|
20
|
+
logger.info('Canceled due to keyboard interrupt')
|
21
|
+
sys.exit(1)
|
22
|
+
|
23
|
+
|
24
|
+
signal.signal(signal.SIGINT, signal_handler)
|
33
25
|
|
34
26
|
|
35
27
|
def main() -> None:
|
28
|
+
from importlib import import_module
|
29
|
+
from pkgutil import iter_modules
|
30
|
+
|
31
|
+
from sonusai import commands_list
|
32
|
+
|
33
|
+
plugins = {}
|
34
|
+
plugin_docstrings = []
|
35
|
+
for _, name, _ in iter_modules():
|
36
|
+
if name.startswith('sonusai_') and not name.startswith('sonusai_asr_'):
|
37
|
+
module = import_module(name)
|
38
|
+
plugins[name] = {
|
39
|
+
'commands': commands_list(module.commands_doc),
|
40
|
+
'basedir': module.BASEDIR,
|
41
|
+
}
|
42
|
+
plugin_docstrings.append(module.commands_doc)
|
43
|
+
|
36
44
|
from docopt import docopt
|
37
45
|
|
38
|
-
import
|
46
|
+
from sonusai import __version__
|
47
|
+
from sonusai.utils import add_commands_to_docstring
|
39
48
|
from sonusai.utils import trim_docstring
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
'doc',
|
45
|
-
'genft',
|
46
|
-
'genmix',
|
47
|
-
'genmixdb',
|
48
|
-
'gentcst',
|
49
|
-
'keras_onnx',
|
50
|
-
'keras_predict',
|
51
|
-
'keras_train',
|
52
|
-
'lsdb',
|
53
|
-
'mkmanifest',
|
54
|
-
'mkwav',
|
55
|
-
'onnx_predict',
|
56
|
-
'plot',
|
57
|
-
'post_spenh_targetf',
|
58
|
-
'torchl_onnx',
|
59
|
-
'torchl_predict',
|
60
|
-
'torchl_train',
|
61
|
-
'tplot',
|
62
|
-
'vars',
|
63
|
-
)
|
64
|
-
|
65
|
-
args = docopt(trim_docstring(__doc__), version=sonusai.__version__, options_first=True)
|
50
|
+
args = docopt(trim_docstring(add_commands_to_docstring(__doc__, plugin_docstrings)),
|
51
|
+
version=__version__,
|
52
|
+
options_first=True)
|
66
53
|
|
67
54
|
command = args['<command>']
|
68
55
|
argv = args['<args>']
|
69
56
|
|
57
|
+
import sys
|
58
|
+
from os.path import join
|
70
59
|
from subprocess import call
|
71
60
|
|
72
61
|
import sonusai
|
73
|
-
from sonusai import
|
62
|
+
from sonusai import logger
|
74
63
|
|
64
|
+
base_commands = sonusai.commands_list()
|
75
65
|
if command == 'help':
|
76
66
|
if not argv:
|
77
67
|
exit(call(['sonusai', '-h']))
|
78
|
-
elif argv[0] in
|
79
|
-
exit(call(['python', f'{sonusai.BASEDIR
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
68
|
+
elif argv[0] in base_commands:
|
69
|
+
exit(call(['python', f'{join(sonusai.BASEDIR, argv[0])}.py', '-h']))
|
70
|
+
|
71
|
+
for plugin, data in plugins.items():
|
72
|
+
if argv[0] in data['commands']:
|
73
|
+
exit(call(['python', f'{join(data["basedir"], argv[0])}.py', '-h']))
|
74
|
+
|
75
|
+
logger.error(f"{argv[0]} is not a SonusAI command. See 'sonusai help'.")
|
76
|
+
sys.exit(1)
|
77
|
+
|
78
|
+
if command in base_commands:
|
79
|
+
exit(call(['python', f'{join(sonusai.BASEDIR, command)}.py'] + argv))
|
80
|
+
|
81
|
+
for plugin, data in plugins.items():
|
82
|
+
if command in data['commands']:
|
83
|
+
exit(call(['python', f'{join(data["basedir"], command)}.py'] + argv))
|
84
84
|
|
85
|
-
|
85
|
+
logger.error(f"{command} is not a SonusAI command. See 'sonusai help'.")
|
86
|
+
sys.exit(1)
|
86
87
|
|
87
88
|
|
88
89
|
if __name__ == '__main__':
|
89
|
-
|
90
|
-
main()
|
91
|
-
except KeyboardInterrupt:
|
92
|
-
logger.info('Canceled due to keyboard interrupt')
|
93
|
-
raise SystemExit(0)
|
90
|
+
main()
|
sonusai/mixture/__init__.py
CHANGED
@@ -108,6 +108,7 @@ from .helpers import get_transform_from_audio
|
|
108
108
|
from .helpers import get_truth_t
|
109
109
|
from .helpers import inverse_transform
|
110
110
|
from .helpers import mixture_metadata
|
111
|
+
from .helpers import read_mixture_data
|
111
112
|
from .helpers import write_mixture_data
|
112
113
|
from .helpers import write_mixture_metadata
|
113
114
|
from .log_duration_and_sizes import log_duration_and_sizes
|
sonusai/mixture/config.py
CHANGED
@@ -480,11 +480,10 @@ def append_noise_files(entry: dict | str, tokens: dict = None) -> list[dict]:
|
|
480
480
|
return noise_files
|
481
481
|
|
482
482
|
|
483
|
-
def get_impulse_response_files(config: dict
|
483
|
+
def get_impulse_response_files(config: dict) -> ImpulseResponseFiles:
|
484
484
|
"""Get the list of impulse response files from a config
|
485
485
|
|
486
486
|
:param config: Config dictionary
|
487
|
-
:param show_progress: Show progress bar
|
488
487
|
:return: List of impulse response files
|
489
488
|
"""
|
490
489
|
from itertools import chain
|
sonusai/mkmanifest.py
CHANGED
@@ -30,6 +30,8 @@ Inputs:
|
|
30
30
|
- 'librispeech'
|
31
31
|
- 'vctk_noisy_speech' expects subdirs named like <name>_wav/ and <name>_txt/ with files in
|
32
32
|
each using same basename, but with .wav and .txt respectively.
|
33
|
+
- 'mcgill-speech' expects audio data in basename/speakerid/speakerid-promptid.wav and
|
34
|
+
transcript data in Scripts/HarvardLists.dat
|
33
35
|
ADAT Audio data environment variable. All found files will be expanded to their full, absolute path and
|
34
36
|
then parts of the path that match the specified environment variable value will be replaced with
|
35
37
|
the variable. This accommodates portability across platforms where the sound datasets may in
|
@@ -42,11 +44,23 @@ Outputs the following to the current directory:
|
|
42
44
|
|
43
45
|
Example usage for LibriSpeech:
|
44
46
|
sonusai mkmanifest -mlibrispeech -eADAT -oasr_manifest.json --include='*.flac' train-clean-100
|
45
|
-
|
47
|
+
sonusai mkmanifest -m mcgill-speech -e ADAT -o asr_manifest_16k.json 16k-LP7/
|
46
48
|
"""
|
47
|
-
|
49
|
+
import signal
|
50
|
+
|
51
|
+
|
52
|
+
def signal_handler(_sig, _frame):
|
53
|
+
import sys
|
54
|
+
|
55
|
+
from sonusai import logger
|
56
|
+
|
57
|
+
logger.info('Canceled due to keyboard interrupt')
|
58
|
+
sys.exit(1)
|
59
|
+
|
60
|
+
|
61
|
+
signal.signal(signal.SIGINT, signal_handler)
|
48
62
|
|
49
|
-
VALID_METHOD = ['librispeech', 'vctk_noisy_speech']
|
63
|
+
VALID_METHOD = ['librispeech', 'vctk_noisy_speech', 'mcgill-speech']
|
50
64
|
|
51
65
|
|
52
66
|
def main() -> None:
|
@@ -88,6 +102,7 @@ def main() -> None:
|
|
88
102
|
from sonusai.utils.asr_manifest_functions import collect_vctk_noisy_speech_transcripts
|
89
103
|
from sonusai.utils.asr_manifest_functions import get_librispeech_manifest_entry
|
90
104
|
from sonusai.utils.asr_manifest_functions import get_vctk_noisy_speech_manifest_entry
|
105
|
+
from sonusai.utils.asr_manifest_functions import get_mcgill_speech_manifest_entry
|
91
106
|
|
92
107
|
start_time = time.monotonic()
|
93
108
|
|
@@ -160,6 +175,30 @@ def main() -> None:
|
|
160
175
|
for result in results:
|
161
176
|
f.write(json.dumps(result) + '\n')
|
162
177
|
|
178
|
+
if method == 'mcgill-speech':
|
179
|
+
logger.info(f'Found {len(entries)} Mcgill Speech files, opening prompt file ...')
|
180
|
+
# Note expecting only one path pointing to data subdir
|
181
|
+
if len(paths) != 1:
|
182
|
+
raise SonusAIError(f'mcgill-speech only support a single path')
|
183
|
+
prompt_fpath = join(join(realpath(abspath(paths[0]))), '../Scripts/HarvardList.dat')
|
184
|
+
with open(prompt_fpath, encoding='utf-8') as f:
|
185
|
+
lines = f.readlines()
|
186
|
+
|
187
|
+
logger.info(f'Found {len(lines) - 4} entries in prompt file.')
|
188
|
+
# First 4 lines are header stuff, can use remaining directly with simple lookup
|
189
|
+
# example line: '01_02:Glue the sheet ...\n' (paragraph 1, sentence 2)
|
190
|
+
# 11 entries per group, so getting line is 11*(p1-1)+(s2-1)
|
191
|
+
lines = lines[4:]
|
192
|
+
|
193
|
+
processing_func = partial(get_mcgill_speech_manifest_entry, transcript_data=lines)
|
194
|
+
progress = tqdm(total=len(entries), desc='Creating Mcgill Speech manifest data')
|
195
|
+
results = pp_tqdm_imap(processing_func, entries, progress=progress)
|
196
|
+
progress.close()
|
197
|
+
|
198
|
+
with open(output, 'w') as f:
|
199
|
+
for result in results:
|
200
|
+
f.write(json.dumps(result) + '\n')
|
201
|
+
|
163
202
|
end_time = time.monotonic()
|
164
203
|
logger.info('')
|
165
204
|
logger.info(f'Completed in {seconds_to_hms(seconds=end_time - start_time)}')
|
@@ -167,8 +206,4 @@ def main() -> None:
|
|
167
206
|
|
168
207
|
|
169
208
|
if __name__ == '__main__':
|
170
|
-
|
171
|
-
main()
|
172
|
-
except KeyboardInterrupt:
|
173
|
-
logger.info('Canceled due to keyboard interrupt')
|
174
|
-
raise SystemExit(0)
|
209
|
+
main()
|
sonusai/mkwav.py
CHANGED
@@ -23,13 +23,25 @@ Outputs the following to the mixture database directory:
|
|
23
23
|
mkwav.log
|
24
24
|
|
25
25
|
"""
|
26
|
+
import signal
|
26
27
|
from dataclasses import dataclass
|
27
28
|
|
28
|
-
from sonusai import logger
|
29
29
|
from sonusai.mixture import AudioT
|
30
30
|
from sonusai.mixture import MixtureDatabase
|
31
31
|
|
32
32
|
|
33
|
+
def signal_handler(_sig, _frame):
|
34
|
+
import sys
|
35
|
+
|
36
|
+
from sonusai import logger
|
37
|
+
|
38
|
+
logger.info('Canceled due to keyboard interrupt')
|
39
|
+
sys.exit(1)
|
40
|
+
|
41
|
+
|
42
|
+
signal.signal(signal.SIGINT, signal_handler)
|
43
|
+
|
44
|
+
|
33
45
|
@dataclass
|
34
46
|
class MPGlobal:
|
35
47
|
mixdb: MixtureDatabase = None
|
@@ -120,6 +132,7 @@ def main() -> None:
|
|
120
132
|
import sonusai
|
121
133
|
from sonusai import create_file_handler
|
122
134
|
from sonusai import initial_log_messages
|
135
|
+
from sonusai import logger
|
123
136
|
from sonusai import update_console_handler
|
124
137
|
from sonusai.mixture import check_audio_files_exist
|
125
138
|
from sonusai.utils import pp_tqdm_imap
|
@@ -164,8 +177,4 @@ def main() -> None:
|
|
164
177
|
|
165
178
|
|
166
179
|
if __name__ == '__main__':
|
167
|
-
|
168
|
-
main()
|
169
|
-
except KeyboardInterrupt:
|
170
|
-
logger.info('Canceled due to keyboard interrupt')
|
171
|
-
raise SystemExit(0)
|
180
|
+
main()
|
sonusai/onnx_predict.py
CHANGED
@@ -29,12 +29,25 @@ Outputs the following to opredict-<TIMESTAMP> directory:
|
|
29
29
|
|
30
30
|
"""
|
31
31
|
|
32
|
-
|
32
|
+
import signal
|
33
|
+
|
33
34
|
from sonusai.mixture import Feature
|
34
35
|
from sonusai.mixture import Predict
|
35
36
|
from sonusai.utils import SonusAIMetaData
|
36
37
|
|
37
38
|
|
39
|
+
def signal_handler(_sig, _frame):
|
40
|
+
import sys
|
41
|
+
|
42
|
+
from sonusai import logger
|
43
|
+
|
44
|
+
logger.info('Canceled due to keyboard interrupt')
|
45
|
+
sys.exit(1)
|
46
|
+
|
47
|
+
|
48
|
+
signal.signal(signal.SIGINT, signal_handler)
|
49
|
+
|
50
|
+
|
38
51
|
def main() -> None:
|
39
52
|
from docopt import docopt
|
40
53
|
|
@@ -60,6 +73,7 @@ def main() -> None:
|
|
60
73
|
|
61
74
|
from sonusai import create_file_handler
|
62
75
|
from sonusai import initial_log_messages
|
76
|
+
from sonusai import logger
|
63
77
|
from sonusai import update_console_handler
|
64
78
|
from sonusai.mixture import MixtureDatabase
|
65
79
|
from sonusai.mixture import get_feature_from_audio
|
@@ -233,8 +247,4 @@ def pad_and_predict(feature: Feature,
|
|
233
247
|
|
234
248
|
|
235
249
|
if __name__ == '__main__':
|
236
|
-
|
237
|
-
main()
|
238
|
-
except KeyboardInterrupt:
|
239
|
-
logger.info('Canceled due to keyboard interrupt')
|
240
|
-
raise SystemExit(0)
|
250
|
+
main()
|
sonusai/plot.py
CHANGED
@@ -41,16 +41,29 @@ Outputs:
|
|
41
41
|
|
42
42
|
"""
|
43
43
|
|
44
|
+
import signal
|
45
|
+
|
44
46
|
import numpy as np
|
45
47
|
from matplotlib import pyplot as plt
|
46
48
|
|
47
|
-
from sonusai import logger
|
48
49
|
from sonusai.mixture import AudioT
|
49
50
|
from sonusai.mixture import Feature
|
50
51
|
from sonusai.mixture import Predict
|
51
52
|
from sonusai.mixture import Truth
|
52
53
|
|
53
54
|
|
55
|
+
def signal_handler(_sig, _frame):
|
56
|
+
import sys
|
57
|
+
|
58
|
+
from sonusai import logger
|
59
|
+
|
60
|
+
logger.info('Canceled due to keyboard interrupt')
|
61
|
+
sys.exit(1)
|
62
|
+
|
63
|
+
|
64
|
+
signal.signal(signal.SIGINT, signal_handler)
|
65
|
+
|
66
|
+
|
54
67
|
def spec_plot(mixture: AudioT,
|
55
68
|
feature: Feature,
|
56
69
|
predict: Predict = None,
|
@@ -264,6 +277,7 @@ def main() -> None:
|
|
264
277
|
from sonusai import SonusAIError
|
265
278
|
from sonusai import create_file_handler
|
266
279
|
from sonusai import initial_log_messages
|
280
|
+
from sonusai import logger
|
267
281
|
from sonusai import update_console_handler
|
268
282
|
from sonusai.mixture import MixtureDatabase
|
269
283
|
from sonusai.mixture import FeatureGeneratorConfig
|
@@ -457,8 +471,4 @@ def main() -> None:
|
|
457
471
|
|
458
472
|
|
459
473
|
if __name__ == '__main__':
|
460
|
-
|
461
|
-
main()
|
462
|
-
except KeyboardInterrupt:
|
463
|
-
logger.info('Canceled due to keyboard interrupt')
|
464
|
-
raise SystemExit(0)
|
474
|
+
main()
|
sonusai/post_spenh_targetf.py
CHANGED
@@ -20,9 +20,20 @@ Outputs the following to post_spenh_targetf-<TIMESTAMP> directory:
|
|
20
20
|
post_spenh_targetf.log
|
21
21
|
|
22
22
|
"""
|
23
|
+
import signal
|
23
24
|
from dataclasses import dataclass
|
24
25
|
|
25
|
-
|
26
|
+
|
27
|
+
def signal_handler(_sig, _frame):
|
28
|
+
import sys
|
29
|
+
|
30
|
+
from sonusai import logger
|
31
|
+
|
32
|
+
logger.info('Canceled due to keyboard interrupt')
|
33
|
+
sys.exit(1)
|
34
|
+
|
35
|
+
|
36
|
+
signal.signal(signal.SIGINT, signal_handler)
|
26
37
|
|
27
38
|
|
28
39
|
@dataclass
|
@@ -146,8 +157,4 @@ def _process(file: str) -> None:
|
|
146
157
|
|
147
158
|
|
148
159
|
if __name__ == '__main__':
|
149
|
-
|
150
|
-
main()
|
151
|
-
except KeyboardInterrupt:
|
152
|
-
logger.info('Canceled due to keyboard interrupt')
|
153
|
-
exit()
|
160
|
+
main()
|
@@ -0,0 +1,71 @@
|
|
1
|
+
"""sonusai summarize_metric_spenh
|
2
|
+
|
3
|
+
usage: summarize_metric_spenh [-hr] [-s SORT] LOC
|
4
|
+
|
5
|
+
options:
|
6
|
+
-h, --help
|
7
|
+
-s SORT, --sort SORT Sort by SORT column. [default: MIXID]
|
8
|
+
-r, --reverse Reverse sort order.
|
9
|
+
|
10
|
+
Summarize speech enhancement metrics results using data generated by SonusAI calc_metric_spenh.
|
11
|
+
|
12
|
+
Inputs:
|
13
|
+
LOC A SonusAI calc_metric_spenh results directory.
|
14
|
+
|
15
|
+
"""
|
16
|
+
import signal
|
17
|
+
|
18
|
+
|
19
|
+
def signal_handler(_sig, _frame):
|
20
|
+
import sys
|
21
|
+
|
22
|
+
from sonusai import logger
|
23
|
+
|
24
|
+
logger.info('Canceled due to keyboard interrupt')
|
25
|
+
sys.exit(1)
|
26
|
+
|
27
|
+
|
28
|
+
signal.signal(signal.SIGINT, signal_handler)
|
29
|
+
|
30
|
+
|
31
|
+
def summarize_metric_spenh(location: str, by: str = 'MIXID', reverse: bool = False) -> str:
|
32
|
+
import glob
|
33
|
+
|
34
|
+
import pandas as pd
|
35
|
+
|
36
|
+
files = sorted(glob.glob(location + '/*_metric_spenh.txt'))
|
37
|
+
need_header = True
|
38
|
+
header = ['MIXID']
|
39
|
+
data = []
|
40
|
+
for file in files:
|
41
|
+
with open(file, 'r') as f:
|
42
|
+
for i, line in enumerate(f):
|
43
|
+
if i == 1 and need_header:
|
44
|
+
need_header = False
|
45
|
+
header.extend(line.strip().split())
|
46
|
+
elif i == 2:
|
47
|
+
data.append(line.strip().split())
|
48
|
+
break
|
49
|
+
|
50
|
+
df = pd.DataFrame(data, columns=header)
|
51
|
+
df[header[0:-2]] = df[header[0:-2]].apply(pd.to_numeric, errors='coerce')
|
52
|
+
return df.sort_values(by=by, ascending=not reverse).to_string(index=False)
|
53
|
+
|
54
|
+
|
55
|
+
def main():
|
56
|
+
from docopt import docopt
|
57
|
+
|
58
|
+
import sonusai
|
59
|
+
from sonusai.utils import trim_docstring
|
60
|
+
|
61
|
+
args = docopt(trim_docstring(__doc__), version=sonusai.__version__, options_first=True)
|
62
|
+
|
63
|
+
by = args['--sort']
|
64
|
+
reverse = args['--reverse']
|
65
|
+
location = args['LOC']
|
66
|
+
|
67
|
+
print(summarize_metric_spenh(location, by, reverse))
|
68
|
+
|
69
|
+
|
70
|
+
if __name__ == '__main__':
|
71
|
+
main()
|
sonusai/tplot.py
CHANGED
@@ -41,7 +41,19 @@ options:
|
|
41
41
|
A multi-page plot TARGET-tplot.pdf or CONFIG-tplot.pdf is generated.
|
42
42
|
|
43
43
|
"""
|
44
|
-
|
44
|
+
import signal
|
45
|
+
|
46
|
+
|
47
|
+
def signal_handler(_sig, _frame):
|
48
|
+
import sys
|
49
|
+
|
50
|
+
from sonusai import logger
|
51
|
+
|
52
|
+
logger.info('Canceled due to keyboard interrupt')
|
53
|
+
sys.exit(1)
|
54
|
+
|
55
|
+
|
56
|
+
signal.signal(signal.SIGINT, signal_handler)
|
45
57
|
|
46
58
|
|
47
59
|
# TODO: re-work for modern mixdb API
|
@@ -328,8 +340,4 @@ def main() -> None:
|
|
328
340
|
|
329
341
|
|
330
342
|
if __name__ == '__main__':
|
331
|
-
|
332
|
-
main()
|
333
|
-
except KeyboardInterrupt:
|
334
|
-
logger.info('Canceled due to keyboard interrupt')
|
335
|
-
raise SystemExit(0)
|
343
|
+
main()
|
sonusai/utils/__init__.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# SonusAI general utilities
|
2
2
|
from .asl_p56 import asl_p56
|
3
|
+
from .asr import ASRData
|
3
4
|
from .asr import ASRResult
|
4
5
|
from .asr import calc_asr
|
5
6
|
from .audio_devices import get_default_input_device
|
@@ -14,24 +15,21 @@ from .create_ts_name import create_ts_name
|
|
14
15
|
from .dataclass_from_dict import dataclass_from_dict
|
15
16
|
from .db import db_to_linear
|
16
17
|
from .db import linear_to_db
|
18
|
+
from .docstring import add_commands_to_docstring
|
19
|
+
from .docstring import trim_docstring
|
17
20
|
from .energy_f import compute_energy_f
|
18
21
|
from .engineering_number import EngineeringNumber
|
19
22
|
from .get_frames_per_batch import get_frames_per_batch
|
20
23
|
from .get_label_names import get_label_names
|
21
24
|
from .grouper import grouper
|
22
25
|
from .human_readable_size import human_readable_size
|
23
|
-
from .keras_utils import check_keras_overrides
|
24
|
-
from .keras_utils import create_onnx_from_keras
|
25
|
-
from .keras_utils import import_and_check_keras_model
|
26
|
-
from .keras_utils import import_keras_model
|
27
|
-
from .keras_utils import keras_onnx
|
28
26
|
from .max_text_width import max_text_width
|
27
|
+
from .model_utils import import_module
|
29
28
|
from .numeric_conversion import float_to_int16
|
30
29
|
from .numeric_conversion import int16_to_float
|
31
30
|
from .onnx_utils import SonusAIMetaData
|
32
31
|
from .onnx_utils import add_sonusai_metadata
|
33
32
|
from .onnx_utils import get_sonusai_metadata
|
34
|
-
from .onnx_utils import replace_stateful_grus
|
35
33
|
from .parallel import pp_imap
|
36
34
|
from .parallel import pp_tqdm_imap
|
37
35
|
from .print_mixture_details import print_class_count
|
@@ -50,6 +48,5 @@ from .stacked_complex import stacked_complex_imag
|
|
50
48
|
from .stacked_complex import stacked_complex_real
|
51
49
|
from .stacked_complex import unstack_complex
|
52
50
|
from .stratified_shuffle_split import stratified_shuffle_split_mixid
|
53
|
-
from .trim_docstring import trim_docstring
|
54
51
|
from .wave import write_wav
|
55
52
|
from .yes_or_no import yes_or_no
|
sonusai/utils/asl_p56.py
CHANGED
@@ -22,7 +22,7 @@ def asl_p56(audio: AudioT) -> float:
|
|
22
22
|
# Hangover time in seconds
|
23
23
|
H = 0.2
|
24
24
|
# Rounded up to next integer
|
25
|
-
|
25
|
+
H_samples = np.ceil(H * SAMPLE_RATE)
|
26
26
|
|
27
27
|
# Margin in dB, difference between threshold and active speech level
|
28
28
|
M = 15.9
|
@@ -40,7 +40,7 @@ def asl_p56(audio: AudioT) -> float:
|
|
40
40
|
a = np.full(thresh_num, -1)
|
41
41
|
|
42
42
|
# Hangover counter for each threshold
|
43
|
-
h = np.full(thresh_num,
|
43
|
+
h = np.full(thresh_num, H_samples)
|
44
44
|
|
45
45
|
# Long-term level square energy of audio
|
46
46
|
sq = sum(np.square(audio))
|
@@ -55,7 +55,7 @@ def asl_p56(audio: AudioT) -> float:
|
|
55
55
|
if q[k] >= c[j]:
|
56
56
|
a[j] = a[j] + 1
|
57
57
|
h[j] = 0
|
58
|
-
elif h[j] <
|
58
|
+
elif h[j] < H_samples:
|
59
59
|
a[j] = a[j] + 1
|
60
60
|
h[j] = h[j] + 1
|
61
61
|
else:
|