bader-comsar 0.0.3__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.
- bader_comsar-0.0.3.dist-info/METADATA +104 -0
- bader_comsar-0.0.3.dist-info/RECORD +22 -0
- bader_comsar-0.0.3.dist-info/WHEEL +5 -0
- bader_comsar-0.0.3.dist-info/licenses/LICENSE +29 -0
- bader_comsar-0.0.3.dist-info/top_level.txt +1 -0
- comsar/__init__.py +22 -0
- comsar/_tracks/__init__.py +21 -0
- comsar/cli/__init__.py +8 -0
- comsar/cli/apollon_hmm.py +102 -0
- comsar/cli/apollon_onsets.py +67 -0
- comsar/cli/apollon_position.py +59 -0
- comsar/cli/comsar_features.py +51 -0
- comsar/scales.csv +946 -0
- comsar/tracks/__init__.py +4 -0
- comsar/tracks/_form.py +0 -0
- comsar/tracks/_pitch.py +448 -0
- comsar/tracks/_rhythm.py +49 -0
- comsar/tracks/_timbre.py +207 -0
- comsar/tracks/helpers.py +127 -0
- comsar/tracks/schema/TonalSystem.schema.json +41 -0
- comsar/tracks/schema/ngram.schema.json +35 -0
- comsar/tracks/utilities.py +168 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bader-comsar
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: Computational Music and Sound Archiving
|
|
5
|
+
Author: Michael Blaß, Rolf Bader
|
|
6
|
+
Author-email: R_Bader@t-online.de
|
|
7
|
+
License: BSD-3-Clause
|
|
8
|
+
Project-URL: Source code, https://codeberg.org/rbader/comsar
|
|
9
|
+
Project-URL: Bug tracker, https://codeberg.org/rbader/comsar/issues
|
|
10
|
+
Project-URL: Documentation, https://codeberg.org/rbader/comsar
|
|
11
|
+
Keywords: comsar,music,analysis,ethnomusicology
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
23
|
+
Classifier: Intended Audience :: Science/Research
|
|
24
|
+
Classifier: Intended Audience :: Information Technology
|
|
25
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: bader-apollon>=0.1.5
|
|
30
|
+
Requires-Dist: numpy>=1.23
|
|
31
|
+
Requires-Dist: pandas
|
|
32
|
+
Requires-Dist: scipy>=1.6
|
|
33
|
+
Requires-Dist: matplotlib>=3
|
|
34
|
+
Requires-Dist: scikit-learn>=1.0
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# comsar — Computational Music and Sound Archiving
|
|
38
|
+
|
|
39
|
+
**comsar** is a Python toolkit for content-based analysis of music and sound,
|
|
40
|
+
with a focus on ethnomusicology (timbre, pitch/melody, tonal systems, rhythm and
|
|
41
|
+
corpus visualisation with Self-Organizing Maps).
|
|
42
|
+
|
|
43
|
+
It is the top layer of a three-package stack maintained by **Rolf Bader**:
|
|
44
|
+
|
|
45
|
+
| Package | Role | Repository |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| [**apollon**](https://codeberg.org/rbader/apollon) | Backbone: audio I/O, feature extraction, HMM, SOM (C-accelerated) | `codeberg.org/rbader/apollon` |
|
|
48
|
+
| [**chainsaddiction**](https://codeberg.org/rbader/chainsaddiction) | Poisson Hidden-Markov-Models in C (used for rhythm / time-series) | `codeberg.org/rbader/chainsaddiction` |
|
|
49
|
+
| [**comsar**](https://codeberg.org/rbader/comsar) | High-level music analysis (`PitchTrack`, `TimbreTrack`, tonal systems, SOM) | `codeberg.org/rbader/comsar` |
|
|
50
|
+
|
|
51
|
+
This fork combines the modern comsar code base with the pitch-tracking and
|
|
52
|
+
tonal-system analysis (`PitchTrack`) merged back from the older comsar version.
|
|
53
|
+
|
|
54
|
+
> **Distribution names.** The original PyPI names `apollon`, `comsar` and
|
|
55
|
+
> `chainsaddiction` belong to the upstream authors. This fork is published as
|
|
56
|
+
> `bader-apollon`, `bader-comsar` and `bader-chainsaddiction`. The **import**
|
|
57
|
+
> names are unchanged: you still write `import comsar`, `import apollon`, etc.
|
|
58
|
+
|
|
59
|
+
## Installation (no compiler needed)
|
|
60
|
+
|
|
61
|
+
Pre-compiled wheels are provided for **Windows, macOS and Linux**
|
|
62
|
+
(CPython 3.9–3.13). Installing comsar pulls apollon and chainsaddiction
|
|
63
|
+
automatically:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
pip install bader-comsar
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
To also run the example notebooks:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
pip install bader-comsar jupyterlab
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For source builds, step-by-step Windows/macOS/Linux instructions, and
|
|
76
|
+
troubleshooting, see the **[full manual](docs/MANUAL.md)**.
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from comsar import PitchTrack, TimbreTrack
|
|
82
|
+
|
|
83
|
+
# Pitch / melody / tonal-system analysis
|
|
84
|
+
pt = PitchTrack()
|
|
85
|
+
result = pt.extract("my_audio.wav")
|
|
86
|
+
print(result.features) # pandas DataFrame
|
|
87
|
+
|
|
88
|
+
# Timbre feature track
|
|
89
|
+
tt = TimbreTrack()
|
|
90
|
+
timbre = tt.extract("my_audio.wav")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Runnable notebooks are in [`examples/`](examples/).
|
|
94
|
+
|
|
95
|
+
## Documentation
|
|
96
|
+
|
|
97
|
+
* **[docs/MANUAL.md](docs/MANUAL.md)** — full manual: architecture,
|
|
98
|
+
installation, module reference, example walkthrough, troubleshooting,
|
|
99
|
+
and how releases/wheels are built.
|
|
100
|
+
* **[examples/](examples/)** — Jupyter notebooks for the main workflows.
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
BSD-3-Clause. Original work © Michael Blaß; this fork maintained by Rolf Bader.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
bader_comsar-0.0.3.dist-info/licenses/LICENSE,sha256=F_xD1DpCQksZS0qDb-oEvQ3PKZCWrQPEnT0DkeUfMNU,1521
|
|
2
|
+
comsar/__init__.py,sha256=8xjGvisOkTCfXIWsYcfP8YnmjnZAQMRlsjaoI8Pt8Kg,890
|
|
3
|
+
comsar/scales.csv,sha256=dCkIYiiIZupMLoYNVX9vdDLdZdBxQ8Vfz3fj2lMfSzg,61731
|
|
4
|
+
comsar/_tracks/__init__.py,sha256=42XDpRV-CVC3aOZW5hSU5aY09ydu1SbBF_N7UUeuumw,812
|
|
5
|
+
comsar/cli/__init__.py,sha256=xfOV4mR7CqjCJNvSvtwsv7WxEGoaS4GqSFBhaXlFdIE,229
|
|
6
|
+
comsar/cli/apollon_hmm.py,sha256=OkOGLXq6Z-ABi5sD1XDwykI9C43f1doeqdwfcAJWc6M,2858
|
|
7
|
+
comsar/cli/apollon_onsets.py,sha256=CrnkB0CTWnmIIogqUxXo2UcxOJpnxFH3I6T7AYZE8Mo,1729
|
|
8
|
+
comsar/cli/apollon_position.py,sha256=_-lR8z5wy_G-w0g7M0C1IYTJs-ZXOQ0RoYcXczwUSPY,1978
|
|
9
|
+
comsar/cli/comsar_features.py,sha256=tU6ayne4iQKdGrT4m5LsW24WXvr_XXo9medoyYKy9OQ,1344
|
|
10
|
+
comsar/tracks/__init__.py,sha256=NH0burmLtvJw2HCGxuECwlJAzhIrd_jKADkgvmGOa3U,105
|
|
11
|
+
comsar/tracks/_form.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
comsar/tracks/_pitch.py,sha256=tqwF5LWulc6gNRx-BbcPkqynHqtv4nPaOvo_92sgP3g,18986
|
|
13
|
+
comsar/tracks/_rhythm.py,sha256=1jOpbcF8nNedZ5oJnftsLNVoMYRdokr9jvgEWaTYvPU,1642
|
|
14
|
+
comsar/tracks/_timbre.py,sha256=X4IJrasl-xYXo1B3VcO3KBf5mTSr_6AVxhyfM0WBHG4,7647
|
|
15
|
+
comsar/tracks/helpers.py,sha256=MJZO4pH1YFEpk4ZKJSva7ao5Vs6WJ4jlbR-i-dgm7gA,4035
|
|
16
|
+
comsar/tracks/utilities.py,sha256=r_WsQ9z9IBCgB4PJ6hQfhwthqO4O8NPXTfsyXyC6bNc,4515
|
|
17
|
+
comsar/tracks/schema/TonalSystem.schema.json,sha256=h48TUQW2T2lmbwcw9OJ4fUqnAyhE0Rt9xwOCedWZ87I,1383
|
|
18
|
+
comsar/tracks/schema/ngram.schema.json,sha256=juigmccEP-LFRl6NQy-DFTOxwDL19c9nMjrOVuW3xA0,1266
|
|
19
|
+
bader_comsar-0.0.3.dist-info/METADATA,sha256=7UqdDH6zX1i98dFMT3rGdD9D6316KqLv1c362yCYUes,3944
|
|
20
|
+
bader_comsar-0.0.3.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
21
|
+
bader_comsar-0.0.3.dist-info/top_level.txt,sha256=S_a_RD-oQpzFnKe4Uvm_92PWZQTMysSfk4398zxL1UY,7
|
|
22
|
+
bader_comsar-0.0.3.dist-info/RECORD,,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Michael Blaß
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
comsar
|
comsar/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""comsar -- Computational Music and Sound Archiving.
|
|
2
|
+
|
|
3
|
+
Top-level convenience re-exports so that user code / notebooks can simply do::
|
|
4
|
+
|
|
5
|
+
from comsar import PitchTrack, TimbreTrack
|
|
6
|
+
"""
|
|
7
|
+
try:
|
|
8
|
+
from importlib.metadata import version as _version, PackageNotFoundError
|
|
9
|
+
except ImportError: # Python < 3.8 fallback
|
|
10
|
+
from importlib_metadata import version as _version, PackageNotFoundError
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
# Distribution name on PyPI is "bader-comsar"; the import name stays "comsar".
|
|
14
|
+
__version__ = _version("bader-comsar")
|
|
15
|
+
except PackageNotFoundError: # e.g. running from a source checkout
|
|
16
|
+
__version__ = "0.0.3"
|
|
17
|
+
|
|
18
|
+
# __version__ is set *before* importing the tracks subpackage, because
|
|
19
|
+
# comsar.tracks._pitch references ``comsar.__version__`` at runtime.
|
|
20
|
+
from .tracks import TimbreTrack, PitchTrack
|
|
21
|
+
|
|
22
|
+
__all__ = ["TimbreTrack", "PitchTrack", "__version__"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Backward-compatibility shim.
|
|
2
|
+
|
|
3
|
+
Older comsar versions kept the implementation under ``comsar._tracks``.
|
|
4
|
+
The current layout lives under ``comsar.tracks``. This package re-exports the
|
|
5
|
+
old import paths so that legacy notebooks keep working, e.g.::
|
|
6
|
+
|
|
7
|
+
from comsar._tracks.utilities import ngramParams, TonalSystemParams
|
|
8
|
+
"""
|
|
9
|
+
import sys as _sys
|
|
10
|
+
|
|
11
|
+
from comsar.tracks import utilities, helpers
|
|
12
|
+
from comsar.tracks import _pitch as pitch
|
|
13
|
+
from comsar.tracks import _timbre as timbre
|
|
14
|
+
|
|
15
|
+
# Register the modules under their legacy dotted paths so that
|
|
16
|
+
# ``from comsar._tracks.<name> import ...`` resolves without separate files.
|
|
17
|
+
for _name, _mod in (("utilities", utilities), ("helpers", helpers),
|
|
18
|
+
("pitch", pitch), ("timbre", timbre)):
|
|
19
|
+
_sys.modules[f"{__name__}.{_name}"] = _mod
|
|
20
|
+
|
|
21
|
+
del _sys, _name, _mod
|
comsar/cli/__init__.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Licensed under the terms of the BSD-3-Clause license.
|
|
4
|
+
# Copyright (C) 2019 Michael Blaß
|
|
5
|
+
# mblass@posteo.net
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import json
|
|
10
|
+
import pathlib
|
|
11
|
+
import sys
|
|
12
|
+
import typing
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
from .. import io
|
|
17
|
+
from .. hmm import PoissonHmm
|
|
18
|
+
from .. types import Array as _Array
|
|
19
|
+
from .. import tools
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _load_track_file(track_file: str) -> dict:
|
|
23
|
+
track_file = pathlib.Path(track_file)
|
|
24
|
+
with track_file.open('r') as fobj:
|
|
25
|
+
track_data = json.load(fobj, object_hook=io.decode_array)
|
|
26
|
+
return track_data
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _parse_feature_file(track_file: str, feature_path: str) -> _Array:
|
|
30
|
+
feature = _load_track_file(track_file)
|
|
31
|
+
for key in feature_path.split('.'):
|
|
32
|
+
try:
|
|
33
|
+
feature = feature[key]
|
|
34
|
+
except KeyError:
|
|
35
|
+
print('Error. Node "{}" not in "{}".'.format(key, track_file))
|
|
36
|
+
exit(10)
|
|
37
|
+
return _scaling(feature, key)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _scaling(data: _Array, feature: str) -> _Array:
|
|
42
|
+
features1000 = ['skewness', 'kurtosis', 'loudness',
|
|
43
|
+
'roughness', 'sharpness']
|
|
44
|
+
if feature in features1000:
|
|
45
|
+
out = tools.scale(data, 1, 1000)
|
|
46
|
+
else:
|
|
47
|
+
out = data
|
|
48
|
+
return out.round().astype(int)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _train_n_hmm(data: _Array, m_states: int, n_trails: int):
|
|
52
|
+
"""Trains ``n_trails`` HMMs each initialized with a random tpm.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
data: Possibly unporcessed input data set.
|
|
56
|
+
m_states: Number of states.
|
|
57
|
+
n_trails: Number of trails.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Best model regarding to log-likelihood.
|
|
61
|
+
"""
|
|
62
|
+
trails = []
|
|
63
|
+
for i in range(n_trails):
|
|
64
|
+
hmm = PoissonHmm(data, m_states, init_lambda='hist', init_gamma='softmax')
|
|
65
|
+
hmm.fit(data)
|
|
66
|
+
if hmm.success and not np.isnan(hmm.quality.nll):
|
|
67
|
+
trails.append(hmm)
|
|
68
|
+
|
|
69
|
+
for i in range(n_trails):
|
|
70
|
+
hmm = PoissonHmm(data, m_states, init_lambda='linear', init_gamma='softmax')
|
|
71
|
+
hmm.fit(data)
|
|
72
|
+
if hmm.success and not np.isnan(hmm.quality.nll):
|
|
73
|
+
trails.append(hmm)
|
|
74
|
+
|
|
75
|
+
for i in range(n_trails):
|
|
76
|
+
hmm = PoissonHmm(data, m_states, init_lambda='quantile', init_gamma='softmax')
|
|
77
|
+
hmm.fit(data)
|
|
78
|
+
if hmm.success and not np.isnan(hmm.quality.nll):
|
|
79
|
+
trails.append(hmm)
|
|
80
|
+
|
|
81
|
+
if len(trails) == 0:
|
|
82
|
+
return None
|
|
83
|
+
return min(trails, key=lambda hmm: abs(hmm.quality.nll))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main(argv=None) -> int:
|
|
87
|
+
if argv is None:
|
|
88
|
+
argv = sys.argv
|
|
89
|
+
|
|
90
|
+
for trf in argv.track_files:
|
|
91
|
+
feature = _parse_feature_file(trf, argv.feature_path)
|
|
92
|
+
hmm = _train_n_hmm(feature, argv.mstates, 5)
|
|
93
|
+
if hmm is None:
|
|
94
|
+
print('Error. Could not train HMM on {}'.format(trf))
|
|
95
|
+
continue
|
|
96
|
+
out_path = io.generate_outpath(trf, argv.outpath, 'hmm')
|
|
97
|
+
io.dump_json(hmm.to_dict(), out_path)
|
|
98
|
+
return 0
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
if __name__ == '__main__':
|
|
102
|
+
sys.exit(main())
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Licensed under the terms of the BSD-3-Clause license.
|
|
2
|
+
# Copyright (C) 2019 Michael Blaß
|
|
3
|
+
# mblass@posteo.net
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import multiprocessing as mp
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from .. import onsets
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _parse_cml(argv):
|
|
13
|
+
parser = argparse.ArgumentParser(description='Apollon onset detection engine')
|
|
14
|
+
|
|
15
|
+
parser.add_argument('--amplitude', action='store_true',
|
|
16
|
+
help='Detect onsets based on local extrema in the time domain signal.')
|
|
17
|
+
|
|
18
|
+
parser.add_argument('--entropy', action='store_true',
|
|
19
|
+
help='Detect onsets based on time domain entropy maxima.')
|
|
20
|
+
|
|
21
|
+
parser.add_argument('--flux', action='store_true',
|
|
22
|
+
help='Detect onsets based on spectral flux.')
|
|
23
|
+
|
|
24
|
+
parser.add_argument('-o', '--outpath', action='store',
|
|
25
|
+
help='Output file path.')
|
|
26
|
+
|
|
27
|
+
parser.add_argument('filepath', type=str, nargs=1)
|
|
28
|
+
return parser.parse_args(argv)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _amp(a):
|
|
32
|
+
print('Amplitude')
|
|
33
|
+
return a
|
|
34
|
+
|
|
35
|
+
def _entropy(a):
|
|
36
|
+
print('Entropy')
|
|
37
|
+
return a
|
|
38
|
+
|
|
39
|
+
def _flux(a):
|
|
40
|
+
print('Flux')
|
|
41
|
+
return a
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main(argv=None):
|
|
45
|
+
if argv is None:
|
|
46
|
+
argv = sys.argv
|
|
47
|
+
|
|
48
|
+
args = _parse_cml(argv)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
args = _parse_cml(argv)
|
|
52
|
+
detectors = {'amplitude': _amp,
|
|
53
|
+
'entropy': _entropy,
|
|
54
|
+
'flux': _flux}
|
|
55
|
+
|
|
56
|
+
methods = [func for name, func in detectors.items() if getattr(args, name)]
|
|
57
|
+
if len(methods) == 0:
|
|
58
|
+
print('At least one detection method required. Aborting.')
|
|
59
|
+
return 1
|
|
60
|
+
|
|
61
|
+
with mp.Pool(processes=3) as pool:
|
|
62
|
+
results = [pool.apply_async(meth, (i,)) for i, meth in enumerate(methods)]
|
|
63
|
+
out = [res.get() for res in results]
|
|
64
|
+
return out
|
|
65
|
+
|
|
66
|
+
if __name__ == '__main__':
|
|
67
|
+
sys.exit(main())
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Licensed under the terms of the BSD-3-Clause license.
|
|
2
|
+
# Copyright (C) 2019 Michael Blaß
|
|
3
|
+
# mblass@posteo.net
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import pathlib
|
|
7
|
+
import pickle
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import pandas as pd
|
|
12
|
+
|
|
13
|
+
from .. import io
|
|
14
|
+
from .. som.utilities import get_winner
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main(argv=None) -> int:
|
|
18
|
+
if argv is None:
|
|
19
|
+
argv = sys.argv
|
|
20
|
+
|
|
21
|
+
weights = io.load(argv.som_file)
|
|
22
|
+
|
|
23
|
+
if argv.rt:
|
|
24
|
+
for hmm in argv.objective_files:
|
|
25
|
+
hmm = io.load_json(hmm)
|
|
26
|
+
gamma_ = hmm.params.gamma_.astype('float64').flatten()
|
|
27
|
+
flat_idx = get_winner(weights, gamma_)
|
|
28
|
+
print(np.unravel_index(flat_idx, (30, 30)))
|
|
29
|
+
|
|
30
|
+
elif argv.tt:
|
|
31
|
+
fs_path = pathlib.Path(argv.som_file).parent.joinpath('fstats.pkl')
|
|
32
|
+
with fs_path.open('rb') as fobj:
|
|
33
|
+
fstats = pickle.load(fobj)
|
|
34
|
+
|
|
35
|
+
feature_mean, feature_std = fstats
|
|
36
|
+
for file_name in argv.objective_files:
|
|
37
|
+
data = io.load_json(file_name)
|
|
38
|
+
feat = data.timbre.features
|
|
39
|
+
timbre_vector = np.array([
|
|
40
|
+
feat.spectral.centroid.mean(), feat.spectral.centroid.std(),
|
|
41
|
+
feat.spectral.spread.mean(), feat.spectral.spread.std(),
|
|
42
|
+
feat.spectral.skewness.mean(), feat.spectral.skewness.std(),
|
|
43
|
+
feat.spectral.kurtosis.mean(), feat.spectral.kurtosis.std(),
|
|
44
|
+
feat.temporal.flux.mean(), feat.temporal.flux.std(),
|
|
45
|
+
feat.perceptual.roughness.mean(), feat.perceptual.roughness.std(),
|
|
46
|
+
feat.perceptual.sharpness.mean(), feat.perceptual.sharpness.std(),
|
|
47
|
+
feat.perceptual.loudness.mean(), feat.perceptual.loudness.std()])
|
|
48
|
+
|
|
49
|
+
timbre_vector = (timbre_vector - feature_mean) / feature_std
|
|
50
|
+
flat_idx = get_winner(weights, timbre_vector)
|
|
51
|
+
print(np.unravel_index(flat_idx, (40, 40)))
|
|
52
|
+
else:
|
|
53
|
+
print('Error. Need track info.')
|
|
54
|
+
return -10
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == '__main__':
|
|
59
|
+
sys.exit(main())
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Licensed under the terms of the BSD-3-Clause license.
|
|
2
|
+
# Copyright (C) 2019 Michael Blaß
|
|
3
|
+
# mblass@posteo.net
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import itertools
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
import typing
|
|
10
|
+
import logging
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
from apollon import io
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main(argv: dict = None) -> int:
|
|
17
|
+
logging.basicConfig(filename='tt.log', filemode='w', level=logging.DEBUG)
|
|
18
|
+
if argv is None:
|
|
19
|
+
argv = sys.argv
|
|
20
|
+
|
|
21
|
+
timer_total = time.time()
|
|
22
|
+
for path in argv.files:
|
|
23
|
+
logging.info('Loading {}'.format(path))
|
|
24
|
+
print('Processing: {}'.format(path), end=' ... ', flush=True)
|
|
25
|
+
timer_start = time.time()
|
|
26
|
+
|
|
27
|
+
if _check_audio(path) != 0:
|
|
28
|
+
return 10
|
|
29
|
+
|
|
30
|
+
track_data = {}
|
|
31
|
+
if argv.rhythm:
|
|
32
|
+
track_data['rhythm'] = analyses.rhythm_track(snd)
|
|
33
|
+
|
|
34
|
+
if argv.timbre:
|
|
35
|
+
track_data['timbre'] = analyses.timbre_track(snd)
|
|
36
|
+
|
|
37
|
+
if argv.pitch:
|
|
38
|
+
track_data['pitch'] = analyses.pitch_track(snd)
|
|
39
|
+
|
|
40
|
+
out_path = io.generate_outpath(path, argv.outpath, 'feat')
|
|
41
|
+
io.dump_json(track_data, out_path)
|
|
42
|
+
timer_stop = time.time()
|
|
43
|
+
print('Done in {:.5} s.'.format(timer_stop-timer_start), flush=True)
|
|
44
|
+
|
|
45
|
+
logging.info('--- JOB DONE ---')
|
|
46
|
+
print('Job done. Total time: {:.5} s.'.format(time.time()-timer_total))
|
|
47
|
+
return 0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
sys.exit(main())
|