partitura 1.7.0__tar.gz → 1.8.0__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.
- {partitura-1.7.0 → partitura-1.8.0}/PKG-INFO +32 -18
- partitura-1.8.0/docs/source/conf.py +120 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/__init__.py +8 -9
- {partitura-1.7.0 → partitura-1.8.0}/partitura/directions.py +12 -2
- {partitura-1.7.0 → partitura-1.8.0}/partitura/display.py +4 -4
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/__init__.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportaudio.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportkern.py +6 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportmatch.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportmidi.py +15 -2
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportmusicxml.py +25 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importdcml.py +8 -3
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importmatch.py +4 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importmei.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importmidi.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importmusicxml.py +54 -20
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importparangonada.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/matchfile_base.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/matchfile_utils.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/matchlines_v0.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/matchlines_v1.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/__init__.py +0 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/key_identification.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/note_features.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/performance_codec.py +32 -16
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/performance_features.py +1 -2
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/pitch_spelling.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/voice_separation.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/performance.py +0 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/score.py +44 -8
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/generic.py +5 -17
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/globals.py +0 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/misc.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/normalize.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/synth.py +1 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura.egg-info/PKG-INFO +32 -18
- {partitura-1.7.0 → partitura-1.8.0}/partitura.egg-info/SOURCES.txt +2 -2
- partitura-1.8.0/partitura.egg-info/requires.txt +31 -0
- partitura-1.8.0/partitura.egg-info/top_level.txt +4 -0
- partitura-1.8.0/pyproject.toml +92 -0
- partitura-1.8.0/tests/test_harmony.py +387 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_midi_export.py +10 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_note_features.py +14 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_pianoroll.py +2 -1
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_synth.py +2 -2
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_times.py +4 -7
- partitura-1.7.0/partitura.egg-info/requires.txt +0 -6
- partitura-1.7.0/partitura.egg-info/top_level.txt +0 -1
- partitura-1.7.0/setup.py +0 -79
- partitura-1.7.0/tests/test_harmony.py +0 -31
- partitura-1.7.0/tests/test_quarter_adjust.py +0 -157
- {partitura-1.7.0 → partitura-1.8.0}/LICENSE +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/README.md +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/assets/musicxml.xsd +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/assets/score_example.krn +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/assets/score_example.mei +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/assets/score_example.mid +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/assets/score_example.musicxml +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportmei.py +1 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/exportparangonada.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importkern.py +1 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importmusic21.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/importnakamura.py +1 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/io/musescore.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/meter.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/note_array_to_score.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/musicanalysis/tonal_tension.py +1 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/__init__.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/fluidsynth.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/partitura/utils/music.py +1 -1
- {partitura-1.7.0 → partitura-1.8.0}/partitura.egg-info/dependency_links.txt +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/setup.cfg +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_clef.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_cross_staff.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_dcml_import.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_deprecations.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_display.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_fluidsynth.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_iter.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_kern.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_key_estimation.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_load_performance.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_load_score.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_m21_import.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_match_export.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_match_import.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_mei.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_merge_parts.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_metrical_position.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_midi_import.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_musescore.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_nakamura.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_new_divs.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_note_array.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_octave_shift.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_parangonada.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_part_properties.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_partial_measures.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_performance.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_performance_codec.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_performance_features.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_pitch_spelling.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_rest_array.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_time_estimation.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_tonal_tension.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_transpose.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_urlload.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_utils.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_voice_estimation.py +0 -0
- {partitura-1.7.0 → partitura-1.8.0}/tests/test_xml.py +0 -0
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: partitura
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: A package for handling symbolic musical information
|
|
5
|
-
Home-page: https://github.com/CPJKU/partitura
|
|
6
5
|
Author: Maarten Grachten, Carlos Cancino-Chacón, Silvan Peter, Emmanouil Karystinaios, Francesco Foscarin, Thassilo Gadermaier, Patricia Hu
|
|
7
|
-
|
|
6
|
+
Maintainer-email: partitura-users@googlegroups.com
|
|
8
7
|
License: Apache 2.0
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Project-URL: Homepage, https://github.com/CPJKU/partitura
|
|
9
|
+
Keywords: music,notation,musicxml,midi
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
11
|
Classifier: Programming Language :: Python
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
14
17
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
15
|
-
Requires-Python: >=3.
|
|
18
|
+
Requires-Python: >=3.10
|
|
16
19
|
Description-Content-Type: text/markdown
|
|
17
20
|
License-File: LICENSE
|
|
18
21
|
Requires-Dist: numpy
|
|
@@ -21,19 +24,30 @@ Requires-Dist: lxml
|
|
|
21
24
|
Requires-Dist: lark-parser
|
|
22
25
|
Requires-Dist: xmlschema
|
|
23
26
|
Requires-Dist: mido
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
Requires-Dist: typing-extensions
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest; extra == "dev"
|
|
30
|
+
Requires-Dist: black; extra == "dev"
|
|
31
|
+
Requires-Dist: nbsphinx; extra == "dev"
|
|
32
|
+
Requires-Dist: music21; extra == "dev"
|
|
33
|
+
Requires-Dist: Pillow; extra == "dev"
|
|
34
|
+
Requires-Dist: musescore; extra == "dev"
|
|
35
|
+
Requires-Dist: miditok; extra == "dev"
|
|
36
|
+
Requires-Dist: tokenizers; extra == "dev"
|
|
37
|
+
Requires-Dist: pandas; extra == "dev"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: nbsphinx; extra == "all"
|
|
40
|
+
Requires-Dist: torch; extra == "all"
|
|
41
|
+
Requires-Dist: pyfluidsynth; extra == "all"
|
|
42
|
+
Requires-Dist: pytest; extra == "all"
|
|
43
|
+
Requires-Dist: black; extra == "all"
|
|
44
|
+
Requires-Dist: music21; extra == "all"
|
|
45
|
+
Requires-Dist: Pillow; extra == "all"
|
|
46
|
+
Requires-Dist: musescore; extra == "all"
|
|
47
|
+
Requires-Dist: miditok; extra == "all"
|
|
48
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
49
|
+
Requires-Dist: pandas; extra == "all"
|
|
32
50
|
Dynamic: license-file
|
|
33
|
-
Dynamic: requires-dist
|
|
34
|
-
Dynamic: requires-python
|
|
35
|
-
Dynamic: summary
|
|
36
|
-
|
|
37
51
|
|
|
38
52
|
[//]: # (<p align="center"> )
|
|
39
53
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# This file only contains a selection of the most common options. For a full
|
|
4
|
+
# list see the documentation:
|
|
5
|
+
# http://www.sphinx-doc.org/en/master/config
|
|
6
|
+
|
|
7
|
+
# -- Path setup --------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
# If extensions (or modules to document with autodoc) are in another directory,
|
|
10
|
+
# add these directories to sys.path here. If the directory is relative to the
|
|
11
|
+
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
12
|
+
#
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
sys.path.insert(0, os.path.abspath("../../partitura"))
|
|
17
|
+
# The master toctree document.
|
|
18
|
+
master_doc = "index"
|
|
19
|
+
|
|
20
|
+
# -- Project information -----------------------------------------------------
|
|
21
|
+
|
|
22
|
+
project = "partitura"
|
|
23
|
+
# copyright = '2019, Maarten Grachten'
|
|
24
|
+
author = "Maarten Grachten, Carlos Cancino-Chacón, Silvan Peter, Emmanouil Karystinaios, Francesco Foscarin, Thassilo Gadermaier"
|
|
25
|
+
|
|
26
|
+
# The version info for the project you're documenting, acts as replacement for
|
|
27
|
+
# |version| and |release|, also used in various other places throughout the
|
|
28
|
+
# built documents.
|
|
29
|
+
#
|
|
30
|
+
# The short X.Y version.
|
|
31
|
+
version = "1.8.0"
|
|
32
|
+
# The full version, including alpha/beta/rc tags.
|
|
33
|
+
release = "1.8.0"
|
|
34
|
+
|
|
35
|
+
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
36
|
+
# for a list of supported languages.
|
|
37
|
+
#
|
|
38
|
+
# This is also used if you do content translation via gettext catalogs.
|
|
39
|
+
# Usually you set "language" from the command line for these cases.
|
|
40
|
+
language = "python"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# -- General configuration ---------------------------------------------------
|
|
44
|
+
|
|
45
|
+
# List of patterns, relative to source directory, that match files and
|
|
46
|
+
# directories to ignore when looking for source files.
|
|
47
|
+
exclude_patterns = ["_build"]
|
|
48
|
+
|
|
49
|
+
# The name of the Pygments (syntax highlighting) style to use.
|
|
50
|
+
pygments_style = "sphinx"
|
|
51
|
+
|
|
52
|
+
# Add any Sphinx extension module names here, as strings. They can be
|
|
53
|
+
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
54
|
+
# ones.
|
|
55
|
+
extensions = [
|
|
56
|
+
"sphinx.ext.autodoc",
|
|
57
|
+
"sphinx.ext.autosummary",
|
|
58
|
+
"sphinx.ext.doctest",
|
|
59
|
+
"sphinx.ext.todo",
|
|
60
|
+
"sphinx.ext.coverage",
|
|
61
|
+
"sphinx.ext.mathjax",
|
|
62
|
+
"sphinx.ext.viewcode",
|
|
63
|
+
# 'sphinxcontrib.napoleon',
|
|
64
|
+
"sphinx.ext.napoleon",
|
|
65
|
+
"nbsphinx",
|
|
66
|
+
# 'sphinxcontrib.bibtex', # for bibliographic references
|
|
67
|
+
# 'sphinxcontrib.rsvgconverter', # for SVG->PDF conversion in LaTeX output
|
|
68
|
+
# 'sphinx_gallery.load_style', # load CSS for gallery (needs SG >= 0.6)
|
|
69
|
+
# 'sphinx_last_updated_by_git', #? get "last updated" from Git
|
|
70
|
+
# 'sphinx_codeautolink', # automatic links from code to documentation
|
|
71
|
+
# 'sphinx.ext.intersphinx', # links to other Sphinx projects (e.g. NumPy)
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
# These projects are also used for the sphinx_codeautolink extension:
|
|
75
|
+
intersphinx_mapping = {
|
|
76
|
+
"IPython": ("https://ipython.readthedocs.io/en/stable/", None),
|
|
77
|
+
"matplotlib": ("https://matplotlib.org/", None),
|
|
78
|
+
"numpy": ("https://docs.scipy.org/doc/numpy/", None),
|
|
79
|
+
"pandas": ("https://pandas.pydata.org/docs/", None),
|
|
80
|
+
"python": ("https://docs.python.org/3/", None),
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# see http://stackoverflow.com/q/12206334/562769
|
|
84
|
+
numpydoc_show_class_members = False
|
|
85
|
+
|
|
86
|
+
# Add any paths that contain templates here, relative to this directory.
|
|
87
|
+
templates_path = ["_templates"]
|
|
88
|
+
|
|
89
|
+
# The suffix(es) of source filenames.
|
|
90
|
+
# You can specify multiple suffix as a list of string:
|
|
91
|
+
# source_suffix = ['.rst', '.md']
|
|
92
|
+
source_suffix = ".rst"
|
|
93
|
+
|
|
94
|
+
# List of patterns, relative to source directory, that match files and
|
|
95
|
+
# directories to ignore when looking for source files.
|
|
96
|
+
# This pattern also affects html_static_path and html_extra_path.
|
|
97
|
+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# -- Options for HTML output -------------------------------------------------
|
|
101
|
+
|
|
102
|
+
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
103
|
+
# a list of builtin themes.
|
|
104
|
+
#
|
|
105
|
+
# only import and set the theme if we're building docs locally
|
|
106
|
+
if os.environ.get("READTHEDOCS") != "True":
|
|
107
|
+
import sphinx_rtd_theme
|
|
108
|
+
|
|
109
|
+
html_theme = "sphinx_rtd_theme"
|
|
110
|
+
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
|
111
|
+
else:
|
|
112
|
+
html_theme = "default"
|
|
113
|
+
|
|
114
|
+
# Add any paths that contain custom static files (such as style sheets) here,
|
|
115
|
+
# relative to this directory. They are copied after the builtin static files,
|
|
116
|
+
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
117
|
+
# html_static_path = ['_static']
|
|
118
|
+
|
|
119
|
+
# Output file base name for HTML help builder.
|
|
120
|
+
htmlhelp_basename = "partituradoc"
|
|
@@ -6,7 +6,9 @@ data, display rendered scores, and functions to estimate pitch
|
|
|
6
6
|
spelling, voice assignment, and key signature.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import sys
|
|
10
|
+
from importlib.metadata import version
|
|
11
|
+
from importlib.resources import files
|
|
10
12
|
|
|
11
13
|
from .io import load_score, load_performance, load_score_as_part, lp
|
|
12
14
|
from .io.musescore import load_via_musescore
|
|
@@ -29,18 +31,15 @@ from .display import render
|
|
|
29
31
|
from . import musicanalysis
|
|
30
32
|
from .musicanalysis import make_note_features, compute_note_array, full_note_array
|
|
31
33
|
|
|
32
|
-
|
|
33
34
|
# define a version variable
|
|
34
|
-
__version__ =
|
|
35
|
+
__version__ = version("partitura")
|
|
35
36
|
|
|
36
37
|
#: An example MusicXML file for didactic purposes
|
|
37
|
-
EXAMPLE_MUSICXML =
|
|
38
|
-
"partitura", "assets/score_example.musicxml"
|
|
39
|
-
)
|
|
38
|
+
EXAMPLE_MUSICXML = str(files("partitura") / "assets" / "score_example.musicxml")
|
|
40
39
|
|
|
41
|
-
EXAMPLE_MIDI =
|
|
42
|
-
EXAMPLE_MEI =
|
|
43
|
-
EXAMPLE_KERN =
|
|
40
|
+
EXAMPLE_MIDI = str(files("partitura") / "assets" / "score_example.mid")
|
|
41
|
+
EXAMPLE_MEI = str(files("partitura") / "assets" / "score_example.mei")
|
|
42
|
+
EXAMPLE_KERN = str(files("partitura") / "assets" / "score_example.krn")
|
|
44
43
|
|
|
45
44
|
__all__ = [
|
|
46
45
|
"load_score",
|
|
@@ -327,6 +327,12 @@ def regularize_form(children):
|
|
|
327
327
|
return " ".join(unabbreviate(ch.lower()) for ch in children)
|
|
328
328
|
|
|
329
329
|
|
|
330
|
+
def check_tree(tree, col_name="column"):
|
|
331
|
+
meta = getattr(tree, "meta", None)
|
|
332
|
+
col = getattr(meta, col_name, None)
|
|
333
|
+
return col
|
|
334
|
+
|
|
335
|
+
|
|
330
336
|
def create_directions(tree, string, start=None, end=None):
|
|
331
337
|
"""
|
|
332
338
|
Recursively walk the parse tree of `string` to create a `score.Direction`
|
|
@@ -334,9 +340,13 @@ def create_directions(tree, string, start=None, end=None):
|
|
|
334
340
|
|
|
335
341
|
"""
|
|
336
342
|
if start is None:
|
|
337
|
-
|
|
343
|
+
col = check_tree(tree, "column")
|
|
344
|
+
if col is not None:
|
|
345
|
+
start = col - 1
|
|
338
346
|
if end is None:
|
|
339
|
-
|
|
347
|
+
col = check_tree(tree, "end_column")
|
|
348
|
+
if col is not None:
|
|
349
|
+
end = col - 1
|
|
340
350
|
|
|
341
351
|
if tree.data == "conj":
|
|
342
352
|
return create_directions(tree.children[0], string) + create_directions(
|
|
@@ -20,7 +20,6 @@ from partitura.score import ScoreLike
|
|
|
20
20
|
|
|
21
21
|
from partitura.utils.misc import PathLike, deprecated_alias
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
__all__ = ["render"]
|
|
25
24
|
|
|
26
25
|
# def ly_install_msg():
|
|
@@ -117,9 +116,10 @@ def render_lilypond(
|
|
|
117
116
|
|
|
118
117
|
prvw_sfx = ".preview.{}".format(fmt)
|
|
119
118
|
|
|
120
|
-
with
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
with (
|
|
120
|
+
TemporaryFile() as xml_fh,
|
|
121
|
+
NamedTemporaryFile(suffix=prvw_sfx, delete=False) as img_fh,
|
|
122
|
+
):
|
|
123
123
|
# save part to musicxml in file handle xml_fh
|
|
124
124
|
save_musicxml(score_data, xml_fh)
|
|
125
125
|
# rewind read pointer of file handle before we pass it to musicxml2ly
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
"""
|
|
4
4
|
This module contains methods for exporting Kern files.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import math
|
|
7
8
|
from collections import defaultdict
|
|
9
|
+
from importlib.metadata import version
|
|
8
10
|
|
|
9
11
|
import numpy
|
|
10
12
|
|
|
@@ -19,6 +21,9 @@ from partitura.utils.misc import deprecated_alias, PathLike
|
|
|
19
21
|
__all__ = ["save_kern"]
|
|
20
22
|
|
|
21
23
|
|
|
24
|
+
VERSION = version("partitura")
|
|
25
|
+
|
|
26
|
+
|
|
22
27
|
ACC_TO_SIGN = {
|
|
23
28
|
0: "n",
|
|
24
29
|
-1: "-",
|
|
@@ -327,7 +332,7 @@ def save_kern(
|
|
|
327
332
|
out_data = exporter.parse()
|
|
328
333
|
out_data = exporter.trim(out_data)
|
|
329
334
|
# Use numpy savetxt to save the file
|
|
330
|
-
footer = "Encoded using the Partitura Python package, version
|
|
335
|
+
footer = f"Encoded using the Partitura Python package, version {VERSION}"
|
|
331
336
|
if out is not None:
|
|
332
337
|
np.savetxt(
|
|
333
338
|
fname=out,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
This module contains methods for exporting MIDI files
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import numpy as np
|
|
7
8
|
|
|
8
9
|
from collections import defaultdict, OrderedDict
|
|
@@ -405,6 +406,12 @@ def save_score_midi(
|
|
|
405
406
|
if not tempos:
|
|
406
407
|
tempos[0] = MetaMessage("set_tempo", tempo=500000)
|
|
407
408
|
|
|
409
|
+
# note velocities
|
|
410
|
+
velocities = []
|
|
411
|
+
for vp in part.iter_all(score.Dynamic):
|
|
412
|
+
velocities.append((vp.start.t, round(90 * vp.velocity / 100)))
|
|
413
|
+
velocities = np.stack(velocities) if velocities else velocities
|
|
414
|
+
|
|
408
415
|
if anacrusis_behavior == "time_sig_change":
|
|
409
416
|
# Change time signature to match the duration of the measure
|
|
410
417
|
# This ensure the beat and downbeats position are coherent
|
|
@@ -486,11 +493,17 @@ def save_score_midi(
|
|
|
486
493
|
# key is a tuple (part_group, part, voice) that will be
|
|
487
494
|
# converted into a (track, channel) pair.
|
|
488
495
|
key = (pg, part, note.voice)
|
|
496
|
+
vel = velocity
|
|
497
|
+
if len(velocities) > 0:
|
|
498
|
+
vel_idx = (
|
|
499
|
+
np.searchsorted(velocities[:, 0], note.start.t, side="right") - 1
|
|
500
|
+
)
|
|
501
|
+
vel = int(velocities[vel_idx, 1])
|
|
489
502
|
events[key][to_ppq(note.start.t)].append(
|
|
490
|
-
Message("note_on", note=note.midi_pitch)
|
|
503
|
+
Message("note_on", note=note.midi_pitch, velocity=vel)
|
|
491
504
|
)
|
|
492
505
|
events[key][to_ppq(note.start.t + note.duration_tied)].append(
|
|
493
|
-
Message("note_off", note=note.midi_pitch)
|
|
506
|
+
Message("note_off", note=note.midi_pitch, velocity=vel)
|
|
494
507
|
)
|
|
495
508
|
event_keys[key] = True
|
|
496
509
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
This module contains methods for exporting MusicXML files.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import math
|
|
7
8
|
from collections import defaultdict
|
|
8
9
|
from lxml import etree
|
|
@@ -777,6 +778,7 @@ def do_directions(part, start, end, counter):
|
|
|
777
778
|
result.append(elem)
|
|
778
779
|
|
|
779
780
|
tempos = part.iter_all(score.Tempo, start, end)
|
|
781
|
+
dynamics = part.iter_all(score.Dynamic, start, end)
|
|
780
782
|
directions = part.iter_all(score.Direction, start, end, include_subclasses=True)
|
|
781
783
|
|
|
782
784
|
for tempo in tempos:
|
|
@@ -791,6 +793,10 @@ def do_directions(part, start, end, counter):
|
|
|
791
793
|
)
|
|
792
794
|
result.append((tempo.start.t, None, e3))
|
|
793
795
|
|
|
796
|
+
for dynamic in dynamics:
|
|
797
|
+
e3 = etree.Element("sound", dynamics="{}".format(dynamic.velocity))
|
|
798
|
+
result.append((dynamic.start.t, None, e3))
|
|
799
|
+
|
|
794
800
|
for direction in directions:
|
|
795
801
|
text = direction.raw_text or direction.text
|
|
796
802
|
|
|
@@ -907,6 +913,9 @@ def do_harmony(part, start, end):
|
|
|
907
913
|
root_e = etree.SubElement(harmony_e, "root")
|
|
908
914
|
root_step_e = etree.SubElement(root_e, "root-step")
|
|
909
915
|
root_step_e.text = h.root
|
|
916
|
+
if h.alter != 0:
|
|
917
|
+
root_alter_e = etree.SubElement(root_e, "root-alter")
|
|
918
|
+
root_alter_e.text = str(h.alter)
|
|
910
919
|
if h.bass is not None:
|
|
911
920
|
bass_e = etree.SubElement(harmony_e, "bass")
|
|
912
921
|
bass_step_e = etree.SubElement(bass_e, "bass-step")
|
|
@@ -1048,6 +1057,22 @@ def save_musicxml(
|
|
|
1048
1057
|
|
|
1049
1058
|
root = etree.Element("score-partwise")
|
|
1050
1059
|
|
|
1060
|
+
# add work metadata
|
|
1061
|
+
if score_data.work_title or score_data.work_number:
|
|
1062
|
+
work_tag = etree.SubElement(root, "work")
|
|
1063
|
+
if score_data.work_title:
|
|
1064
|
+
work_title_tag = etree.SubElement(work_tag, "work_title")
|
|
1065
|
+
work_title_tag.text = str(score_data.work_title)
|
|
1066
|
+
if score_data.work_number:
|
|
1067
|
+
work_number_tag = etree.SubElement(work_tag, "work_number")
|
|
1068
|
+
work_number_tag.text = str(score_data.work_number)
|
|
1069
|
+
if score_data.movement_title:
|
|
1070
|
+
movement_title_tag = etree.SubElement(root, "movement_title")
|
|
1071
|
+
movement_title_tag.text = str(score_data.movement_title)
|
|
1072
|
+
if score_data.movement_number:
|
|
1073
|
+
movement_number_tag = etree.SubElement(root, "movement_number")
|
|
1074
|
+
movement_number_tag.text = str(score_data.movement_number)
|
|
1075
|
+
|
|
1051
1076
|
partlist_e = etree.SubElement(root, "part-list")
|
|
1052
1077
|
state = {
|
|
1053
1078
|
"note_id_counter": {},
|
|
@@ -4,6 +4,8 @@ from math import ceil
|
|
|
4
4
|
import partitura.score as spt
|
|
5
5
|
from partitura.score import process_local_key
|
|
6
6
|
from partitura.utils.music import estimate_symbolic_duration
|
|
7
|
+
from pandas.api.types import is_object_dtype
|
|
8
|
+
from pandas.api.types import is_string_dtype
|
|
7
9
|
|
|
8
10
|
try:
|
|
9
11
|
import pandas as pd
|
|
@@ -19,7 +21,8 @@ def read_note_tsv(note_tsv_path, metadata=None):
|
|
|
19
21
|
data = data[~data["quarterbeats"].isna()]
|
|
20
22
|
data["quarterbeats"] = (
|
|
21
23
|
data["quarterbeats"].apply(eval)
|
|
22
|
-
if data.dtypes["quarterbeats"]
|
|
24
|
+
if is_string_dtype(data.dtypes["quarterbeats"])
|
|
25
|
+
or is_object_dtype(data.dtypes["quarterbeats"])
|
|
23
26
|
else data["quarterbeats"]
|
|
24
27
|
)
|
|
25
28
|
unique_durations = data["duration"].unique()
|
|
@@ -204,7 +207,8 @@ def read_measure_tsv(measure_tsv_path, part):
|
|
|
204
207
|
data = data[~data["quarterbeats"].isna()]
|
|
205
208
|
data["quarterbeats"] = (
|
|
206
209
|
data["quarterbeats"].apply(eval)
|
|
207
|
-
if data.dtypes["quarterbeats"]
|
|
210
|
+
if is_string_dtype(data.dtypes["quarterbeats"])
|
|
211
|
+
or is_object_dtype(data.dtypes["quarterbeats"])
|
|
208
212
|
else data["quarterbeats"]
|
|
209
213
|
)
|
|
210
214
|
data["onset_div"] = np.array([int(qd * qdivs) for qd in data["quarterbeats"]])
|
|
@@ -239,7 +243,8 @@ def read_harmony_tsv(beat_tsv_path, part):
|
|
|
239
243
|
data = data[~data["quarterbeats"].isna()]
|
|
240
244
|
data["quarterbeats"] = (
|
|
241
245
|
data["quarterbeats"].apply(eval)
|
|
242
|
-
if data.dtypes["quarterbeats"]
|
|
246
|
+
if is_string_dtype(data.dtypes["quarterbeats"])
|
|
247
|
+
or is_object_dtype(data.dtypes["quarterbeats"])
|
|
243
248
|
else data["quarterbeats"]
|
|
244
249
|
)
|
|
245
250
|
data["onset_div"] = np.array([int(qd * qdivs) for qd in data["quarterbeats"]])
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
This module contains methods for parsing matchfiles
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import os
|
|
7
8
|
from typing import Union, Tuple, Optional, Callable, List
|
|
8
9
|
import warnings
|
|
@@ -516,7 +517,9 @@ def part_from_matchfile(
|
|
|
516
517
|
|
|
517
518
|
# ___ these divs are relative to quarters;
|
|
518
519
|
divs = np.lcm.reduce(np.unique(divs_arg))
|
|
519
|
-
onset_in_divs = np.r_[0, np.cumsum(divs * iois_in_quarters, dtype=int)][
|
|
520
|
+
onset_in_divs = np.r_[0, np.cumsum(np.round(divs * iois_in_quarters), dtype=int)][
|
|
521
|
+
inv_idxs
|
|
522
|
+
]
|
|
520
523
|
onset_in_quarters = onset_in_quarters[inv_idxs]
|
|
521
524
|
|
|
522
525
|
part.set_quarter_duration(0, divs)
|