├── .flake8
├── .github
└── workflows
│ ├── linting.yml
│ ├── partitura_unittests.yml
│ ├── pypi_publish.yml
│ └── stale.yml
├── .gitignore
├── .readthedocs.yml
├── CHANGES.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── docs
├── Makefile
├── make.bat
├── requirements.txt
└── source
│ ├── Tutorial
│ └── notebook.ipynb
│ ├── conf.py
│ ├── genindex.rst
│ ├── images
│ ├── aknowledge_logo.png
│ ├── aknowledge_logo_negative.png
│ ├── erc_fwf_logos.jpg
│ ├── issue_choosing_label.png
│ ├── issue_page.png
│ ├── open_pull_request.png
│ ├── pull_requests.png
│ ├── score_example.png
│ ├── score_example_1.png
│ ├── score_example_2.png
│ ├── unitest_pass.png
│ └── writing_issue.png
│ ├── index.rst
│ ├── introduction.rst
│ └── modules
│ ├── partitura.musicanalysis.rst
│ ├── partitura.performance.rst
│ ├── partitura.rst
│ ├── partitura.score.rst
│ └── partitura.utils.rst
├── partitura
├── __init__.py
├── assets
│ ├── mei.rng
│ ├── musicxml.xsd
│ ├── partitura_logo_black.png
│ ├── partitura_logo_white.png
│ ├── score_example.krn
│ ├── score_example.mei
│ ├── score_example.mid
│ └── score_example.musicxml
├── directions.py
├── display.py
├── io
│ ├── __init__.py
│ ├── exportaudio.py
│ ├── exportkern.py
│ ├── exportmatch.py
│ ├── exportmei.py
│ ├── exportmidi.py
│ ├── exportmusicxml.py
│ ├── exportparangonada.py
│ ├── importdcml.py
│ ├── importkern.py
│ ├── importmatch.py
│ ├── importmei.py
│ ├── importmidi.py
│ ├── importmusic21.py
│ ├── importmusicxml.py
│ ├── importnakamura.py
│ ├── importparangonada.py
│ ├── matchfile_base.py
│ ├── matchfile_utils.py
│ ├── matchlines_v0.py
│ ├── matchlines_v1.py
│ └── musescore.py
├── musicanalysis
│ ├── __init__.py
│ ├── key_identification.py
│ ├── meter.py
│ ├── note_array_to_score.py
│ ├── note_features.py
│ ├── performance_codec.py
│ ├── performance_features.py
│ ├── pitch_spelling.py
│ ├── tonal_tension.py
│ └── voice_separation.py
├── performance.py
├── score.py
└── utils
│ ├── __init__.py
│ ├── fluidsynth.py
│ ├── generic.py
│ ├── globals.py
│ ├── misc.py
│ ├── music.py
│ ├── normalize.py
│ └── synth.py
├── requirements.txt
├── setup.py
└── tests
├── __init__.py
├── data
├── kern
│ ├── chor228.krn
│ ├── double_repeat_example.krn
│ ├── fine_with_repeat.krn
│ ├── long_example.krn
│ ├── single_voice_example.krn
│ ├── spline_splitting.krn
│ ├── tie_mismatch.krn
│ ├── tuple_durations.krn
│ ├── variable_length_pr_bug.krn
│ └── voice_duplication.krn
├── match
│ ├── Chopin_op10_no3_p01.match
│ ├── mozart_k265_var1.match
│ └── test_fuer_elise.match
├── mei
│ ├── Bach_Hilf_Herr_Jesu.mei
│ ├── Bach_Prelude.mei
│ ├── Beethoven_Op119_Nr01-Breitkopf.mei
│ ├── Beethoven_Op119_Nr02-Breitkopf.mei
│ ├── CRIM_Mass_0030_4.mei
│ ├── Mozart_k265_v1.mei
│ ├── Schubert_An_die_Sonne_D.439.mei
│ ├── mensural.mei
│ ├── test_articulation.mei
│ ├── test_barline.mei
│ ├── test_clefs_tss.mei
│ ├── test_cross_staff_voices.mei
│ ├── test_divs_tuplet.mei
│ ├── test_grace_note.mei
│ ├── test_merge_voices2.mei
│ ├── test_metrical_position.mei
│ ├── test_parts_duration.mei
│ ├── test_parts_duration2.mei
│ ├── test_ties.mei
│ ├── test_tuplets.mei
│ ├── test_tuplets_no_ppq.mei
│ ├── test_unfold_complex.mei
│ └── test_unfold_timeline.mei
├── midi
│ ├── bach_midi_score.mid
│ ├── mozart_k265_var1.mid
│ ├── mozart_k265_var1_quantized.mid
│ ├── test_anacrusis.mid
│ └── test_basic_midi.mid
├── musescore
│ └── 160.03_Pastorale.mscx
├── musicxml
│ ├── Three-Part_Invention_No_13_(fragment).xml
│ ├── example_octave_shift.musicxml
│ ├── mozart_k265_var1.musicxml
│ ├── test_anacrusis.xml
│ ├── test_articulation.xml
│ ├── test_barline.xml
│ ├── test_basic_midi.musicxml
│ ├── test_beats.xml
│ ├── test_chew_vosa_example.xml
│ ├── test_chord_duration.musicxml
│ ├── test_clef.musicxml
│ ├── test_clef_map.musicxml
│ ├── test_clefs_tss.xml
│ ├── test_cross_staff_beaming.musicxml
│ ├── test_cross_staff_voices.musicxml
│ ├── test_grace_note.xml
│ ├── test_harmony.musicxml
│ ├── test_ignore_invisible_objects.musicxml
│ ├── test_length_pianoroll.xml
│ ├── test_merge_interpolation.xml
│ ├── test_merge_voices1.xml
│ ├── test_merge_voices2.xml
│ ├── test_metrical_position.xml
│ ├── test_multi_part.xml
│ ├── test_multi_part_change_divs.xml
│ ├── test_note_features.xml
│ ├── test_note_ties.xml
│ ├── test_note_ties_divs.xml
│ ├── test_part_group.xml
│ ├── test_partial_measures.xml
│ ├── test_partial_measures_consecutive.xml
│ ├── test_pianoroll_sum.xml
│ ├── test_pianoroll_sum_reduced.xml
│ ├── test_polyphonic.xml
│ ├── test_rest.musicxml
│ ├── test_score_object.musicxml
│ ├── test_ts_map_ts_starts_not_at_zero.xml
│ ├── test_tuplet_attributes.musicxml
│ ├── test_unfold_complex.xml
│ ├── test_unfold_complex_result.xml
│ ├── test_unfold_dacapo.xml
│ ├── test_unfold_dacapo_result.xml
│ ├── test_unfold_timeline.xml
│ ├── test_unfold_timeline_result.xml
│ ├── test_unfold_timeline_result_updated_ids.xml
│ ├── test_unfold_volta_numbers.xml
│ └── test_unfold_volta_numbers_result.xml
├── nakamura
│ ├── Shi05_infer_corresp.txt
│ ├── Shi05_infer_match.txt
│ ├── test_nakamura_performance_corresp.txt
│ └── test_nakamura_performance_match.txt
├── parangonada
│ └── mozart_k265_var1
│ │ ├── align.csv
│ │ ├── feature.csv
│ │ ├── part.csv
│ │ ├── ppart.csv
│ │ └── zalign.csv
├── png
│ └── example_score.png
├── tsv
│ ├── test_harmonies.tsv
│ ├── test_measures.tsv
│ └── test_notes.tsv
└── wav
│ └── example_linear_equal_temperament_sr8000.wav
├── temp_test.py
├── test_clef.py
├── test_cross_staff.py
├── test_dcml_import.py
├── test_deprecations.py
├── test_display.py
├── test_fluidsynth.py
├── test_harmony.py
├── test_kern.py
├── test_key_estimation.py
├── test_load_performance.py
├── test_load_score.py
├── test_m21_import.py
├── test_match_export.py
├── test_match_import.py
├── test_mei.py
├── test_merge_parts.py
├── test_metrical_position.py
├── test_midi_export.py
├── test_midi_import.py
├── test_musescore.py
├── test_nakamura.py
├── test_new_divs.py
├── test_note_array.py
├── test_note_features.py
├── test_octave_shift.py
├── test_parangonada.py
├── test_part_properties.py
├── test_partial_measures.py
├── test_performance.py
├── test_performance_codec.py
├── test_performance_features.py
├── test_pianoroll.py
├── test_pitch_spelling.py
├── test_quarter_adjust.py
├── test_rest_array.py
├── test_synth.py
├── test_time_estimation.py
├── test_times.py
├── test_tonal_tension.py
├── test_transpose.py
├── test_urlload.py
├── test_utils.py
├── test_voice_estimation.py
└── test_xml.py
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length = 88
3 | per-file-ignores = __init__.py:F401
4 |
--------------------------------------------------------------------------------
/.github/workflows/linting.yml:
--------------------------------------------------------------------------------
1 | name: Blacken code
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | jobs:
8 | format:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - name: Format code with black
13 | run: |
14 | pip install black
15 | black ./partitura
16 | - name: Commit changes
17 | uses: EndBug/add-and-commit@v4
18 | with:
19 | author_name: ${{ github.actor }}
20 | author_email: ${{ github.actor }}@users.noreply.github.com
21 | message: "Format code with black (bot)"
22 | add: "."
23 | - name: Notify errors
24 | if: failure()
25 | uses: dawidd6/action-send-mail@v2
26 | with:
27 | server_address: smtp.gmail.com
28 | server_port: 465
29 | username: ${{ secrets.EMAIL_USERNAME }}
30 | password: ${{ secrets.EMAIL_PASSWORD }}
31 | subject: "Format code with black"
32 | body: "Format code with black failed"
33 | to: ${{ secrets.EMAIL_TO }}
34 | from: ${{ secrets.EMAIL_FROM }}
35 | content_type: text/plain
36 |
--------------------------------------------------------------------------------
/.github/workflows/partitura_unittests.yml:
--------------------------------------------------------------------------------
1 | name: Partitura Unittests
2 |
3 | on:
4 | push:
5 | branches: [main, develop]
6 | pull_request:
7 | branches: [develop]
8 |
9 | jobs:
10 | test:
11 | strategy:
12 | max-parallel: 5
13 | matrix:
14 | platform: [ubuntu-latest, macos-latest, windows-latest]
15 |
16 | runs-on: ${{ matrix.platform }}
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Set up Python 3.8
20 | uses: actions/setup-python@v2
21 | with:
22 | python-version: 3.8
23 | - name: Install dependencies
24 | run: |
25 | python -m pip install --upgrade pip
26 | pip install -r requirements.txt
27 | pip install .
28 | - name: Install Optional dependencies
29 | run: |
30 | pip install music21==8.3.0 Pillow==9.5.0 musescore==0.0.1
31 | pip install miditok==2.0.6 tokenizers==0.13.3 pandas==2.0.3
32 | - name: Run Tests
33 | run: |
34 | pip install coverage
35 | python -m unittest discover ./tests/ 'test*.py'
36 | coverage run -m unittest discover ./tests/ 'test*.py'
37 | coverage xml
38 |
39 | - name: Check coverage with CodeCov
40 | uses: codecov/codecov-action@v1
41 | with:
42 | file: ./coverage.xml
43 | verbose: true
44 |
45 |
--------------------------------------------------------------------------------
/.github/workflows/pypi_publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish to PyPI.org
2 | on:
3 | release:
4 | types: [published]
5 | jobs:
6 | pypi:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout
10 | uses: actions/checkout@v3
11 | with:
12 | fetch-depth: 0
13 | - run: python3 -m pip install --upgrade build && python3 -m build
14 | - name: Publish package
15 | uses: pypa/gh-action-pypi-publish@release/v1
16 | with:
17 | password: ${{ secrets.PYPI_API_TOKEN }}
18 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: "Close stale issues and PRs"
2 |
3 | on:
4 | schedule:
5 | # Every day at 00:00
6 | - cron: "0 0 * * *"
7 | workflow_dispatch:
8 |
9 | jobs:
10 | stale:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/stale@v4.0.0
15 | with:
16 | stale-issue-message: 'This issue had no activity for **6 months**. It will be closed in **2 weeks** unless there is some new activity. Is this issue already resolved?'
17 | stale-issue-label: 'stale'
18 | exempt-issue-labels: 'bug,enhancement,good first issue'
19 | stale-pr-message: 'This pull request had no activity for **6 months**. It will be closed in **2 weeks** unless there is some new activity.'
20 | stale-pr-label: 'stale'
21 | days-before-stale: 180
22 | days-before-close: 14
23 | operations-per-run: 200
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | +.pyc
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | pip-wheel-metadata/
25 | share/python-wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 | MANIFEST
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .nox/
45 | .coverage
46 | .coverage.*
47 | .cache
48 | nosetests.xml
49 | coverage.xml
50 | *.cover
51 | *.py,cover
52 | .hypothesis/
53 | .pytest_cache/
54 | cover/
55 |
56 | # Translations
57 | *.mo
58 | *.pot
59 |
60 | # Django stuff:
61 | *.log
62 | local_settings.py
63 | db.sqlite3
64 | db.sqlite3-journal
65 |
66 | # Flask stuff:
67 | instance/
68 | .webassets-cache
69 |
70 | # Scrapy stuff:
71 | .scrapy
72 |
73 | # Sphinx documentation
74 | docs/_build/
75 |
76 | # PyBuilder
77 | .pybuilder/
78 | target/
79 |
80 | # Jupyter Notebook
81 | .ipynb_checkpoints
82 |
83 | # IPython
84 | profile_default/
85 | ipython_config.py
86 |
87 | # pyenv
88 | # For a library or package, you might want to ignore these files since the code is
89 | # intended to run in multiple environments; otherwise, check them in:
90 | # .python-version
91 |
92 | # pipenv
93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
96 | # install all needed dependencies.
97 | #Pipfile.lock
98 |
99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
100 | __pypackages__/
101 |
102 | # Celery stuff
103 | celerybeat-schedule
104 | celerybeat.pid
105 |
106 | # SageMath parsed files
107 | *.sage.py
108 |
109 | # Environments
110 | .env
111 | .venv
112 | env/
113 | venv/
114 | ENV/
115 | env.bak/
116 | venv.bak/
117 |
118 | # Spyder project settings
119 | .spyderproject
120 | .spyproject
121 |
122 | # Rope project settings
123 | .ropeproject
124 |
125 | # mkdocs documentation
126 | /site
127 |
128 | # mypy
129 | .mypy_cache/
130 | .dmypy.json
131 | dmypy.json
132 |
133 | # Pyre type checker
134 | .pyre/
135 |
136 | # pytype static type analyzer
137 | .pytype/
138 |
139 | # Cython debug symbols
140 | cython_debug/
141 |
142 | # static files generated from Django application using `collectstatic`
143 | media
144 | static
145 |
146 | .DS_Store
147 | *#
148 | *~
149 |
150 | # vscode
151 | .vscode
152 |
153 | # phdocs
154 | phdocs.txt
155 |
156 | # fluidsynth default soundfont
157 | partitura/assets/MuseScore_General.sf*
158 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 |
2 | # .readthedocs.yaml
3 | # Read the Docs configuration file
4 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
5 |
6 | # Required
7 | version: 2
8 |
9 | # Set the version of Python and other tools you might need
10 | build:
11 | os: ubuntu-20.04
12 | tools:
13 | python: "3.8"
14 |
15 | #mkdocs:
16 | # configuration: mkdocs.yml
17 |
18 | # Optionally declare the Python requirements required to build your docs
19 | python:
20 | install:
21 | - requirements: docs/requirements.txt
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | You can help the developers of **Partitura** by contributing, requesting features or reporting error.
4 |
5 | ## Opening an Issue
6 |
7 | To open an issue navigate to the partitura github repository:
8 |
9 | [Repository]: https://github.com/CPJKU/partitura/issues "Partitura Issues Link"
10 |
11 | #### Click to **New Issue**
12 |
13 | 
14 |
15 | #### Write your description
16 |
17 | 
18 |
19 | #### Choose the appropriate label
20 |
21 | 
22 |
23 | ##### How to choose your issue label:
24 |
25 | - **Question** to ask us a question or **help wanted** if you need a solution to a particular partitura problem.
26 | - **Bug** to report something not working correctly.
27 | - **Enhancement** to request for a feature.
28 |
29 | ## How to contribute
30 |
31 | A step by step guide :
32 |
33 | 1. To contribute is to open a relevant issue.
34 | 2. ***Fork*** the Partitura repo.
35 | 3. *Checkout* or *Pull* the latest stable develop branch.
36 | 4. *Checkout a new branch* from the develop with the name of your develop idea.
37 | 5. When finished coding, open a pull request to the develop branch of partitura.
38 |
39 | ### Open a relevant issue
40 |
41 | Follow section how to open an issue.
42 |
43 | ### **Fork** the Repo
44 |
45 | Fork partitura from
46 | https://github.com/CPJKU/partitura
47 |
48 | Once that you have already forked the repo, you can clone it:
49 | ```shell
50 | git clone https://github.com/YourUsername/partitura.git
51 | cd partitura
52 | ```
53 |
54 | ### Get latest Develop Branch
55 |
56 | ```shell
57 | git fetch upstream
58 | git checkout develop
59 | git pull
60 | ```
61 |
62 | ### Create your Branch
63 |
64 | ```shel
65 | git checkout -b mycrazyidea
66 | ```
67 |
68 | Do your coding magic!!!
69 |
70 | Remember to commit regularly with descriptive messages about your changes.
71 |
72 | **!!! IMPORTANT NOTE !!!**
73 |
74 | Write Unit tests to check the compatibility and assure the evolution of your features.
75 |
76 | *Please follow instruction script found in the Tutorial repository.*
77 |
78 | ### Opening your Pull Request
79 |
80 | ##### Go to your forked Partitura repo and Click New Pull Request
81 |
82 | Open a Pull request from your new branch into the original `https://github.com/CPJKU/partitura` **develop** branch.
83 |
84 | Your pull request should then be visible on:
85 |
86 | [Partitura Pull Requests]: https://github.com/CPJKU/partitura/pulls "Partitura Pull Requests"
87 |
88 | 
89 |
90 | ##### Set the base to develop and the compare to your branch
91 |
92 | 
93 |
94 | ##### Then create your Pull Request and add a description.
95 |
96 | When you create your PR then the partitura Unitests including the Unit Tests you wrote are ran.
97 |
98 | If there is no conflict with the develop branch then you will see this on your screen :
99 |
100 | 
101 |
102 | If indeed the tests pass then a person from the development team of Partitura will review your work and accept your Pull Request.
103 |
104 | Your features will then be included to the next release of Partitura or a discussion will kick-start on your pull request thread.
105 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | partitura
2 | sphinx==6.1.3
3 | nbsphinx==0.8.12
4 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
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 | import pkg_resources
16 |
17 | sys.path.insert(0, os.path.abspath("../../partitura"))
18 | # The master toctree document.
19 | master_doc = "index"
20 |
21 | # -- Project information -----------------------------------------------------
22 |
23 | project = "partitura"
24 | # copyright = '2019, Maarten Grachten'
25 | author = "Maarten Grachten, Carlos Cancino-Chacón, Silvan Peter, Emmanouil Karystinaios, Francesco Foscarin, Thassilo Gadermaier"
26 |
27 | # The version info for the project you're documenting, acts as replacement for
28 | # |version| and |release|, also used in various other places throughout the
29 | # built documents.
30 | #
31 | # The short X.Y version.
32 | version = "1.6.0" # pkg_resources.get_distribution("partitura").version
33 | # The full version, including alpha/beta/rc tags.
34 | release = "1.6.0"
35 |
36 | # # The full version, including alpha/beta/rc tags
37 | # release = pkg_resources.get_distribution("partitura").version
38 | # # release = '0.1.0-pre'
39 |
40 | # The language for content autogenerated by Sphinx. Refer to documentation
41 | # for a list of supported languages.
42 | #
43 | # This is also used if you do content translation via gettext catalogs.
44 | # Usually you set "language" from the command line for these cases.
45 | language = "python"
46 |
47 |
48 | # -- General configuration ---------------------------------------------------
49 |
50 | # List of patterns, relative to source directory, that match files and
51 | # directories to ignore when looking for source files.
52 | exclude_patterns = ["_build"]
53 |
54 | # The name of the Pygments (syntax highlighting) style to use.
55 | pygments_style = "sphinx"
56 |
57 | # Add any Sphinx extension module names here, as strings. They can be
58 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
59 | # ones.
60 | extensions = [
61 | "sphinx.ext.autodoc",
62 | "sphinx.ext.autosummary",
63 | "sphinx.ext.doctest",
64 | "sphinx.ext.todo",
65 | "sphinx.ext.coverage",
66 | "sphinx.ext.mathjax",
67 | "sphinx.ext.viewcode",
68 | # 'sphinxcontrib.napoleon',
69 | "sphinx.ext.napoleon",
70 | "nbsphinx",
71 | # 'sphinxcontrib.bibtex', # for bibliographic references
72 | # 'sphinxcontrib.rsvgconverter', # for SVG->PDF conversion in LaTeX output
73 | # 'sphinx_gallery.load_style', # load CSS for gallery (needs SG >= 0.6)
74 | # 'sphinx_last_updated_by_git', #? get "last updated" from Git
75 | # 'sphinx_codeautolink', # automatic links from code to documentation
76 | # 'sphinx.ext.intersphinx', # links to other Sphinx projects (e.g. NumPy)
77 | ]
78 |
79 | # These projects are also used for the sphinx_codeautolink extension:
80 | intersphinx_mapping = {
81 | "IPython": ("https://ipython.readthedocs.io/en/stable/", None),
82 | "matplotlib": ("https://matplotlib.org/", None),
83 | "numpy": ("https://docs.scipy.org/doc/numpy/", None),
84 | "pandas": ("https://pandas.pydata.org/docs/", None),
85 | "python": ("https://docs.python.org/3/", None),
86 | }
87 |
88 | # see http://stackoverflow.com/q/12206334/562769
89 | numpydoc_show_class_members = False
90 |
91 | # Add any paths that contain templates here, relative to this directory.
92 | templates_path = ["_templates"]
93 |
94 | # The suffix(es) of source filenames.
95 | # You can specify multiple suffix as a list of string:
96 | # source_suffix = ['.rst', '.md']
97 | source_suffix = ".rst"
98 |
99 | # List of patterns, relative to source directory, that match files and
100 | # directories to ignore when looking for source files.
101 | # This pattern also affects html_static_path and html_extra_path.
102 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
103 |
104 |
105 | # -- Options for HTML output -------------------------------------------------
106 |
107 | # The theme to use for HTML and HTML Help pages. See the documentation for
108 | # a list of builtin themes.
109 | #
110 | # only import and set the theme if we're building docs locally
111 | if os.environ.get("READTHEDOCS") != "True":
112 | import sphinx_rtd_theme
113 |
114 | html_theme = "sphinx_rtd_theme"
115 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
116 | else:
117 | html_theme = "default"
118 |
119 | # Add any paths that contain custom static files (such as style sheets) here,
120 | # relative to this directory. They are copied after the builtin static files,
121 | # so a file named "default.css" will overwrite the builtin "default.css".
122 | # html_static_path = ['_static']
123 |
124 | # Output file base name for HTML help builder.
125 | htmlhelp_basename = "partituradoc"
126 |
--------------------------------------------------------------------------------
/docs/source/genindex.rst:
--------------------------------------------------------------------------------
1 | Index
2 | =====
3 |
--------------------------------------------------------------------------------
/docs/source/images/aknowledge_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/aknowledge_logo.png
--------------------------------------------------------------------------------
/docs/source/images/aknowledge_logo_negative.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/aknowledge_logo_negative.png
--------------------------------------------------------------------------------
/docs/source/images/erc_fwf_logos.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/erc_fwf_logos.jpg
--------------------------------------------------------------------------------
/docs/source/images/issue_choosing_label.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/issue_choosing_label.png
--------------------------------------------------------------------------------
/docs/source/images/issue_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/issue_page.png
--------------------------------------------------------------------------------
/docs/source/images/open_pull_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/open_pull_request.png
--------------------------------------------------------------------------------
/docs/source/images/pull_requests.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/pull_requests.png
--------------------------------------------------------------------------------
/docs/source/images/score_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/score_example.png
--------------------------------------------------------------------------------
/docs/source/images/score_example_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/score_example_1.png
--------------------------------------------------------------------------------
/docs/source/images/score_example_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/score_example_2.png
--------------------------------------------------------------------------------
/docs/source/images/unitest_pass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/unitest_pass.png
--------------------------------------------------------------------------------
/docs/source/images/writing_issue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/docs/source/images/writing_issue.png
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. partitura documentation master file, created by
2 | sphinx-quickstart on Thu Aug 15 18:48:12 2019.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Partitura documentation
7 | =======================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 |
12 | introduction
13 | Tutorial/notebook.ipynb
14 | genindex
15 |
16 | .. _api_reference:
17 |
18 | .. toctree::
19 | :maxdepth: 2
20 | :caption: API Reference
21 |
22 | ./modules/partitura
23 | ./modules/partitura.score
24 | ./modules/partitura.performance
25 | ./modules/partitura.musicanalysis
26 | ./modules/partitura.utils
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/source/modules/partitura.musicanalysis.rst:
--------------------------------------------------------------------------------
1 | partitura.musicanalysis
2 | =======================
3 | .. currentmodule:: partitura.musicanalysis
4 | .. automodule:: partitura.musicanalysis
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | ..
10 | partitura.musicanalysis.voice\_separation
11 | -----------------------------------------
12 |
13 | .. toctree::
14 |
15 | .. automodule:: partitura.musicanalysis.voice_separation
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
20 | partitura.musicanalysis.key\_identification
21 | -------------------------------------------
22 |
23 | .. automodule:: partitura.musicanalysis.key_identification
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
28 | partitura.musicanalysis.pitch\_spelling
29 | ---------------------------------------
30 |
31 | .. automodule:: partitura.musicanalysis.pitch_spelling
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:
35 |
36 |
--------------------------------------------------------------------------------
/docs/source/modules/partitura.performance.rst:
--------------------------------------------------------------------------------
1 | partitura.performance
2 | ---------------------
3 |
4 | .. automodule:: partitura.performance
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 |
--------------------------------------------------------------------------------
/docs/source/modules/partitura.rst:
--------------------------------------------------------------------------------
1 | partitura
2 | ---------
3 |
4 | .. automodule:: partitura
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 | :member-order: bysource
9 |
--------------------------------------------------------------------------------
/docs/source/modules/partitura.score.rst:
--------------------------------------------------------------------------------
1 | partitura.score
2 | ---------------
3 |
4 | .. automodule:: partitura.score
5 | :member-order: bysource
6 | :members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/modules/partitura.utils.rst:
--------------------------------------------------------------------------------
1 | partitura.utils
2 | ---------------
3 |
4 | ..
5 | we need this import for `make doctest` to work. Without it, it will not find
6 | the names of members imported in partitura/utils/__init__.py
7 |
8 | .. testsetup:: *
9 |
10 | from partitura.utils import *
11 |
12 | .. automodule:: partitura.utils
13 | :members:
14 |
--------------------------------------------------------------------------------
/partitura/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | """
4 | The top level of the package contains functions to load and save
5 | data, display rendered scores, and functions to estimate pitch
6 | spelling, voice assignment, and key signature.
7 | """
8 |
9 | import pkg_resources
10 |
11 | from .io import load_score, load_performance, load_score_as_part, lp
12 | from .io.musescore import load_via_musescore
13 | from .io.importmusicxml import load_musicxml, musicxml_to_notearray
14 | from .io.exportmusicxml import save_musicxml
15 | from .io.importmei import load_mei
16 | from .io.importkern import load_kern
17 | from .io.importmusic21 import load_music21
18 | from .io.importdcml import load_dcml
19 | from .io.importmidi import load_score_midi, load_performance_midi, midi_to_notearray
20 | from .io.exportmidi import save_score_midi, save_performance_midi
21 | from .io.importmatch import load_match
22 | from .io.exportmatch import save_match
23 | from .io.importnakamura import load_nakamuramatch, load_nakamuracorresp
24 | from .io.importparangonada import load_parangonada_csv
25 | from .io.exportparangonada import save_parangonada_csv, save_csv_for_parangonada
26 | from .io.exportaudio import save_wav, save_wav_fluidsynth
27 | from .io.exportmei import save_mei
28 | from .display import render
29 | from . import musicanalysis
30 | from .musicanalysis import make_note_features, compute_note_array, full_note_array
31 |
32 |
33 | # define a version variable
34 | __version__ = pkg_resources.get_distribution("partitura").version
35 |
36 | #: An example MusicXML file for didactic purposes
37 | EXAMPLE_MUSICXML = pkg_resources.resource_filename(
38 | "partitura", "assets/score_example.musicxml"
39 | )
40 |
41 | EXAMPLE_MIDI = pkg_resources.resource_filename("partitura", "assets/score_example.mid")
42 | EXAMPLE_MEI = pkg_resources.resource_filename("partitura", "assets/score_example.mei")
43 | EXAMPLE_KERN = pkg_resources.resource_filename("partitura", "assets/score_example.krn")
44 |
45 | __all__ = [
46 | "load_score",
47 | "load_score_as_part",
48 | "load_performance",
49 | "load_musicxml",
50 | "save_musicxml",
51 | "load_mei",
52 | "load_kern",
53 | "musicxml_to_notearray",
54 | "load_score_midi",
55 | "save_score_midi",
56 | "load_via_musescore",
57 | "load_performance_midi",
58 | "save_performance_midi",
59 | "load_match",
60 | "save_match",
61 | "load_dcml",
62 | "load_nakamuramatch",
63 | "load_nakamuracorresp",
64 | "load_parangonada_csv",
65 | "save_parangonada_csv",
66 | "save_wav",
67 | "save_wav_fluidsynth",
68 | "render",
69 | ]
70 |
--------------------------------------------------------------------------------
/partitura/assets/partitura_logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/partitura/assets/partitura_logo_black.png
--------------------------------------------------------------------------------
/partitura/assets/partitura_logo_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/partitura/assets/partitura_logo_white.png
--------------------------------------------------------------------------------
/partitura/assets/score_example.krn:
--------------------------------------------------------------------------------
1 | **kern **kern
2 | *staff2 *staff1
3 | *clefG2 *clefG2
4 | *k[] *k[]
5 | *M4/4 *M4/4
6 | =1- =1-
7 | 1a 2r
8 | . 2cc 2ee
9 | =! =!
10 | *- *-
11 |
--------------------------------------------------------------------------------
/partitura/assets/score_example.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 2024-10-30
13 |
14 |
15 |
16 |
17 |
18 | Verovio
19 | Transcoded from MusicXML
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/partitura/assets/score_example.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/partitura/assets/score_example.mid
--------------------------------------------------------------------------------
/partitura/assets/score_example.musicxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | Piano
9 |
10 |
11 |
12 |
13 |
14 |
15 | 12
16 |
20 |
21 |
22 |
23 |
24 | A
25 | 4
26 |
27 | 48
28 | 1
29 | whole
30 | 2
31 |
32 |
33 | 48
34 |
35 |
36 |
37 | 24
38 | 2
39 | half
40 | 1
41 |
42 |
43 |
44 | C
45 | 5
46 |
47 | 24
48 | 2
49 | half
50 | 1
51 |
52 |
53 |
54 |
55 | E
56 | 5
57 |
58 | 24
59 | 2
60 | half
61 | 1
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/partitura/musicanalysis/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tools for estimating key signature, time signature,
5 | pitch spelling, voice information, tonal tension, as well as methods for
6 | deriving note-level features and performance encodings.
7 | """
8 |
9 | from .voice_separation import estimate_voices
10 | from .key_identification import estimate_key
11 | from .pitch_spelling import estimate_spelling
12 | from .tonal_tension import estimate_tonaltension
13 | from .meter import estimate_time
14 | from .note_features import (
15 | list_note_feats_functions,
16 | make_note_features,
17 | make_note_feats,
18 | compute_note_array,
19 | full_note_array,
20 | make_rest_feats,
21 | make_rest_features,
22 | )
23 | from .performance_codec import encode_performance, decode_performance
24 | from .performance_features import make_performance_features
25 | from .note_array_to_score import note_array_to_score
26 |
27 |
28 | __all__ = [
29 | "estimate_voices",
30 | "estimate_key",
31 | "estimate_spelling",
32 | "estimate_tonaltension",
33 | "estimate_time",
34 | "list_note_feats_functions",
35 | "make_note_features",
36 | "make_rest_features",
37 | "encode_performance",
38 | "decode_performance",
39 | "compute_note_array",
40 | "full_note_array",
41 | "make_performance_features",
42 | "note_array_to_score",
43 | ]
44 |
--------------------------------------------------------------------------------
/partitura/utils/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | Top level of the utilities module.
5 | """
6 |
7 | from partitura.utils.generic import (
8 | ComparableMixin,
9 | ReplaceRefMixin,
10 | partition,
11 | iter_subclasses,
12 | iter_current_next,
13 | sorted_dict_items,
14 | PrettyPrintTree,
15 | find_nearest,
16 | add_field,
17 | show_diff,
18 | search,
19 | _OrderedSet,
20 | )
21 | from partitura.utils.music import (
22 | MIDI_BASE_CLASS,
23 | ALTER_SIGNS,
24 | find_tie_split,
25 | fifths_mode_to_key_name,
26 | key_name_to_fifths_mode,
27 | estimate_symbolic_duration,
28 | format_symbolic_duration,
29 | symbolic_to_numeric_duration,
30 | to_quarter_tempo,
31 | pitch_spelling_to_midi_pitch,
32 | estimate_clef_properties,
33 | ensure_pitch_spelling_format,
34 | ensure_notearray,
35 | compute_pianoroll,
36 | compute_pitch_class_pianoroll,
37 | pianoroll_to_notearray,
38 | match_note_arrays,
39 | key_mode_to_int,
40 | clef_sign_to_int,
41 | clef_int_to_sign,
42 | remove_silence_from_performed_part,
43 | note_array_from_part_list,
44 | slice_notearray_by_time,
45 | note_array_from_part,
46 | note_array_from_note_list,
47 | get_time_units_from_note_array,
48 | update_note_ids_after_unfolding,
49 | note_name_to_pitch_spelling,
50 | note_name_to_midi_pitch,
51 | pitch_spelling_to_note_name,
52 | rest_array_from_part,
53 | rest_array_from_rest_list,
54 | ensure_rest_array,
55 | rest_array_from_part_list,
56 | )
57 | from partitura.utils.synth import synthesize
58 |
59 | from partitura.utils.misc import (
60 | PathLike,
61 | get_document_name,
62 | deprecated_alias,
63 | deprecated_parameter,
64 | )
65 |
66 | from partitura.utils.normalize import normalize
67 |
68 | __all__ = [
69 | "ensure_notearray",
70 | "note_array_from_part",
71 | "ensure_rest_array",
72 | "compute_pianoroll",
73 | "compute_pitch_class_pianoroll",
74 | "pianoroll_to_notearray",
75 | "slice_notearray_by_time",
76 | "key_name_to_fifths_mode",
77 | "fifths_mode_to_key_name",
78 | "key_mode_to_int",
79 | "clef_sign_to_int",
80 | "clef_int_to_sign",
81 | "pitch_spelling_to_midi_pitch",
82 | "pitch_spelling_to_note_name",
83 | "show_diff",
84 | "PrettyPrintTree",
85 | "synthesize",
86 | "normalize",
87 | ]
88 |
--------------------------------------------------------------------------------
/partitura/utils/normalize.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains normalization utilities
5 | """
6 | import numpy as np
7 | from partitura.utils.globals import EPSILON
8 |
9 |
10 | def range_normalize(
11 | array,
12 | min_value=None,
13 | max_value=None,
14 | log=False,
15 | log2=False,
16 | exp=False,
17 | exp2=False,
18 | hard_clip=True,
19 | ):
20 | """
21 | Linear mapping a vector from range [min_value, max_value] to [0, 1].
22 | Preprocessing possible with log and exp.
23 | Values exceeding the range [0, 1] are clipped to 0 or 1 if
24 | clip is True, otherwise they are extrapolated.
25 | """
26 | if min_value is None:
27 | min_value = array.min()
28 | if max_value is None:
29 | max_value = array.max()
30 | if log:
31 | array = np.log(np.abs(array) + EPSILON)
32 | elif log2:
33 | array = np.log2(np.abs(array) + EPSILON)
34 | if exp:
35 | array = np.exp(array)
36 | elif exp2:
37 | array = np.exp2(array)
38 | # handle div by zero
39 | if min_value == max_value:
40 | array = np.clip(array, 0, 1)
41 | else:
42 | array = (array - min_value) / (max_value - min_value)
43 | if hard_clip:
44 | return np.clip(array, 0, 1)
45 | else:
46 | return array
47 |
48 |
49 | def zero_one_normalize(
50 | array, min_value=-3.0, max_value=3.0, log=False, exp=False, clip=True
51 | ):
52 | """
53 | Compute zero mean and unit variance of a vector.
54 | Preprocessing possible with log and exp.
55 | Values exceeding the range [-min_value, max_value]
56 | are clipped if clip is True.
57 | """
58 |
59 | if log:
60 | array = np.log(np.abs(array) + EPSILON)
61 | if exp:
62 | array = np.exp(array)
63 |
64 | array = (array - array.mean()) / array.std()
65 | if clip:
66 | return np.clip(array, min_value, max_value)
67 | else:
68 | return array
69 |
70 |
71 | def minmaxrange_normalize(array):
72 | """
73 | Linear mapping of a vector from range [array.min(), array.max()] to [0, 1].
74 | Constant vector is clipped to [0, 1].
75 | """
76 | return range_normalize(array)
77 |
78 |
79 | DEFAULT_NORM_FUNCS = {
80 | "pitch": {
81 | "func": range_normalize,
82 | "kwargs": {"min_value": 0, "max_value": 127},
83 | },
84 | "velocity": {
85 | "func": range_normalize,
86 | "kwargs": {"min_value": 0, "max_value": 127},
87 | },
88 | "onset_beat": {
89 | "func": minmaxrange_normalize,
90 | "kwargs": {},
91 | },
92 | "duration_beat": {
93 | "func": range_normalize,
94 | "kwargs": {"min_value": -3, "max_value": 3, "log2": True},
95 | # ref beat = 4th -> -3 = 32nd, 3 = breve
96 | },
97 | "beat_period": {
98 | "func": range_normalize,
99 | "kwargs": {"min_value": -3, "max_value": 2, "log2": True},
100 | # ref 1 second / beat -> -3 = 0.125 sec / beat , 2 = 4 sec / beat
101 | },
102 | "timing": {
103 | "func": range_normalize,
104 | "kwargs": {"min_value": -0.2, "max_value": 0.2},
105 | # deviation in seconds
106 | },
107 | "articulation_log": {
108 | "func": range_normalize,
109 | "kwargs": {"min_value": -4, "max_value": 3},
110 | # thia ia the ratio in base2 log -> just min max clip
111 | },
112 | # fill up with all note and performance features
113 | }
114 |
115 |
116 | def normalize(
117 | in_array,
118 | norm_funcs=DEFAULT_NORM_FUNCS,
119 | norm_func_fallback=minmaxrange_normalize,
120 | default_value=np.inf,
121 | ):
122 | """
123 | Normalize a note array.
124 | May include note features as well as performance features.
125 | All input columns must be of numeric types, everything is
126 | cast to single precision float.
127 |
128 | Parameters
129 | ----------
130 | array : np.ndarray
131 | The performance array to be normalized.
132 | norm_funcs : dict
133 | A dictionary of normalization functions for each feature.
134 |
135 | Returns
136 | -------
137 | array : np.ndarray
138 | The normalized performance array.
139 | """
140 | dtype_new = np.dtype(
141 | {
142 | "names": in_array.dtype.names,
143 | "formats": [float for k in range(len(in_array.dtype.names))],
144 | }
145 | )
146 | array = in_array.copy().astype(dtype_new)
147 |
148 | for feature in array.dtype.names:
149 | # use mask for non-default values and don't change default values
150 | non_default_mask = array[feature] != default_value
151 |
152 | # check whether the feature has non-uniform values
153 | if len(np.unique(array[feature][non_default_mask])) == 1:
154 | array[feature][non_default_mask] = 0.0
155 | else:
156 | # check whether a normalization function is defined for the feature
157 | if feature not in norm_funcs:
158 | array[feature][non_default_mask] = norm_func_fallback(
159 | array[feature][non_default_mask]
160 | )
161 | else:
162 | array[feature][non_default_mask] = norm_funcs[feature]["func"](
163 | array[feature][non_default_mask], **norm_funcs[feature]["kwargs"]
164 | )
165 |
166 | return array
167 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | scipy
3 | xmlschema
4 | lxml
5 | lark-parser
6 | mido
7 | nbsphinx
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import io
5 | import os
6 | import sys
7 | from shutil import rmtree
8 |
9 | from setuptools import find_packages, setup, Command
10 |
11 | # Package meta-data.
12 | NAME = "partitura"
13 | DESCRIPTION = "A package for handling symbolic musical information"
14 | KEYWORDS = "music notation musicxml midi"
15 | URL = "https://github.com/CPJKU/partitura"
16 | EMAIL = "partitura-users@googlegroups.com"
17 | AUTHOR = "Maarten Grachten, Carlos Cancino-Chacón, Silvan Peter, Emmanouil Karystinaios, Francesco Foscarin, Thassilo Gadermaier, Patricia Hu"
18 | REQUIRES_PYTHON = ">=3.7"
19 | VERSION = "1.6.0"
20 |
21 | # What packages are required for this module to be executed?
22 | REQUIRED = ["numpy", "scipy", "lxml", "lark-parser", "xmlschema", "mido"]
23 |
24 | # What packages are optional?
25 | EXTRAS = {}
26 |
27 | here = os.path.abspath(os.path.dirname(__file__))
28 |
29 | try:
30 | with io.open(os.path.join(here, "README.md"), encoding="utf-8") as f:
31 | long_description = "\n" + f.read()
32 | except FileNotFoundError:
33 | long_description = DESCRIPTION
34 |
35 | # Load the package's __version__.py module as a dictionary.
36 | about = {}
37 | if not VERSION:
38 | with open(os.path.join(here, NAME, "__version__.py")) as f:
39 | exec(f.read(), about)
40 | else:
41 | about["__version__"] = VERSION
42 |
43 |
44 | # Where the magic happens:
45 | setup(
46 | name=NAME,
47 | version=about["__version__"],
48 | description=DESCRIPTION,
49 | long_description=long_description,
50 | long_description_content_type="text/markdown",
51 | keywords=KEYWORDS,
52 | author=AUTHOR,
53 | author_email=EMAIL,
54 | python_requires=REQUIRES_PYTHON,
55 | url=URL,
56 | packages=find_packages(exclude=("tests",)),
57 | package_data={
58 | "partitura": [
59 | "assets/musicxml.xsd",
60 | "assets/score_example.mid",
61 | "assets/score_example.musicxml",
62 | "assets/score_example.krn",
63 | "assets/score_example.mei",
64 | ]
65 | },
66 | install_requires=REQUIRED,
67 | extras_require=EXTRAS,
68 | include_package_data=True,
69 | license="Apache 2.0",
70 | classifiers=[
71 | # Trove classifiers
72 | # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
73 | "License :: OSI Approved :: MIT License",
74 | "Programming Language :: Python",
75 | "Programming Language :: Python :: 3",
76 | "Programming Language :: Python :: Implementation :: CPython",
77 | "Programming Language :: Python :: Implementation :: PyPy",
78 | ],
79 | )
80 |
--------------------------------------------------------------------------------
/tests/data/kern/chor228.krn:
--------------------------------------------------------------------------------
1 | !!!!SEGMENT: chor228.krn
2 | !!!COM: Bach, Johann Sebastian
3 | !!!CDT: 1685/02/21/-1750/07/28/
4 | !!!OTL@@DE: Danket dem Herren, denn er ist sehr freundlich
5 | !!!SCT: BWV 286
6 | !!!PC#: 228
7 | !!!AGN: chorale
8 | **kern **kern **kern **kern
9 | *ICvox *ICvox *ICvox *ICvox
10 | *IGrand *IGrand *IGrand *IGrand
11 | *Ibass *Itenor *Ialto *Isoprn
12 | *tb *tb *tb *tb
13 | *ITr *ITr *ITr *ITr
14 | *I"Bass *I"Tenor *I"Alto *I"Soprano
15 | *clefF *clefGv2 *clefG2 *clefG
16 | *k[] *k[] *k[] *k[]
17 | *a: *a: *a: *a:
18 | *M4/4 *M4/4 *M4/4 *M4/4
19 | *met(c) *met(c) *met(c) *met(c)
20 | *MM100 *MM100 *MM100 *MM100
21 | 4A 4c 4e 4a
22 | =1 =1 =1 =1
23 | 4.A 4e 4a 4cc
24 | . 4e [8b 4b
25 | 8G# . 8b_ .
26 | 8AL 4e 8bL] 4cc
27 | 8AAJ . [8aJ .
28 | 4BB [4d 8aL] 4dd
29 | . . 8gnXJ .
30 | =2 =2 =2 =2
31 | 8CL 8dL] 4g 4ee
32 | 8D 16cL . .
33 | . 16BJJ . .
34 | 8E 4c 4g 4ee
35 | 8FJ . . .
36 | 4GnX 4.B 8gL 4dd
37 | . . 8fJ .
38 | 4A . 4e 4cc
39 | . [8A . .
40 | =3 =3 =3 =3
41 | 2E 4A] 2e 2b
42 | . 8G#L . .
43 | . 8F#J . .
44 | 4EE; 4G#; 4e; 4b;
45 | 8EL 4G# 4e 4b
46 | 8DJ . . .
47 | =4 =4 =4 =4
48 | 4C 4A 4e 4ee
49 | 4C 4A 4f# 4dd
50 | 4BB 4B 4g# 4dd
51 | 4AA 8cL [4a 4cc
52 | . 8dJ . .
53 | =5 =5 =5 =5
54 | 4E 4e 8aL] 4b
55 | . . 8g#J .
56 | 8AnXL 4e [4a 4cc
57 | 8GnXJ . . .
58 | 4F 4d 8aL] 4dd
59 | . . 8g#J .
60 | 4E 4e 4a 4cc
61 | =6 =6 =6 =6
62 | 4D 4f 4.a 4b
63 | 4E 8.eL . 4b
64 | . . 8g# .
65 | . 16dJk . .
66 | 4AA; 4c#; 4e; 4a;
67 | == == == ==
68 | *- *- *- *-
69 | !!!hum2abc: -Q ''
70 | !!!title: @{PC#}. @{OTL@@DE}
71 | !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian Bach,
72 | !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und Härtel,
73 | !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 Four-Part
74 | !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1940).
75 | !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
76 | !!!EED: Craig Stuart Sapp
77 | !!!EEV: 2009/05/22
78 |
--------------------------------------------------------------------------------
/tests/data/kern/double_repeat_example.krn:
--------------------------------------------------------------------------------
1 | **kern **kern **kern **kern
2 | *staff2 *staff2 *staff1 *staff1
3 | *clefF4 *clefF4 *clefG2 *clefG2
4 | *k[f#c#g#] *k[f#c#g#] *k[f#c#g#] *k[f#c#g#]
5 | *M4/4 *M4/4 *M4/4 *M4/4
6 | 4AA 4c# 4a 4ee
7 | =1 =1 =1 =1
8 | 8AL 4c# 4a 4ee
9 | 8BJ . . .
10 | 8c#L 4c# 4a 4ee
11 | 8AJ . . .
12 | 8DL 4d 4a 4ff#
13 | 8EJ . . .
14 | 8F#L 4d 4a 4ff#
15 | 8DJ . . .
16 | =2 =2 =2 =2
17 | 2A; 2c#; 2a; 2ee;
18 | 4r 4r 4r 4r
19 | 4A 4e 4a 4cc#
20 | =3 =3 =3 =3
21 | 4G# 4e 4b 4dd
22 | 4A 4e 4a 4cc#
23 | 8EL 4e 4g# 4b
24 | 8DJ . . .
25 | 8C#L 4e [4a 8.cc#L
26 | 8AAJ . . .
27 | . . . 16ddJ
28 | =4 =4 =4 =4
29 | 2E 8eL 8a]L 2b
30 | . 16d 8f#J .
31 | . 16c#J . .
32 | . 4d 4g# .
33 | 4AA; 4c#; 4e; 4a;
34 | =:|! =:| =:| =:|!
35 | *- *- *- *-
36 |
--------------------------------------------------------------------------------
/tests/data/kern/fine_with_repeat.krn:
--------------------------------------------------------------------------------
1 | **kern **kern **kern
2 | *staff2 *staff2 *staff1
3 | *clefG2 *clefG2 *clefG2
4 | *k[] *k[] *k[]
5 | *M3/4 *M3/4 *M3/4
6 | =1- =1- =1-
7 | 4r 4r [4ee
8 | 4c 4g 8.ee]L
9 | . . 16ffJk
10 | 4f 4g 8.ddL
11 | . . 16eeJk
12 | =2 =2 =2
13 | 4e 4g 4cc
14 | 4r 4r 4gg
15 | 4r 4r 4gg
16 | =3 =3 =3
17 | (2B ([2.g (8ggL
18 | . . 8ff)J
19 | . . (8ffL
20 | . . 8ee)J
21 | 4c . (8eeL
22 | . . 8dd)J
23 | =4 =4 =4
24 | 4G) 4g]) 4dd
25 | 4r 4r 4b
26 | 4r 4r 4g
27 | =5 =5 =5
28 | 4r 4r [4ee
29 | 4c 4g 8.ee]L
30 | . . 16ffJk
31 | 4f 4g 8.ddL
32 | . . 16eeJk
33 | =6 =6 =6
34 | 4e 4g 4cc
35 | 4r 4r 4ccc
36 | 4E 4c 4ccc
37 | =7 =7 =7
38 | 4f 4c 16gg#LL
39 | . . 16aaJJ
40 | . . 8r
41 | 4r 4r 16eeLL
42 | . . 16ffJJ
43 | . . 8r
44 | 4Gn 4f 16ddLL
45 | . . 16bJJ
46 | . . 8r
47 | =8 =8 =8
48 | 4c 4e 4cc
49 | 4r 4r 4r
50 | 4r 4r 4r
51 | =:|! =:|! =:|!
52 | *- *- *-
53 |
--------------------------------------------------------------------------------
/tests/data/kern/long_example.krn:
--------------------------------------------------------------------------------
1 | **kern **kern **kern **kern
2 | *staff2 *staff2 *staff1 *staff1
3 | *clefF4 *clefF4 *clefG2 *clefG2
4 | *k[f#c#g#] *k[f#c#g#] *k[f#c#g#] *k[f#c#g#]
5 | *M4/4 *M4/4 *M4/4 *M4/4
6 | 4AA 4c# 4a 4ee
7 | =1 =1 =1 =1
8 | 8AL 4c# 4a 4ee
9 | 8BJ . . .
10 | 8c#L 4c# 4a 4ee
11 | 8AJ . . .
12 | 8DL 4d 4a 4ff#
13 | 8EJ . . .
14 | 8F#L 4d 4a 4ff#
15 | 8DJ . . .
16 | =2 =2 =2 =2
17 | 2A; 2c#; 2a; 2ee;
18 | 4r 4r 4r 4r
19 | 4A 4e 4a 4cc#
20 | =3 =3 =3 =3
21 | 4G# 4e 4b 4dd
22 | 4A 4e 4a 4cc#
23 | 8EL 4e 4g# 4b
24 | 8DJ . . .
25 | 8C#L 4e [4a 8.cc#L
26 | 8AAJ . . .
27 | . . . 16ddJ
28 | =4 =4 =4 =4
29 | 2E 8eL 8a]L 2b
30 | . 16d 8f#J .
31 | . 16c#J . .
32 | . 4d 4g# .
33 | 4AA; 4c#; 4e; 4a;
34 | =:|! =:| =:| =:|!
35 | *- *- *- *-
36 |
--------------------------------------------------------------------------------
/tests/data/kern/single_voice_example.krn:
--------------------------------------------------------------------------------
1 | **kern
2 | *clefG2
3 | *k[b-]
4 | *d:
5 | *M2/2
6 | *met(c)
7 | =1-
8 | 2d
9 | 2a
10 | =2
11 | 2f
12 | 2d
13 | =3
14 | 2c#
15 | 4d
16 | 4e
17 | =4
18 | [2f
19 | 8f]L
20 | 8g
21 | 8f
22 | 8eJ
23 | =5
24 | 4d
25 | *-
26 |
--------------------------------------------------------------------------------
/tests/data/kern/spline_splitting.krn:
--------------------------------------------------------------------------------
1 | **kern **kern **kern **kern
2 | *staff2 *staff2 *staff1 *staff1
3 | *clefF4 *clefF4 *clefG2 *clefG2
4 | *k[f#c#g#] *k[f#c#g#] *k[f#c#g#] *k[f#c#g#]
5 | *M4/4 *M4/4 *M4/4 *M4/4
6 | 4AA 4c# 4a 4ee
7 | =1 =1 =1 =1
8 | * * * *^
9 | 8AL 4c# 4a 4ee 8eee
10 | 8BJ . . . 8eee
11 | 8c#L 4c# 4a 4ee 8ee
12 | 8AJ . . . .
13 | 8DL 4d 4a 4ff# 8fff#
14 | 8EJ . . . 8fff#
15 | 8F#L 4d 4a 4ff# 4fff#
16 | 8DJ . . . .
17 | =2 =2 =2 =2 =2
18 | * * * *v *v
19 | 2A; 2c#; 2a; 2ee;
20 | 4r 4r 4r 4r
21 | 4A 4e 4a 4cc#
22 | =3 =3 =3 =3
23 | 4G# 4e 4b 4dd
24 | 4A 4e 4a 4cc#
25 | 8EL 4e 4g# 4b
26 | 8DJ . . .
27 | 8C#L 4e [4a 8.cc#L
28 | 8AAJ . . .
29 | . . . 16ddJ
30 | =4 =4 =4 =4
31 | *^ * * *
32 | 2.EE 2E 8eL 8a]L 2b
33 | . . 16d 8f#J .
34 | . . 16c#J . .
35 | . . 4d 4g# .
36 | . 4AA; 4c#; 4e; 4a;
37 | =:|! =:|! =:| =:| =:|!
38 | *v *v * * *
39 | *- *- *- *-
--------------------------------------------------------------------------------
/tests/data/kern/tie_mismatch.krn:
--------------------------------------------------------------------------------
1 | **kern
2 | *clefF4
3 | *k[f#c#g#]
4 | *A:
5 | *M3/4
6 | =1-
7 | [8dd
8 | [8aa
9 | 8aa]
10 | [8dd
11 | 8dd]
12 | [8aa
13 | =2
14 | 4aa
15 | 4aa]
16 | [8aa
17 | 8r
18 | ==
19 |
--------------------------------------------------------------------------------
/tests/data/kern/tuple_durations.krn:
--------------------------------------------------------------------------------
1 | **kern
2 | *clefG2
3 | *k[f#c#g#d#]
4 | *M3/4
5 | =1
6 | (8f#L
7 | 8e#J
8 | 4en)
9 | (36d#L
10 | 36e#
11 | 36c#
12 | 36a
13 | 36f##
14 | 36g#
15 | 36dd#
16 | 36aa
17 | 36cc#J
18 | =2
19 | 8b~L
20 | 8a#~J
21 | 4an)
22 | (20gg#L
23 | 20ff#
24 | 20dd#
25 | 20cc#
26 | 20aJ
27 | =3
28 | 8g#)L
29 | (40b
30 | 40a#
31 | 40an
32 | 40e
33 | 40dd#J
34 | 8g#)L
35 | (40b
36 | 40a#
37 | 40an
38 | 40e
39 | 40dd#J
40 | 16g#)
41 | =-
42 | *-
--------------------------------------------------------------------------------
/tests/data/kern/variable_length_pr_bug.krn:
--------------------------------------------------------------------------------
1 | !!!!SEGMENT: chor057.krn
2 | !!!COM: Bach, Johann Sebastian
3 | !!!CDT: 1685/02/21/-1750/07/28/
4 | !!!OTL@@DE: O Traurigkeit, o Herzeleid
5 | !!!SCT: BWV 404
6 | !!!PC#: 57
7 | !!!AGN: chorale
8 | **kern **kern **kern **kern
9 | *ICvox *ICvox *ICvox *ICvox
10 | *Ibass *Itenor *Ialto *Isoprn
11 | *I"Bass *I"Tenor *I"Alto *I"Soprano
12 | *clefF4 *clefGv2 *clefG2 *clefG2
13 | *k[] *k[] *k[] *k[]
14 | *a: *a: *a: *a:
15 | *M4/4 *M4/4 *M4/4 *M4/4
16 | *met(c) *met(c) *met(c) *met(c)
17 | *MM100 *MM100 *MM100 *MM100
18 | 4E 4B 4g# 4ee
19 | =1 =1 =1 =1
20 | 4A 8AL 4e 8ccL
21 | . 8G#J . 8bJ
22 | 4AA 4F# 8eL 4cc
23 | . . 8d#J .
24 | 4E; 4G#; 4e; 4b;
25 | 4DnX 4B 4e 4g#
26 | =2 =2 =2 =2
27 | 4C 4c 4e 4a
28 | 4FnX 8BL 4dnX 4a
29 | . 8AJ . .
30 | 4E; 4B; 4e; 4g#;
31 | 4E 4B 4g#X 4ee
32 | =3 =3 =3 =3
33 | 4A 4c 4a 4ee
34 | 4G# 4B 4b 4ee
35 | 8AL 8cL 4a 4ff
36 | 8BJ 8dJ . .
37 | 4c 8eL 4gnX 8eeL
38 | . 8cJ . 8ddJ
39 | =4 =4 =4 =4
40 | 4F# 4c 4a 2dd
41 | 4GnX 4B 8gL .
42 | . . 8fnXJ .
43 | 2C; 2c; 2e; 2cc;
44 | =5 =5 =5 =5
45 | 4G 4d 4g 4b
46 | 4A 4c 8fL 4cc
47 | . . 8eJ .
48 | 4B 4g 8dL 4dd
49 | . . 8ddJ .
50 | 4c 8GL 4cc 4ee
51 | . 8AJ . .
52 | =6 =6 =6 =6
53 | 4G# 8BL 4b 4dd
54 | . 8EJ . .
55 | 4A 4e 4a 4cc
56 | 2E; 2e; 2g#; 2b;
57 | =7 =7 =7 =7
58 | 4F# (8eL 4e 4a
59 | . 8dJ) . .
60 | 4G# (8dL 4e 4b
61 | . 8cJ) . .
62 | 8AL (8cL 4e 4cc
63 | 8GJ 8BJ) . .
64 | 8FL 4A 8aL 8ddL
65 | 8EJ . 8gnXJ 8eeJ
66 | =8 =8 =8 =8
67 | 4D 4A 4f 2b
68 | 4E 4G# 8eL .
69 | . . 8dJ .
70 | 2AA; 2E; 2c; 2a;
71 | == == == ==
72 | *- *- *- *-
73 | !!!hum2abc: -Q ''
74 | !!!title: @{PC#}. @{OTL@@DE}
75 | !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian Bach,
76 | !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und Härtel,
77 | !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 Four-Part
78 | !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1940).
79 | !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
80 | !!!EED: Craig Stuart Sapp
81 | !!!EEV: 2020/09/05
82 |
--------------------------------------------------------------------------------
/tests/data/kern/voice_duplication.krn:
--------------------------------------------------------------------------------
1 | **kern **kern **kern **kern
2 | *staff2 *staff2 *staff1 *staff1
3 | *clefF4 *clefF4 *clefG2 *clefG2
4 | *k[f#c#] *k[f#c#] *k[f#c#] *k[f#c#]
5 | *M4/4 *M4/4 *M4/4 *M4/4
6 | *b: *b: *b: *b:
7 | *MM58 *MM58 *MM58 *MM58
8 | =1- =1- =1- =1-
9 | [1F# 16A#L 8r 2dd
10 | . 16F# . .
11 | . 16G# 8f# .
12 | . 16A#J . .
13 | . 16BL 8dL .
14 | . 16c# . .
15 | . 16d 8BJ .
16 | . [16BJ . .
17 | . 16B]L 8gL [2cc#
18 | . 16B . .
19 | . 16A# 8f#J .
20 | . 16BJ . .
21 | . 16c#L 8bL .
22 | . 16d . .
23 | . 16e 8a#J .
24 | . 16c#J . .
25 | =2 =2 =2 =2
26 | *^ * * *
27 | 2r 16F#]L 8eL 4f# 4cc#]
28 | . 16AA# . . .
29 | . 16BB 8d#J . .
30 | . 16C#J . . .
31 | . 16D#L 8r 8r 16ccnL
32 | . 16E . . 16a#
33 | . 16FF# 8dn 8g# [8bJ
34 | . 16EE#J . . .
35 | 16r 2FF# 2c# 8f#L 4b]
36 | 16BBL . . . .
37 | 16C# . . 8e#J .
38 | 16DnJ . . . .
39 | 16EnL . . 8.f#L 4a#
40 | 16C# . . . .
41 | [8F#J . . . .
42 | . . . 16enJ .
43 | =76 =76 =76 =76 =76
44 | 1F#] 1BB 1B 1d# 1b
45 | *v *v * * *
46 | == == == ==
47 | *- *- *- *-
--------------------------------------------------------------------------------
/tests/data/mei/test_barline.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 2022-03-16
12 |
13 |
14 |
15 |
16 |
17 | Verovio
18 | Transcoded from MusicXML
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Pno.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/tests/data/mei/test_divs_tuplet.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Untitled score
9 |
10 | Composer / arranger
11 |
12 |
13 |
14 | 2023-08-02
15 |
16 |
17 |
18 |
19 |
20 | Verovio
21 | Transcoded from MusicXML
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Picc.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/tests/data/mei/test_grace_note.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | test grace note
9 |
10 |
11 | 2021-11-04
12 |
13 |
14 |
15 |
16 |
17 | Verovio
18 | Transcoded from MusicXML
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | test grace note
30 |
31 |
32 |
33 |
34 |
35 |
36 | Pno.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/tests/data/mei/test_ties.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Title
9 |
10 | Composer
11 |
12 |
13 | 2021-11-03
14 |
15 |
16 |
17 |
18 |
19 | Verovio
20 | Transcoded from MusicXML
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Title
32 | Composer
33 |
34 |
35 |
36 |
37 | Pno.
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/tests/data/mei/test_tuplets.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | test tuplets
9 |
10 |
11 | 2021-11-02
12 |
13 |
14 |
15 |
16 |
17 | Verovio
18 | Transcoded from MusicXML
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | test tuplets
30 |
31 |
32 |
33 |
34 |
35 |
36 | Pno.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/tests/data/mei/test_tuplets_no_ppq.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | test tuplets
9 |
10 |
11 | 2021-11-02
12 |
13 |
14 |
15 |
16 |
17 | Verovio
18 | Transcoded from MusicXML
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | test tuplets
30 |
31 |
32 |
33 |
34 |
35 |
36 | Pno.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/tests/data/mei/test_unfold_timeline.mei:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Verovio
17 | Transcoded from MusicXML
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/tests/data/midi/bach_midi_score.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/midi/bach_midi_score.mid
--------------------------------------------------------------------------------
/tests/data/midi/mozart_k265_var1.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/midi/mozart_k265_var1.mid
--------------------------------------------------------------------------------
/tests/data/midi/mozart_k265_var1_quantized.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/midi/mozart_k265_var1_quantized.mid
--------------------------------------------------------------------------------
/tests/data/midi/test_anacrusis.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/midi/test_anacrusis.mid
--------------------------------------------------------------------------------
/tests/data/midi/test_basic_midi.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/midi/test_basic_midi.mid
--------------------------------------------------------------------------------
/tests/data/musicxml/example_octave_shift.musicxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | Piano
9 |
10 |
11 |
12 |
13 |
14 |
15 | 12
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 1
27 |
28 |
29 |
30 | A
31 | 4
32 |
33 | 48
34 | 1
35 | whole
36 | 2
37 |
38 |
39 | 48
40 |
41 |
42 |
43 | 24
44 | 2
45 | half
46 | 1
47 |
48 |
49 |
50 | C
51 | 5
52 |
53 | 24
54 | 2
55 | half
56 | 1
57 |
58 |
59 |
60 |
61 | E
62 | 5
63 |
64 | 24
65 | 2
66 | half
67 | 1
68 |
69 |
70 |
71 |
72 |
73 | 1
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_harmony.musicxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Untitled score
6 |
7 |
8 | Composer / arranger
9 |
10 | MuseScore 4.0.1
11 | 2023-05-10
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Flute
22 | Fl.
23 |
24 | Flute
25 |
26 |
27 |
28 | 1
29 | 74
30 | 78.7402
31 | 0
32 |
33 |
34 |
35 |
36 |
37 |
38 | 1
39 |
40 | 0
41 |
42 |
46 |
47 | G
48 | 2
49 |
50 |
51 |
52 |
53 | C
54 |
55 | minor
56 |
57 |
58 | i
59 | none
60 |
61 |
62 |
63 | G
64 | 4
65 |
66 | 2
67 | 1
68 | half
69 | up
70 |
71 |
72 |
73 | G
74 |
75 | dominant
76 |
77 |
78 | V7
79 | none
80 |
81 |
82 |
83 | G
84 | 4
85 |
86 | 2
87 | 1
88 | half
89 | up
90 |
91 |
92 | light-heavy
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_note_ties.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MüsicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 10
16 |
20 |
21 |
22 |
23 |
24 | A
25 | 4
26 |
27 | 15
28 |
29 | 1
30 | up
31 | quarter
32 |
33 |
34 |
35 |
36 |
37 |
38 |
42 |
43 |
44 |
45 | A
46 | 4
47 |
48 | 5
49 |
50 |
51 | 1
52 | eighth
53 |
54 |
55 |
56 |
57 |
58 |
59 | 20
60 |
61 |
62 |
63 | B
64 | 4
65 |
66 | 20
67 | 2
68 | half
69 |
70 |
71 |
72 |
73 |
74 |
75 | A
76 | 4
77 |
78 | 10
79 |
80 | 1
81 | quarter
82 |
83 |
84 |
85 |
86 |
87 |
88 | B
89 | 3
90 |
91 | diamond
92 | 10
93 | 1
94 | quarter
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_note_ties_divs.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 10
16 |
20 |
21 |
22 |
23 |
24 | A
25 | 4
26 |
27 | 15
28 |
29 | 1
30 | quarter
31 |
32 |
33 |
34 |
35 |
36 |
37 | 15
38 |
39 |
40 |
41 | A
42 | 3
43 |
44 | 15
45 | 2
46 | quarter
47 |
48 |
49 |
50 | 20
51 |
52 |
53 |
54 | A
55 | 4
56 |
57 | 10
58 |
59 |
60 | 1
61 | eighth
62 |
63 |
64 |
65 |
66 |
67 |
68 | 10
69 |
70 |
71 |
72 | 10
73 | 2
74 | eighth
75 |
76 |
77 |
78 |
79 |
80 |
81 | A
82 | 4
83 |
84 | 20
85 |
86 | 1
87 | quarter
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_partial_measures.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 1
16 |
17 | 0
18 |
19 |
23 | 1
24 |
25 | G
26 | 2
27 |
28 |
29 |
30 |
31 | C
32 | 4
33 |
34 | 2
35 | 1
36 | half
37 |
38 |
39 |
40 | C
41 | 4
42 |
43 | 2
44 | 1
45 | half
46 |
47 |
48 |
49 |
50 |
51 |
52 | D
53 | 4
54 |
55 | 1
56 | 1
57 | quarter
58 |
59 |
60 |
61 | E
62 | 4
63 |
64 | 1
65 | 1
66 | quarter
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | F
77 | 4
78 |
79 | 2
80 | 1
81 | half
82 |
83 |
84 | light-heavy
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | G
97 | 4
98 |
99 | 4
100 | 1
101 | whole
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | A
112 | 4
113 |
114 | 2
115 | 1
116 | half
117 |
118 |
119 |
120 |
121 |
122 |
123 | B
124 | -1
125 | 4
126 |
127 | 1
128 | 1
129 | quarter
130 |
131 |
132 |
133 |
134 |
135 |
136 | F
137 | 4
138 |
139 | 2
140 | 1
141 | half
142 |
143 |
144 | light-heavy
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_partial_measures_consecutive.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 1
16 |
17 | 0
18 |
19 |
23 | 1
24 |
25 | G
26 | 2
27 |
28 |
29 |
30 |
31 | C
32 | 4
33 |
34 | 2
35 | 1
36 | half
37 |
38 |
39 |
40 | C
41 | 4
42 |
43 | 2
44 | 1
45 | half
46 |
47 |
48 |
49 |
50 |
51 |
52 | D
53 | 4
54 |
55 | 1
56 | 1
57 | half
58 |
59 |
60 |
61 | E
62 | 4
63 |
64 | 1
65 | 1
66 | half
67 |
68 |
69 |
70 |
71 |
72 |
73 | F
74 | 4
75 |
76 | 2
77 | 1
78 | whole
79 |
80 |
81 |
82 |
83 |
84 |
85 | G
86 | 4
87 |
88 | 4
89 | 1
90 | half
91 |
92 |
93 |
94 |
95 |
96 |
97 | A
98 | 4
99 |
100 | 2
101 | 1
102 | half
103 |
104 |
105 |
106 |
107 |
108 |
109 | B
110 | -1
111 | 4
112 |
113 | 1
114 | 1
115 | quarter
116 |
117 |
118 |
119 |
120 |
121 |
122 | F
123 | 4
124 |
125 | 2
126 | 1
127 | whole
128 |
129 |
130 | light-heavy
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_unfold_timeline.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 10
19 |
23 |
24 |
25 |
26 |
27 | 10
28 | 1
29 | quarter
30 |
31 |
32 |
33 | A
34 | 4
35 |
36 | 10
37 | 1
38 | quarter
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | A
47 | 3
48 |
49 | 10
50 | 1
51 | quarter
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_unfold_timeline_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 10
16 |
20 |
21 |
22 |
23 | 10
24 | 1
25 | quarter
26 |
27 |
28 |
29 | A
30 | 4
31 |
32 | 10
33 | 1
34 | quarter
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | A
43 | 3
44 |
45 | 10
46 | 1
47 | quarter
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 10
61 | 1
62 | quarter
63 |
64 |
65 |
66 | A
67 | 4
68 |
69 | 10
70 | 1
71 | quarter
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | A
80 | 3
81 |
82 | 10
83 | 1
84 | quarter
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_unfold_timeline_result_updated_ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 |
15 | 10
16 |
20 |
21 |
22 |
23 | 10
24 | 1
25 | quarter
26 |
27 |
28 |
29 | A
30 | 4
31 |
32 | 10
33 | 1
34 | quarter
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | A
43 | 3
44 |
45 | 10
46 | 1
47 | quarter
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 10
61 | 1
62 | quarter
63 |
64 |
65 |
66 | A
67 | 4
68 |
69 | 10
70 | 1
71 | quarter
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | A
80 | 3
81 |
82 | 10
83 | 1
84 | quarter
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/tests/data/musicxml/test_unfold_volta_numbers.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | MusicXML Part
9 |
10 |
11 |
12 |
13 |
14 | 1
15 |
16 | 0
17 |
18 |
22 |
23 | G
24 | 2
25 |
26 |
27 |
28 |
29 | C
30 | 4
31 |
32 | 4
33 | 1
34 | whole
35 |
36 |
37 | light-heavy
38 |
39 |
40 |
41 |
42 |
43 |
44 | D
45 | 4
46 |
47 | 1
48 | 1
49 | quarter
50 | up
51 |
52 |
53 |
54 | E
55 | 4
56 |
57 | 1
58 | 1
59 | quarter
60 | up
61 |
62 |
63 |
64 |
65 | heavy-light
66 |
67 |
68 |
69 |
70 | F
71 | 4
72 |
73 | 2
74 | 1
75 | half
76 | up
77 |
78 |
79 |
80 |
81 |
82 | G
83 | 4
84 |
85 | 4
86 | 1
87 | whole
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | A
97 | 4
98 |
99 | 2
100 | 1
101 | half
102 | up
103 |
104 |
105 | light-heavy
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | 2
117 | 1
118 | half
119 |
120 |
121 |
122 | B
123 | 4
124 |
125 | 2
126 | 1
127 | half
128 | up
129 |
130 |
131 |
132 |
133 |
134 | 4
135 | 1
136 |
137 |
138 | light-heavy
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | C
150 | 5
151 |
152 | 4
153 | 1
154 | whole
155 |
156 |
157 | light-heavy
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/tests/data/nakamura/Shi05_infer_corresp.txt:
--------------------------------------------------------------------------------
1 | 0 2.70299 C4 60 36 0 0.25 C4 60 80
2 | 1 3.29915 D4 62 51 1 0.5 D4 62 80
3 | 2 3.90919 E4 64 54 2 0.75 E4 64 80
4 | 3 4.56838 F4 65 57 3 1 F4 65 80
5 | 4 5.59082 G4 67 44 4 1.375 G4 67 80
6 | 5 5.73077 F4 65 54 5 1.4375 F4 65 80
7 | 6 5.86646 E4 64 53 6 1.5 E4 64 80
8 | 7 6.4936 A4 69 61 7 1.75 A4 69 80
9 | 8 7.12714 D4 62 47 8 2 D4 62 80
10 | 9 7.79274 G4 67 51 9 2.25 G4 67 80
11 | 10 8.85257 A4 69 42 10 2.625 A4 69 80
12 | 11 9.13783 G4 67 41 11 2.75 G4 67 80
13 | 12 9.41774 F4 65 44 12 2.875 F4 65 80
14 | 13 9.70086 E4 64 41 13 3 E4 64 80
15 | 14 9.9733 F4 65 50 14 3.125 F4 65 80
16 | 15 10.2436 G4 67 57 15 3.25 G4 67 80
17 | 16 10.2724 E4 64 36 16 3.25 E4 64 80
18 | 17 10.5716 D4 62 45 17 3.375 D4 62 80
19 | 18 10.828 A4 69 65 18 3.5 A4 69 80
--------------------------------------------------------------------------------
/tests/data/nakamura/Shi05_infer_match.txt:
--------------------------------------------------------------------------------
1 | //Version: ScorePerfmMatch_v170104
2 | // Score: ./score_hmm.txt
3 | // Perfm: ./infer_spr.txt
4 | // fmt3x: ./score_fmt3x.txt
5 | 0 2.70299 3.55129 C4 36 35 0 0 250 P1-1-0 0 0
6 | 1 3.29915 4.03312 D4 51 59 0 0 500 P1-1-1 0 -
7 | 2 3.90919 4.65812 E4 54 46 0 0 750 P1-1-2 0 -
8 | 3 4.56838 5.58013 F4 57 37 0 0 1000 P1-1-3 0 -
9 | 4 5.59082 6.03206 G4 44 38 0 0 1375 P1-1-4 0 -
10 | 5 5.73077 6.06945 F4 54 37 0 0 1437 P1-1-5 0 -
11 | 6 5.86646 6.71902 E4 53 41 0 0 1500 P1-1-6 0 -
12 | 7 6.4936 7.21048 A4 61 56 0 0 1750 P1-1-7 0 -
13 | 8 7.12714 8.01924 D4 47 55 0 0 2000 P1-1-8 0 -
14 | 9 7.79274 8.90279 G4 51 56 0 0 2250 P1-1-9 0 -
15 | 10 8.85257 9.19445 A4 42 46 0 0 2625 P1-1-10 0 -
16 | 11 9.13783 9.50856 G4 41 36 0 0 2750 P1-1-11 0 -
17 | 12 9.41774 9.66881 F4 44 50 0 0 2875 P1-1-12 0 -
18 | 13 9.70086 9.97864 E4 41 61 0 0 3000 P1-1-13 0 -
19 | 14 9.9733 10.4113 F4 50 39 0 0 3125 P1-1-14 0 -
20 | 15 10.2436 10.9626 G4 57 52 0 0 3250 P1-1-15 0 -
21 | 16 10.2724 10.7201 E4 36 30 0 0 3250 P1-1-16 0 -
22 | 17 10.5716 10.8654 D4 45 54 0 0 3375 P1-1-17 0 -
23 | 18 10.828 11.484 A4 65 60 0 0 3500 P1-1-18 0 -
--------------------------------------------------------------------------------
/tests/data/nakamura/test_nakamura_performance_corresp.txt:
--------------------------------------------------------------------------------
1 | // alignID alignOntime alignSitch alignPitch alignOnvel refID refOntime refSitch refPitch refOnvel
2 | 0 0.000000 E5 76 64 0 0.000000 E5 76 64
3 | 1 0.000000 G4 67 64 1 0.000000 G4 67 64
4 | 2 0.000000 C4 60 64 2 0.000000 C4 60 64
5 | 3 0.000000 C3 48 64 3 0.000000 C3 48 64
6 | 4 0.500000 F5 77 64 4 0.500000 F5 77 64
7 | 5 1.000000 G5 79 64 5 1.000000 G5 79 64
8 | 6 1.000000 A4 69 64 6 1.000000 A4 69 64
9 | 7 1.000000 C4 60 64 7 1.000000 C4 60 64
10 | 8 1.000000 F3 53 64 8 1.000000 F3 53 64
11 | 9 2.000000 G5 79 64 10 2.000000 G5 79 64
12 | 10 2.000000 G4 67 64 11 2.000000 G4 67 64
13 | 11 2.000000 C4 60 64 12 2.000000 C4 60 64
14 | 12 2.000000 E3 52 64 13 2.000000 E3 52 64
15 | 13 2.500000 E5 76 64 14 2.500000 E5 76 64
16 | 14 3.000000 F5 77 64 15 3.000000 F5 77 64
17 | 15 3.000000 A4 69 64 16 3.000000 A4 69 64
18 | 16 3.000000 D4 62 64 17 3.000000 D4 62 64
19 | 17 3.000000 D3 50 64 18 3.000000 D3 50 64
20 | 18 3.250000 E5 76 64 * -1 * -1 -1
21 | 19 3.500000 D5 74 64 19 3.500000 D5 74 64
22 | 20 4.000000 E5 76 64 20 4.000000 E5 76 64
23 | 21 4.000000 G4 67 64 21 4.000000 G4 67 64
24 | 22 4.000000 C4 60 64 22 4.000000 C4 60 64
25 | 23 4.000000 G3 55 64 23 4.000000 G3 55 64
26 | 24 4.500000 D5 74 64 24 4.500000 D5 74 64
27 | 25 5.000000 C5 72 64 25 5.000000 C5 72 64
28 | 26 5.000000 F4 65 64 26 5.000000 F4 65 64
29 | 27 5.000000 B3 59 64 27 5.000000 B3 59 64
30 | 28 5.000000 G2 43 64 28 5.000000 G2 43 64
31 | 29 5.500000 D5 74 64 29 5.500000 D5 74 64
32 | 30 6.000000 C5 72 64 30 6.000000 C5 72 64
33 | 31 6.000000 E4 64 64 31 6.000000 E4 64 64
34 | 32 6.000000 C4 60 64 32 6.000000 C4 60 64
35 | 33 6.000000 C3 48 64 33 6.000000 C3 48 64
36 | * -1 * -1 -1 9 1.500000 F5 77 64
37 |
--------------------------------------------------------------------------------
/tests/data/nakamura/test_nakamura_performance_match.txt:
--------------------------------------------------------------------------------
1 | //Version: ScorePerfmMatch_v170503
2 | // Score: ./test_nakamura_score_hmm.txt
3 | // Perfm: ./test_nakamura_performance_spr.txt
4 | // fmt3x: ./test_nakamura_score_fmt3x.txt
5 | 0 0.000000 0.500000 E5 64 64 1 0 0 P1-1-0 0 0
6 | 1 0.000000 1.000000 G4 64 64 2 0 0 P1-1-1 0 -
7 | 2 0.000000 1.000000 C4 64 64 3 0 0 P1-1-2 0 -
8 | 3 0.000000 1.000000 C3 64 64 4 0 0 P1-1-3 0 -
9 | 4 0.500000 1.000000 F5 64 64 1 0 500 P1-1-4 0 -
10 | 5 1.000000 1.500000 G5 64 64 1 0 1000 P1-1-5 0 -
11 | 6 1.000000 2.000000 A4 64 64 2 0 1000 P1-1-6 0 -
12 | 7 1.000000 2.000000 C4 64 64 3 0 1000 P1-1-7 0 -
13 | 8 1.000000 2.000000 F3 64 64 4 0 1000 P1-1-8 0 -
14 | 9 2.000000 2.500000 G5 64 64 1 0 2000 P1-1-10 0 -
15 | 10 2.000000 3.000000 G4 64 64 2 0 2000 P1-1-11 0 -
16 | 11 2.000000 3.000000 C4 64 64 3 0 2000 P1-1-12 0 -
17 | 12 2.000000 3.000000 E3 64 64 4 0 2000 P1-1-13 0 -
18 | 13 2.500000 3.000000 E5 64 64 1 0 2500 P1-1-14 0 -
19 | 14 3.000000 3.250000 F5 64 64 1 0 3000 P1-1-15 0 -
20 | 15 3.000000 4.000000 A4 64 64 2 0 3000 P1-1-16 0 -
21 | 16 3.000000 4.000000 D4 64 64 3 0 3000 P1-1-17 0 -
22 | 17 3.000000 4.000000 D3 64 64 4 0 3000 P1-1-18 0 -
23 | 18 3.250000 3.500000 E5 64 64 1 0 3500 * 3 -
24 | 19 3.500000 4.000000 D5 64 64 1 0 3500 P1-1-19 0 -
25 | 20 4.000000 4.500000 E5 64 64 1 0 4000 P1-1-20 0 -
26 | 21 4.000000 5.000000 G4 64 64 2 0 4000 P1-1-21 0 -
27 | 22 4.000000 5.000000 C4 64 64 3 0 4000 P1-1-22 0 -
28 | 23 4.000000 5.000000 G3 64 64 4 0 4000 P1-1-23 0 -
29 | 24 4.500000 5.000000 D5 64 64 1 0 4500 P1-1-24 0 -
30 | 25 5.000000 5.500000 C5 64 64 1 0 5000 P1-1-25 0 -
31 | 26 5.000000 6.000000 F4 64 64 2 0 5000 P1-1-26 0 -
32 | 27 5.000000 6.000000 B3 64 64 3 0 5000 P1-1-27 0 -
33 | 28 5.000000 6.000000 G2 64 64 4 0 5000 P1-1-28 0 -
34 | 29 5.500000 6.000000 D5 64 64 1 0 5500 P1-1-29 0 -
35 | 30 6.000000 8.000000 C5 64 64 1 0 6000 P1-1-30 0 -
36 | 31 6.000000 8.000000 E4 64 64 2 0 6000 P1-1-31 0 -
37 | 32 6.000000 8.000000 C4 64 64 3 0 6000 P1-1-32 0 -
38 | 33 6.000000 8.000000 C3 64 64 4 0 6000 P1-1-33 0 -
39 | //Missing 1500 P1-1-9
40 |
--------------------------------------------------------------------------------
/tests/data/parangonada/mozart_k265_var1/align.csv:
--------------------------------------------------------------------------------
1 | idx,matchtype,partid,ppartid
2 | 0,0,n9,n0
3 | 1,0,n1,n1
4 | 2,0,n2,n2
5 | 3,0,n3,n3
6 | 4,0,n4,n4
7 | 5,0,n10,n5
8 | 6,0,n5,n6
9 | 7,0,n6,n7
10 | 8,0,n7,n8
11 | 9,0,n8,n9
12 | 10,0,n19,n10
13 | 11,0,n11,n11
14 | 12,0,n12,n12
15 | 13,0,n13,n13
16 | 14,0,n14,n14
17 | 15,0,n15,n15
18 | 16,0,n20,n16
19 | 17,0,n16,n17
20 | 18,0,n17,n18
21 | 19,0,n18,n19
22 | 20,0,n21,n20
23 | 21,0,n29,n21
24 | 22,0,n22,n22
25 | 23,0,n23,n23
26 | 24,0,n24,n24
27 | 25,0,n25,n25
28 | 26,0,n30,n26
29 | 27,0,n26,n27
30 | 28,0,n27,n28
31 | 29,0,n28,n29
32 | 30,0,n39,n30
33 | 31,0,n31,n31
34 | 32,0,n40,n32
35 | 33,0,n32,n33
36 | 34,0,n33,n34
37 | 35,0,n34,n35
38 | 36,0,n35,n36
39 | 37,0,n36,n37
40 | 38,0,n37,n38
41 | 39,0,n42,n39
42 | 40,0,n38,n40
43 | 41,0,n43,n41
44 | 42,0,n51,n42
45 | 43,0,n44,n43
46 | 44,0,n45,n44
47 | 45,0,n46,n45
48 | 46,0,n47,n46
49 | 47,0,n48,n47
50 | 48,0,n49,n48
51 | 49,0,n50,n49
52 | 50,0,n53,n50
53 | 51,0,n54,n51
54 | 52,0,n62,n52
55 | 53,0,n55,n53
56 | 54,0,n56,n54
57 | 55,0,n57,n55
58 | 56,0,n58,n56
59 | 57,0,n59,n57
60 | 58,0,n60,n58
61 | 59,0,n64,n59
62 | 60,0,n61,n60
63 | 61,0,n65,n61
64 | 62,0,n69,n62
65 | 63,0,n66,n63
66 | 64,0,n70,n64
67 | 65,0,n67,n65
68 | 66,0,n68,n66
69 | 67,0,n71,n67
70 | 68,0,n73,n68
71 | 69,0,n74,n69
72 | 70,0,n83,n70
73 | 71,0,n75,n71
74 | 72,0,n76,n72
75 | 73,0,n77,n73
76 | 74,0,n78,n74
77 | 75,0,n79,n75
78 | 76,0,n84,n76
79 | 77,0,n80,n77
80 | 78,0,n81,n78
81 | 79,0,n82,n79
82 | 80,0,n93,n80
83 | 81,0,n85,n81
84 | 82,0,n86,n82
85 | 83,0,n87,n83
86 | 84,0,n88,n84
87 | 85,0,n89,n85
88 | 86,0,n94,n86
89 | 87,0,n90,n87
90 | 88,0,n91,n88
91 | 89,0,n92,n89
92 | 90,0,n95,n90
93 | 91,0,n103,n91
94 | 92,0,n96,n92
95 | 93,0,n97,n93
96 | 94,0,n98,n94
97 | 95,0,n104,n95
98 | 96,0,n99,n96
99 | 97,0,n100,n97
100 | 98,0,n101,n98
101 | 99,0,n102,n99
102 | 100,0,n105,n100
103 | 101,0,n113,n101
104 | 102,0,n106,n102
105 | 103,0,n107,n103
106 | 104,0,n108,n104
107 | 105,0,n109,n105
108 | 106,0,n114,n106
109 | 107,0,n110,n107
110 | 108,0,n111,n108
111 | 109,0,n112,n109
112 | 110,0,n124,n110
113 | 111,0,n123,n111
114 | 112,0,n115,n112
115 | 113,0,n116,n113
116 | 114,0,n117,n114
117 | 115,0,n118,n115
118 | 116,0,n119,n116
119 | 117,0,n120,n117
120 | 118,0,n121,n118
121 | 119,0,n122,n119
122 | 120,0,n133,n120
123 | 121,0,n134,n121
124 | 122,0,n125,n122
125 | 123,0,n126,n123
126 | 124,0,n127,n124
127 | 125,0,n128,n125
128 | 126,0,n129,n126
129 | 127,0,n130,n127
130 | 128,0,n131,n128
131 | 129,0,n132,n129
132 | 130,0,n135,n130
133 | 131,0,n143,n131
134 | 132,0,n144,n132
135 | 133,0,n136,n133
136 | 134,0,n137,n134
137 | 135,0,n138,n135
138 | 136,0,n139,n136
139 | 137,2,undefined,n137
140 | 138,0,n140,n138
141 | 139,0,n141,n139
142 | 140,0,n146,n140
143 | 141,0,n142,n141
144 | 142,0,n153,n142
145 | 143,0,n150,n143
146 | 144,0,n147,n144
147 | 145,0,n151,n145
148 | 146,0,n148,n146
149 | 147,0,n152,n147
150 | 148,0,n149,n148
151 | 149,0,n162,n149
152 | 150,0,n154,n150
153 | 151,0,n155,n151
154 | 152,0,n156,n152
155 | 153,0,n157,n153
156 | 154,0,n163,n154
157 | 155,0,n158,n155
158 | 156,0,n159,n156
159 | 157,0,n160,n157
160 | 158,0,n161,n158
161 | 159,0,n172,n159
162 | 160,0,n164,n160
163 | 161,0,n165,n161
164 | 162,0,n166,n162
165 | 163,0,n167,n163
166 | 164,0,n168,n164
167 | 165,0,n173,n165
168 | 166,0,n169,n166
169 | 167,0,n170,n167
170 | 168,0,n171,n168
171 | 169,0,n174,n169
172 | 170,0,n182,n170
173 | 171,0,n175,n171
174 | 172,0,n176,n172
175 | 173,0,n177,n173
176 | 174,0,n178,n174
177 | 175,0,n183,n175
178 | 176,0,n179,n176
179 | 177,0,n180,n177
180 | 178,0,n181,n178
181 | 179,0,n192,n179
182 | 180,0,n193,n180
183 | 181,0,n184,n181
184 | 182,0,n185,n182
185 | 183,0,n186,n183
186 | 184,0,n187,n184
187 | 185,0,n188,n185
188 | 186,0,n189,n186
189 | 187,0,n190,n187
190 | 188,0,n195,n188
191 | 189,0,n191,n189
192 | 190,0,n196,n190
193 | 191,0,n204,n191
194 | 192,0,n197,n192
195 | 193,0,n198,n193
196 | 194,0,n199,n194
197 | 195,0,n200,n195
198 | 196,0,n201,n196
199 | 197,0,n202,n197
200 | 198,0,n203,n198
201 | 199,0,n206,n199
202 | 200,0,n207,n200
203 | 201,0,n215,n201
204 | 202,0,n208,n202
205 | 203,0,n209,n203
206 | 204,0,n210,n204
207 | 205,0,n211,n205
208 | 206,0,n212,n206
209 | 207,0,n213,n207
210 | 208,0,n214,n208
211 | 209,0,n217,n209
212 | 210,0,n218,n210
213 | 211,0,n222,n211
214 | 212,0,n219,n212
215 | 213,0,n223,n213
216 | 214,0,n220,n214
217 | 215,0,n221,n215
218 | 216,0,n224,n216
219 | 217,0,n226,n217
220 | 218,0,n227,n218
221 |
--------------------------------------------------------------------------------
/tests/data/parangonada/mozart_k265_var1/feature.csv:
--------------------------------------------------------------------------------
1 | velocity,timing,articulation,id
2 | 0.0,0.0,0.0,n9
3 | 0.0,0.0,0.0,n1
4 | 0.0,0.0,0.0,n2
5 | 0.0,0.0,0.0,n3
6 | 0.0,0.0,0.0,n4
7 | 0.0,0.0,0.0,n10
8 | 0.0,0.0,0.0,n5
9 | 0.0,0.0,0.0,n6
10 | 0.0,0.0,0.0,n7
11 | 0.0,0.0,0.0,n8
12 | 0.0,0.0,0.0,n19
13 | 0.0,0.0,0.0,n11
14 | 0.0,0.0,0.0,n12
15 | 0.0,0.0,0.0,n13
16 | 0.0,0.0,0.0,n14
17 | 0.0,0.0,0.0,n20
18 | 0.0,0.0,0.0,n15
19 | 0.0,0.0,0.0,n16
20 | 0.0,0.0,0.0,n17
21 | 0.0,0.0,0.0,n18
22 | 0.0,0.0,0.0,n29
23 | 0.0,0.0,0.0,n21
24 | 0.0,0.0,0.0,n22
25 | 0.0,0.0,0.0,n23
26 | 0.0,0.0,0.0,n24
27 | 0.0,0.0,0.0,n30
28 | 0.0,0.0,0.0,n25
29 | 0.0,0.0,0.0,n26
30 | 0.0,0.0,0.0,n27
31 | 0.0,0.0,0.0,n28
32 | 0.0,0.0,0.0,n39
33 | 0.0,0.0,0.0,n40
34 | 0.0,0.0,0.0,n31
35 | 0.0,0.0,0.0,n32
36 | 0.0,0.0,0.0,n33
37 | 0.0,0.0,0.0,n34
38 | 0.0,0.0,0.0,n35
39 | 0.0,0.0,0.0,n36
40 | 0.0,0.0,0.0,n37
41 | 0.0,0.0,0.0,n42
42 | 0.0,0.0,0.0,n38
43 | 0.0,0.0,0.0,n51
44 | 0.0,0.0,0.0,n43
45 | 0.0,0.0,0.0,n44
46 | 0.0,0.0,0.0,n45
47 | 0.0,0.0,0.0,n46
48 | 0.0,0.0,0.0,n47
49 | 0.0,0.0,0.0,n48
50 | 0.0,0.0,0.0,n49
51 | 0.0,0.0,0.0,n53
52 | 0.0,0.0,0.0,n50
53 | 0.0,0.0,0.0,n62
54 | 0.0,0.0,0.0,n54
55 | 0.0,0.0,0.0,n55
56 | 0.0,0.0,0.0,n56
57 | 0.0,0.0,0.0,n57
58 | 0.0,0.0,0.0,n58
59 | 0.0,0.0,0.0,n59
60 | 0.0,0.0,0.0,n60
61 | 0.0,0.0,0.0,n64
62 | 0.0,0.0,0.0,n61
63 | 0.0,0.0,0.0,n69
64 | 0.0,0.0,0.0,n65
65 | 0.0,0.0,0.0,n66
66 | 0.0,0.0,0.0,n70
67 | 0.0,0.0,0.0,n67
68 | 0.0,0.0,0.0,n68
69 | 0.0,0.0,0.0,n73
70 | 0.0,0.0,0.0,n71
71 | 0.0,0.0,0.0,n74
72 | 0.0,0.0,0.0,n83
73 | 0.0,0.0,0.0,n75
74 | 0.0,0.0,0.0,n76
75 | 0.0,0.0,0.0,n77
76 | 0.0,0.0,0.0,n78
77 | 0.0,0.0,0.0,n84
78 | 0.0,0.0,0.0,n79
79 | 0.0,0.0,0.0,n80
80 | 0.0,0.0,0.0,n81
81 | 0.0,0.0,0.0,n82
82 | 0.0,0.0,0.0,n93
83 | 0.0,0.0,0.0,n85
84 | 0.0,0.0,0.0,n86
85 | 0.0,0.0,0.0,n87
86 | 0.0,0.0,0.0,n88
87 | 0.0,0.0,0.0,n94
88 | 0.0,0.0,0.0,n89
89 | 0.0,0.0,0.0,n90
90 | 0.0,0.0,0.0,n91
91 | 0.0,0.0,0.0,n92
92 | 0.0,0.0,0.0,n103
93 | 0.0,0.0,0.0,n95
94 | 0.0,0.0,0.0,n96
95 | 0.0,0.0,0.0,n97
96 | 0.0,0.0,0.0,n98
97 | 0.0,0.0,0.0,n104
98 | 0.0,0.0,0.0,n99
99 | 0.0,0.0,0.0,n100
100 | 0.0,0.0,0.0,n101
101 | 0.0,0.0,0.0,n102
102 | 0.0,0.0,0.0,n113
103 | 0.0,0.0,0.0,n105
104 | 0.0,0.0,0.0,n106
105 | 0.0,0.0,0.0,n107
106 | 0.0,0.0,0.0,n108
107 | 0.0,0.0,0.0,n114
108 | 0.0,0.0,0.0,n109
109 | 0.0,0.0,0.0,n110
110 | 0.0,0.0,0.0,n111
111 | 0.0,0.0,0.0,n112
112 | 0.0,0.0,0.0,n123
113 | 0.0,0.0,0.0,n124
114 | 0.0,0.0,0.0,n115
115 | 0.0,0.0,0.0,n116
116 | 0.0,0.0,0.0,n117
117 | 0.0,0.0,0.0,n118
118 | 0.0,0.0,0.0,n119
119 | 0.0,0.0,0.0,n120
120 | 0.0,0.0,0.0,n121
121 | 0.0,0.0,0.0,n122
122 | 0.0,0.0,0.0,n133
123 | 0.0,0.0,0.0,n134
124 | 0.0,0.0,0.0,n125
125 | 0.0,0.0,0.0,n126
126 | 0.0,0.0,0.0,n127
127 | 0.0,0.0,0.0,n128
128 | 0.0,0.0,0.0,n129
129 | 0.0,0.0,0.0,n130
130 | 0.0,0.0,0.0,n131
131 | 0.0,0.0,0.0,n132
132 | 0.0,0.0,0.0,n143
133 | 0.0,0.0,0.0,n144
134 | 0.0,0.0,0.0,n135
135 | 0.0,0.0,0.0,n136
136 | 0.0,0.0,0.0,n137
137 | 0.0,0.0,0.0,n138
138 | 0.0,0.0,0.0,n139
139 | 0.0,0.0,0.0,n140
140 | 0.0,0.0,0.0,n141
141 | 0.0,0.0,0.0,n146
142 | 0.0,0.0,0.0,n142
143 | 0.0,0.0,0.0,n153
144 | 0.0,0.0,0.0,n150
145 | 0.0,0.0,0.0,n147
146 | 0.0,0.0,0.0,n151
147 | 0.0,0.0,0.0,n148
148 | 0.0,0.0,0.0,n152
149 | 0.0,0.0,0.0,n149
150 | 0.0,0.0,0.0,n162
151 | 0.0,0.0,0.0,n154
152 | 0.0,0.0,0.0,n155
153 | 0.0,0.0,0.0,n156
154 | 0.0,0.0,0.0,n157
155 | 0.0,0.0,0.0,n163
156 | 0.0,0.0,0.0,n158
157 | 0.0,0.0,0.0,n159
158 | 0.0,0.0,0.0,n160
159 | 0.0,0.0,0.0,n161
160 | 0.0,0.0,0.0,n172
161 | 0.0,0.0,0.0,n164
162 | 0.0,0.0,0.0,n165
163 | 0.0,0.0,0.0,n166
164 | 0.0,0.0,0.0,n167
165 | 0.0,0.0,0.0,n173
166 | 0.0,0.0,0.0,n168
167 | 0.0,0.0,0.0,n169
168 | 0.0,0.0,0.0,n170
169 | 0.0,0.0,0.0,n171
170 | 0.0,0.0,0.0,n182
171 | 0.0,0.0,0.0,n174
172 | 0.0,0.0,0.0,n175
173 | 0.0,0.0,0.0,n176
174 | 0.0,0.0,0.0,n177
175 | 0.0,0.0,0.0,n183
176 | 0.0,0.0,0.0,n178
177 | 0.0,0.0,0.0,n179
178 | 0.0,0.0,0.0,n180
179 | 0.0,0.0,0.0,n181
180 | 0.0,0.0,0.0,n192
181 | 0.0,0.0,0.0,n193
182 | 0.0,0.0,0.0,n184
183 | 0.0,0.0,0.0,n185
184 | 0.0,0.0,0.0,n186
185 | 0.0,0.0,0.0,n187
186 | 0.0,0.0,0.0,n188
187 | 0.0,0.0,0.0,n189
188 | 0.0,0.0,0.0,n190
189 | 0.0,0.0,0.0,n195
190 | 0.0,0.0,0.0,n191
191 | 0.0,0.0,0.0,n204
192 | 0.0,0.0,0.0,n196
193 | 0.0,0.0,0.0,n197
194 | 0.0,0.0,0.0,n198
195 | 0.0,0.0,0.0,n199
196 | 0.0,0.0,0.0,n200
197 | 0.0,0.0,0.0,n201
198 | 0.0,0.0,0.0,n202
199 | 0.0,0.0,0.0,n206
200 | 0.0,0.0,0.0,n203
201 | 0.0,0.0,0.0,n215
202 | 0.0,0.0,0.0,n207
203 | 0.0,0.0,0.0,n208
204 | 0.0,0.0,0.0,n209
205 | 0.0,0.0,0.0,n210
206 | 0.0,0.0,0.0,n211
207 | 0.0,0.0,0.0,n212
208 | 0.0,0.0,0.0,n213
209 | 0.0,0.0,0.0,n217
210 | 0.0,0.0,0.0,n214
211 | 0.0,0.0,0.0,n222
212 | 0.0,0.0,0.0,n218
213 | 0.0,0.0,0.0,n219
214 | 0.0,0.0,0.0,n223
215 | 0.0,0.0,0.0,n220
216 | 0.0,0.0,0.0,n221
217 | 0.0,0.0,0.0,n226
218 | 0.0,0.0,0.0,n224
219 | 0.0,0.0,0.0,n227
220 |
--------------------------------------------------------------------------------
/tests/data/parangonada/mozart_k265_var1/zalign.csv:
--------------------------------------------------------------------------------
1 | idx,matchtype,partid,ppartid
2 | 0,0,n9,n0
3 | 1,0,n1,n1
4 | 2,0,n2,n2
5 | 3,0,n3,n3
6 | 4,0,n4,n4
7 | 5,0,n10,n5
8 | 6,0,n5,n6
9 | 7,0,n6,n7
10 | 8,0,n7,n8
11 | 9,0,n8,n9
12 | 10,0,n19,n10
13 | 11,0,n11,n11
14 | 12,0,n12,n12
15 | 13,0,n13,n13
16 | 14,0,n14,n14
17 | 15,0,n15,n15
18 | 16,0,n20,n16
19 | 17,0,n16,n17
20 | 18,0,n17,n18
21 | 19,0,n18,n19
22 | 20,0,n21,n20
23 | 21,0,n29,n21
24 | 22,0,n22,n22
25 | 23,0,n23,n23
26 | 24,0,n24,n24
27 | 25,0,n25,n25
28 | 26,0,n30,n26
29 | 27,0,n26,n27
30 | 28,0,n27,n28
31 | 29,0,n28,n29
32 | 30,0,n39,n30
33 | 31,0,n31,n31
34 | 32,0,n40,n32
35 | 33,0,n32,n33
36 | 34,0,n33,n34
37 | 35,0,n34,n35
38 | 36,0,n35,n36
39 | 37,0,n36,n37
40 | 38,0,n37,n38
41 | 39,0,n42,n39
42 | 40,0,n38,n40
43 | 41,0,n43,n41
44 | 42,0,n51,n42
45 | 43,0,n44,n43
46 | 44,0,n45,n44
47 | 45,0,n46,n45
48 | 46,0,n47,n46
49 | 47,0,n48,n47
50 | 48,0,n49,n48
51 | 49,0,n50,n49
52 | 50,0,n53,n50
53 | 51,0,n54,n51
54 | 52,0,n62,n52
55 | 53,0,n55,n53
56 | 54,0,n56,n54
57 | 55,0,n57,n55
58 | 56,0,n58,n56
59 | 57,0,n59,n57
60 | 58,0,n60,n58
61 | 59,0,n64,n59
62 | 60,0,n61,n60
63 | 61,0,n65,n61
64 | 62,0,n69,n62
65 | 63,0,n66,n63
66 | 64,0,n70,n64
67 | 65,0,n67,n65
68 | 66,0,n68,n66
69 | 67,0,n71,n67
70 | 68,0,n73,n68
71 | 69,0,n74,n69
72 | 70,0,n83,n70
73 | 71,0,n75,n71
74 | 72,0,n76,n72
75 | 73,0,n77,n73
76 | 74,0,n78,n74
77 | 75,0,n79,n75
78 | 76,0,n84,n76
79 | 77,0,n80,n77
80 | 78,0,n81,n78
81 | 79,0,n82,n79
82 | 80,0,n93,n80
83 | 81,0,n85,n81
84 | 82,0,n86,n82
85 | 83,0,n87,n83
86 | 84,0,n88,n84
87 | 85,0,n89,n85
88 | 86,0,n94,n86
89 | 87,0,n90,n87
90 | 88,0,n91,n88
91 | 89,0,n92,n89
92 | 90,0,n95,n90
93 | 91,0,n103,n91
94 | 92,0,n96,n92
95 | 93,0,n97,n93
96 | 94,0,n98,n94
97 | 95,0,n104,n95
98 | 96,0,n99,n96
99 | 97,0,n100,n97
100 | 98,0,n101,n98
101 | 99,0,n102,n99
102 | 100,0,n105,n100
103 | 101,0,n113,n101
104 | 102,0,n106,n102
105 | 103,0,n107,n103
106 | 104,0,n108,n104
107 | 105,0,n109,n105
108 | 106,0,n114,n106
109 | 107,0,n110,n107
110 | 108,0,n111,n108
111 | 109,0,n112,n109
112 | 110,0,n124,n110
113 | 111,0,n123,n111
114 | 112,0,n115,n112
115 | 113,0,n116,n113
116 | 114,0,n117,n114
117 | 115,0,n118,n115
118 | 116,0,n119,n116
119 | 117,0,n120,n117
120 | 118,0,n121,n118
121 | 119,0,n122,n119
122 | 120,0,n133,n120
123 | 121,0,n134,n121
124 | 122,0,n125,n122
125 | 123,0,n126,n123
126 | 124,0,n127,n124
127 | 125,0,n128,n125
128 | 126,0,n129,n126
129 | 127,0,n130,n127
130 | 128,0,n131,n128
131 | 129,0,n132,n129
132 | 130,0,n135,n130
133 | 131,0,n143,n131
134 | 132,0,n144,n132
135 | 133,0,n136,n133
136 | 134,0,n137,n134
137 | 135,0,n138,n135
138 | 136,0,n139,n136
139 | 137,2,undefined,n137
140 | 138,0,n140,n138
141 | 139,0,n141,n139
142 | 140,0,n146,n140
143 | 141,0,n142,n141
144 | 142,0,n153,n142
145 | 143,0,n150,n143
146 | 144,0,n147,n144
147 | 145,0,n151,n145
148 | 146,0,n148,n146
149 | 147,0,n152,n147
150 | 148,0,n149,n148
151 | 149,0,n162,n149
152 | 150,0,n154,n150
153 | 151,0,n155,n151
154 | 152,0,n156,n152
155 | 153,0,n157,n153
156 | 154,0,n163,n154
157 | 155,0,n158,n155
158 | 156,0,n159,n156
159 | 157,0,n160,n157
160 | 158,0,n161,n158
161 | 159,0,n172,n159
162 | 160,0,n164,n160
163 | 161,0,n165,n161
164 | 162,0,n166,n162
165 | 163,0,n167,n163
166 | 164,0,n168,n164
167 | 165,0,n173,n165
168 | 166,0,n169,n166
169 | 167,0,n170,n167
170 | 168,0,n171,n168
171 | 169,0,n174,n169
172 | 170,0,n182,n170
173 | 171,0,n175,n171
174 | 172,0,n176,n172
175 | 173,0,n177,n173
176 | 174,0,n178,n174
177 | 175,0,n183,n175
178 | 176,0,n179,n176
179 | 177,0,n180,n177
180 | 178,0,n181,n178
181 | 179,0,n192,n179
182 | 180,0,n193,n180
183 | 181,0,n184,n181
184 | 182,0,n185,n182
185 | 183,0,n186,n183
186 | 184,0,n187,n184
187 | 185,0,n188,n185
188 | 186,0,n189,n186
189 | 187,0,n190,n187
190 | 188,0,n195,n188
191 | 189,0,n191,n189
192 | 190,0,n196,n190
193 | 191,0,n204,n191
194 | 192,0,n197,n192
195 | 193,0,n198,n193
196 | 194,0,n199,n194
197 | 195,0,n200,n195
198 | 196,0,n201,n196
199 | 197,0,n202,n197
200 | 198,0,n203,n198
201 | 199,0,n206,n199
202 | 200,0,n207,n200
203 | 201,0,n215,n201
204 | 202,0,n208,n202
205 | 203,0,n209,n203
206 | 204,0,n210,n204
207 | 205,0,n211,n205
208 | 206,0,n212,n206
209 | 207,0,n213,n207
210 | 208,0,n214,n208
211 | 209,0,n217,n209
212 | 210,0,n218,n210
213 | 211,0,n222,n211
214 | 212,0,n219,n212
215 | 213,0,n223,n213
216 | 214,0,n220,n214
217 | 215,0,n221,n215
218 | 216,0,n224,n216
219 | 217,0,n226,n217
220 | 218,0,n227,n218
221 |
--------------------------------------------------------------------------------
/tests/data/png/example_score.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/png/example_score.png
--------------------------------------------------------------------------------
/tests/data/wav/example_linear_equal_temperament_sr8000.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CPJKU/partitura/bfaac43eebb47eaf1aef9841087674c08b22a30e/tests/data/wav/example_linear_equal_temperament_sr8000.wav
--------------------------------------------------------------------------------
/tests/temp_test.py:
--------------------------------------------------------------------------------
1 | import partitura as pt
2 |
3 | score = pt.load_mei(r"C:\Users\fosca\Desktop\JKU\partitura\tests\data\mei\example_noMeasures_noBeams.mei")
4 | print(score.parts)
5 |
--------------------------------------------------------------------------------
/tests/test_clef.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for clef related methods.
5 | """
6 | import unittest
7 | from tests import (
8 | CLEF_TESTFILES,
9 | CLEF_MAP_TESTFILES
10 | )
11 | import numpy as np
12 | from partitura import load_musicxml
13 | from partitura.musicanalysis import compute_note_array
14 | from partitura.musicanalysis.note_features import clef_feature
15 | from partitura.score import merge_parts
16 | import partitura
17 |
18 | class TestingClefFeatureExtraction(unittest.TestCase):
19 | def test_clef_feature_exctraction(self):
20 | for fn in CLEF_TESTFILES:
21 | score = load_musicxml(fn, force_note_ids = "keep")
22 | sna1 = compute_note_array(score.parts[0],
23 | feature_functions=["clef_feature"])
24 | sna2 = compute_note_array(score.parts[1],
25 | feature_functions=["clef_feature"])
26 | mpart = merge_parts(score.parts, reassign="staff")
27 | sna3 = compute_note_array(mpart,
28 | feature_functions=["clef_feature"])
29 |
30 | sna1test1 = sna1["clef_feature.clef_sign"] == np.array([1., 0., 2., 0., 0., 2., 0., 0., 1., 0.])
31 | sna1test2 = sna1["clef_feature.clef_line"] == np.array([4., 2., 3., 2., 2., 4., 2., 2., 4., 2.])
32 | sna1test3 = sna1["clef_feature.clef_octave_change"] == np.array([0., 0., 0., 1., 1., 0., -1., 0., 0., 0.])
33 | self.assertTrue(np.all(sna1test1), "clef sign does not match")
34 | self.assertTrue(np.all(sna1test2), "clef line does not match")
35 | self.assertTrue(np.all(sna1test3), "clef octave does not match")
36 |
37 |
38 | sna2test1 = sna2["clef_feature.clef_sign"] == np.array([1., 0.])
39 | sna2test2 = sna2["clef_feature.clef_line"] == np.array([4., 2.])
40 | sna2test3 = sna2["clef_feature.clef_octave_change"] == np.array([0., 0.])
41 | self.assertTrue(np.all(sna2test1), "clef sign does not match")
42 | self.assertTrue(np.all(sna2test2), "clef line does not match")
43 | self.assertTrue(np.all(sna2test3), "clef octave does not match")
44 |
45 | sna3test1 = sna3["clef_feature.clef_sign"] == np.array([1., 0., 2., 0., 0., 1., 2., 0., 0., 0., 1., 0.])
46 | sna3test2 = sna3["clef_feature.clef_line"] == np.array([4., 2., 3., 2., 2., 4., 4., 2., 2., 2., 4., 2.])
47 | sna3test3 = sna3["clef_feature.clef_octave_change"] == np.array([0., 0., 0., 1., 1., 0., 0., -1., 0., 0., 0., 0.])
48 | self.assertTrue(np.all(sna3test1), "clef sign does not match")
49 | self.assertTrue(np.all(sna3test2), "clef line does not match")
50 | self.assertTrue(np.all(sna3test3), "clef octave does not match")
51 |
52 |
53 |
54 |
55 | class TestClefMap(unittest.TestCase):
56 | def test_clef_map(self):
57 | score = load_musicxml(CLEF_MAP_TESTFILES[0])
58 | for part in score:
59 | # clef = (staff_no, sign_shape, line, octave_shift)
60 | map_fn = part.clef_map
61 | self.assertTrue(
62 | np.all(map_fn(part.first_point.t) == np.array([[1, 0, 2, 0], [2, 1, 4, 0]])) # treble / bass
63 | )
64 | self.assertTrue(
65 | np.all(map_fn(7) == np.array([[1, 0, 2, -2], [2, 0, 2, 0]])) # treble15vb / treble
66 | )
67 | self.assertTrue(
68 | np.all(map_fn(8) == np.array([[1, 0, 2, 1], [2, 1, 4, 0]])) # treble8va / bass
69 | )
70 | self.assertTrue(
71 | np.all(map_fn(11) == np.array([[1, 2, 3, 0], [2, 1, 4, 0]])) # ut3 / bass
72 | )
73 | self.assertTrue(
74 | np.all(map_fn(12) == np.array([[1, 2, 3, 0], [2, 1, 3, 0]])) # ut3 / bass3
75 | )
76 | self.assertTrue(
77 | np.all(map_fn(13) == np.array([[1, 2, 4, 0], [2, 1, 3, 0]])) # ut4 / bass3
78 | )
79 | self.assertTrue(
80 | np.all(map_fn(part.last_point.t) == np.array([[1, 2, 4, 0], [2, 1, 3, 0]])) # ut4 / bass3
81 | )
82 |
83 |
84 | def test_clef_map_multipart(self):
85 | score = load_musicxml(CLEF_TESTFILES[0])
86 | p1 = score.parts[0]
87 | p2 = score.parts[1]
88 |
89 | t = np.arange(16)
90 | target_p1_octave_change = np.array([ 0, 0, 0, 0, 1, 1, 1, 1, -1, -1, 0, 0, 0, 0, 0, 0])
91 | target_p1_line = np.array([4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4])
92 | map_fn = p1.clef_map
93 | self.assertTrue(np.all(map_fn(t)[0,:,3] == target_p1_octave_change))
94 | self.assertTrue(np.all(map_fn(t)[1,:,2] == target_p1_line))
95 |
96 | target_p2_sign = np.zeros(16) # 16 stepgs G clef, imputed missing clef in the beginning
97 | map_fn = p2.clef_map
98 | self.assertTrue(np.all(map_fn(t)[1,:,1] == target_p2_sign))
99 |
100 |
101 | p3 = merge_parts(score.parts, reassign="staff")
102 | map_fn = p3.clef_map
103 | self.assertTrue(np.all(map_fn(t)[0,:,3] == target_p1_octave_change))
104 | self.assertTrue(np.all(map_fn(t)[1,:,2] == target_p1_line))
105 | self.assertTrue(np.all(map_fn(t)[3,:,1] == target_p2_sign))
106 |
--------------------------------------------------------------------------------
/tests/test_cross_staff.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from partitura import load_musicxml, load_mei
3 | import numpy as np
4 | from tests import CROSS_STAFF_TESTFILES
5 |
6 |
7 | class CrossStaffBeaming(unittest.TestCase):
8 | def test_cross_staff_single_part_musicxml(self):
9 | score = load_musicxml(CROSS_STAFF_TESTFILES[0])
10 | note_array = score.note_array(include_staff=True)
11 | expected_staff = np.array([1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 1])
12 | cross_staff_mask = (note_array["pitch"] > 52) & (note_array["pitch"] < 72)
13 | note_array_staff = note_array[cross_staff_mask]["staff"]
14 | expected_voice = np.ones(len(note_array_staff), dtype=int)
15 | note_array_voice = note_array[cross_staff_mask]["voice"]
16 | self.assertTrue(np.all(note_array_staff == expected_staff))
17 | self.assertTrue(np.all(note_array_voice == expected_voice))
18 |
19 | class CrossStaffVoices(unittest.TestCase):
20 | def test_music_xml(self):
21 | score = load_musicxml(CROSS_STAFF_TESTFILES[1])
22 | note_array = score.note_array(include_staff=True)
23 | expected_staff = [2,1,1,2,1,2,1,1]
24 | expected_voice = [5,2,1,5,5,5,5,5]
25 | self.assertEqual(note_array["staff"].tolist(), expected_staff)
26 | self.assertEqual(note_array["voice"].tolist(), expected_voice)
27 |
28 | def test_mei(self):
29 | score = load_mei(CROSS_STAFF_TESTFILES[2])
30 | note_array = score.note_array(include_staff=True)
31 | expected_staff = [2,1,1,2,1,2,1,1]
32 | expected_voice = [5,2,1,5,5,5,5,5]
33 | self.assertEqual(note_array["staff"].tolist(), expected_staff)
34 | self.assertEqual(note_array["voice"].tolist(), expected_voice)
--------------------------------------------------------------------------------
/tests/test_dcml_import.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from partitura import load_dcml
3 | from tests import TSV_PATH
4 | import os
5 | import pandas as pd
6 |
7 |
8 | class ImportDCMLAnnotations(unittest.TestCase):
9 | def test_tsv_import_from_dcml(self):
10 | note_path = os.path.join(TSV_PATH, "test_notes.tsv")
11 | measure_path = os.path.join(TSV_PATH, "test_measures.tsv")
12 | harmony_path = os.path.join(TSV_PATH, "test_harmonies.tsv")
13 | score = load_dcml(note_path, measure_path, harmony_path)
14 | note_lines = pd.read_csv(note_path, sep="\t", header=None)
15 | self.assertEqual(len(score.parts), 1)
16 | self.assertEqual(len(score[0].notes), len(note_lines)-1, "Number of notes do not match")
17 |
18 |
19 | if __name__ == '__main__':
20 | unittest.main()
21 |
--------------------------------------------------------------------------------
/tests/test_deprecations.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module includes tests for deprecation utilities.
5 | """
6 | import unittest
7 | import warnings
8 | import numpy as np
9 |
10 | from partitura.utils import deprecated_alias, deprecated_parameter
11 |
12 | RNG = np.random.RandomState(1984)
13 |
14 |
15 | class TestDeprecations(unittest.TestCase):
16 | @deprecated_alias(old_p1="new_p1", old_p2="new_p2")
17 | def func_alias(self, new_p1=None, new_p2=None, **kwargs):
18 |
19 | crit = not ("old_p1" in kwargs or "old_p2" in kwargs)
20 |
21 | self.assertTrue(crit)
22 | self.assertTrue(new_p1 is not None)
23 | self.assertTrue(new_p2 is not None)
24 |
25 | @deprecated_parameter(*[f"deprecated{i}" for i in range(10)])
26 | def func_parameter(self, new_p1=None, new_p2=None, **kwargs):
27 |
28 | crit = not any([f"deprecated{i}" in kwargs for i in range(10)])
29 |
30 | self.assertTrue(crit)
31 | self.assertTrue(new_p1 is not None)
32 | self.assertTrue(new_p2 is not None)
33 |
34 | def test_deprecated_alias(self):
35 | with warnings.catch_warnings():
36 | warnings.simplefilter("ignore")
37 | for old_p1, old_p2 in RNG.rand(10, 2):
38 | self.func_alias(old_p1=old_p1, old_p2=old_p2)
39 |
40 | def test_deprecated_parameter(self):
41 | with warnings.catch_warnings():
42 | warnings.simplefilter("ignore")
43 | for rp in RNG.rand(10, 12):
44 | kwargs = dict(
45 | [("new_p1", rp[0]), ("new_p2", rp[1])]
46 | + [(f"deprecated{i}", rp[i + 2]) for i in range(10)]
47 | )
48 | self.func_parameter(**kwargs)
49 |
--------------------------------------------------------------------------------
/tests/test_display.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module includes tests for display utilities. Since these utilities
5 | rely on externally installed software (e.g., MuseScore, Lilypond),
6 | they cannot be automatically tested by GitHub.
7 | """
8 | import os
9 | import tempfile
10 | import unittest
11 |
12 | import numpy as np
13 |
14 | from partitura.utils.misc import concatenate_images, PIL_EXISTS, Image
15 |
16 | from tests import PNG_TESTFILES
17 |
18 |
19 | class TestMuseScoreExport(unittest.TestCase):
20 | def test_concat_images(self):
21 | """
22 | Test `partitura.utils.misc.concatenate_images`
23 | """
24 | if PIL_EXISTS:
25 |
26 | for fn in PNG_TESTFILES:
27 | filenames = [fn, fn]
28 |
29 | # original image
30 | oimage = Image.open(fn)
31 |
32 | # images concatenated vertically
33 | cimage_vertical = concatenate_images(
34 | filenames=filenames,
35 | out=None,
36 | concat_mode="vertical",
37 | )
38 |
39 | tmpdir = tempfile.gettempdir()
40 |
41 | ofn = os.path.join(tmpdir, "test_output.png")
42 | concatenate_images(
43 | filenames=filenames,
44 | out=ofn,
45 | concat_mode="vertical",
46 | )
47 | reloaded_image = Image.open(ofn)
48 |
49 | self.assertTrue(
50 | np.allclose(
51 | np.asarray(reloaded_image),
52 | np.asarray(cimage_vertical),
53 | )
54 | )
55 |
56 | cimage_horizontal = concatenate_images(
57 | filenames=filenames,
58 | out=None,
59 | concat_mode="horizontal",
60 | )
61 |
62 | expected_size_vertical = (oimage.size[0], oimage.size[1] * 2)
63 | expected_size_horizontal = (oimage.size[0] * 2, oimage.size[1])
64 | self.assertTrue(cimage_vertical.size == expected_size_vertical)
65 | self.assertTrue(cimage_horizontal.size == expected_size_horizontal)
66 |
67 | oimage.close()
68 | reloaded_image.close()
69 |
--------------------------------------------------------------------------------
/tests/test_fluidsynth.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for the fluidsynth methods.
5 | """
6 | import unittest
7 |
8 | import numpy as np
9 | from scipy.io import wavfile
10 | import tempfile
11 |
12 | from partitura.utils.fluidsynth import (
13 | synthesize_fluidsynth,
14 | HAS_FLUIDSYNTH,
15 | SAMPLE_RATE,
16 | )
17 |
18 | from partitura import EXAMPLE_MUSICXML, load_score, load_performance_midi
19 |
20 | from partitura.io.exportaudio import save_wav_fluidsynth
21 |
22 | from tests import MOZART_VARIATION_FILES
23 |
24 | RNG = np.random.RandomState(1984)
25 |
26 | if HAS_FLUIDSYNTH:
27 |
28 | class TestSynthesize(unittest.TestCase):
29 |
30 | score = load_score(EXAMPLE_MUSICXML)
31 |
32 | def test_synthesize(self):
33 |
34 | score_na = self.score.note_array()
35 |
36 | duration_beats = (
37 | score_na["onset_beat"] + score_na["duration_beat"]
38 | ).max() - score_na["onset_beat"].min()
39 |
40 | for bpm in RNG.randint(30, 200, size=10):
41 |
42 | for samplerate in [12000, 16000, 22000, SAMPLE_RATE]:
43 |
44 | duration_sec = duration_beats * 60 / bpm
45 | y = synthesize_fluidsynth(
46 | note_info=self.score,
47 | samplerate=samplerate,
48 | bpm=bpm,
49 | )
50 |
51 | expected_length = np.round(duration_sec * samplerate)
52 |
53 | self.assertTrue(len(y) == expected_length)
54 |
55 | self.assertTrue(isinstance(y, np.ndarray))
56 |
57 | class TestSynthExport(unittest.TestCase):
58 |
59 | test_files = [
60 | load_score(MOZART_VARIATION_FILES["musicxml"]),
61 | load_performance_midi(MOZART_VARIATION_FILES["midi"]),
62 | ]
63 |
64 | def export(self, note_info):
65 |
66 | y = synthesize_fluidsynth(
67 | note_info=note_info,
68 | samplerate=SAMPLE_RATE,
69 | bpm=60,
70 | )
71 |
72 | with tempfile.TemporaryFile(suffix=".wav") as filename:
73 |
74 | save_wav_fluidsynth(
75 | input_data=note_info,
76 | out=filename,
77 | samplerate=SAMPLE_RATE,
78 | bpm=60,
79 | )
80 |
81 | sr_rec, rec_audio = wavfile.read(filename)
82 |
83 | self.assertTrue(sr_rec == SAMPLE_RATE)
84 | self.assertTrue(len(rec_audio) == len(y))
85 | self.assertTrue(
86 | np.allclose(
87 | rec_audio / rec_audio.max(),
88 | y / y.max(),
89 | atol=1e-4,
90 | )
91 | )
92 |
93 | def test_export(self):
94 |
95 | for note_info in self.test_files:
96 |
97 | self.export(note_info)
98 |
--------------------------------------------------------------------------------
/tests/test_harmony.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for io of the harmony musicxml tag.
5 | """
6 |
7 | import unittest
8 | from partitura import load_musicxml
9 | from partitura.score import ChordSymbol, RomanNumeral
10 | from tests import HARMONY_TESTFILES
11 |
12 |
13 | class HarmonyImportTester(unittest.TestCase):
14 | part = load_musicxml(HARMONY_TESTFILES[0])[0]
15 | def test_chordsymbol(self):
16 | roots = list()
17 | kinds = list()
18 | for cs in self.part.iter_all(ChordSymbol):
19 | roots.append(cs.root)
20 | kinds.append(cs.kind)
21 | self.assertEqual(roots, ['C', 'G'])
22 | self.assertEqual(kinds, ['m', '7'])
23 |
24 | def test_romanNumeral(self):
25 | text = list()
26 | for cs in self.part.iter_all(RomanNumeral):
27 | text.append(cs.text)
28 | self.assertEqual(text, ['i', 'V7'])
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/tests/test_kern.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for KERN import and export.
5 | """
6 | import unittest
7 |
8 | import partitura
9 | import os
10 | from tests import KERN_TESTFILES, KERN_TIES, KERN_PATH
11 | from tempfile import TemporaryDirectory
12 | from partitura.score import merge_parts
13 | from partitura.utils import ensure_notearray
14 | from partitura.io.importkern import load_kern
15 | from partitura.io.exportkern import save_kern
16 | from partitura import load_musicxml
17 | import numpy as np
18 |
19 |
20 | class TestImportKERN(unittest.TestCase):
21 | def test_example_kern(self):
22 | document_path = partitura.EXAMPLE_KERN
23 | kern_part = merge_parts(load_kern(document_path))
24 | xml_part = load_musicxml(partitura.EXAMPLE_MUSICXML)
25 | ka = ensure_notearray(kern_part)
26 | xa = ensure_notearray(xml_part)
27 | self.assertTrue(
28 | np.all(ka["onset_beat"] == xa["onset_beat"]),
29 | "Kern onset beats do not match target",
30 | )
31 | self.assertTrue(
32 | np.all(ka["duration_beat"] == xa["duration_beat"]),
33 | "Kern duration beats do not match target.",
34 | )
35 |
36 | def test_examples(self):
37 | for fn in KERN_TESTFILES:
38 | score = load_kern(fn)
39 | self.assertTrue(True)
40 |
41 | def test_chorale_import(self):
42 | file_path = os.path.join(KERN_PATH, "chor228.krn")
43 | score = load_kern(file_path)
44 | num_measures = 8
45 | num_parts = 4
46 | num_notes = 102
47 | self.assertTrue(len(score.parts) == num_parts)
48 | self.assertTrue(all([len(part.measures) == num_measures for part in score.parts]))
49 | self.assertTrue(len(score.note_array()) == num_notes)
50 |
51 | def test_tie_mismatch(self):
52 |
53 | fn = KERN_TIES[0]
54 | score = load_kern(fn)
55 |
56 | self.assertTrue(True)
57 |
58 | def test_spline_splitting(self):
59 | file_path = os.path.join(KERN_PATH, "spline_splitting.krn")
60 | score = load_kern(file_path)
61 | num_parts = 4
62 | voices_per_part = [2, 1, 1, 2]
63 | self.assertTrue(num_parts == len(score.parts))
64 | for i, part in enumerate(score.parts):
65 | vn = part.note_array()["voice"].max()
66 | self.assertTrue(voices_per_part[i] == vn)
67 |
68 | def test_import_export(self):
69 | imported_score = load_kern(partitura.EXAMPLE_KERN)
70 | with TemporaryDirectory() as tmpdir:
71 | out = os.path.join(tmpdir, "test.match")
72 | save_kern(imported_score, out)
73 | exported_score = load_kern(out)
74 | im_na = imported_score.note_array(include_staff=True)
75 | ex_na = exported_score.note_array(include_staff=True)
76 | self.assertTrue(np.all(im_na["onset_beat"] == ex_na["onset_beat"]))
77 | self.assertTrue(np.all(im_na["duration_beat"] == ex_na["duration_beat"]))
78 | self.assertTrue(np.all(im_na["pitch"] == ex_na["pitch"]))
79 | self.assertTrue(np.all(im_na["staff"] == ex_na["staff"]))
80 | # NOTE: Voices are not the same because of the way voices are assigned in merge_parts
81 |
82 |
83 | # if __name__ == "__main__":
84 | # unittest.main()
85 |
--------------------------------------------------------------------------------
/tests/test_key_estimation.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for the key estimation methods.
5 | """
6 | import unittest
7 |
8 | from partitura import EXAMPLE_MUSICXML
9 | from partitura import load_musicxml
10 | from partitura.musicanalysis import estimate_key
11 | from partitura.utils import key_name_to_fifths_mode, fifths_mode_to_key_name
12 |
13 |
14 | class KeyModeComputation(unittest.TestCase):
15 | minor_sharps = ["Em", "Bm", "F#m", "C#m", "G#m", "D#m", "A#m"]
16 | minor_flats = ["Dm", "Gm", "Cm", "Fm", "Bbm", "Ebm", "Abm"]
17 | major_sharps = ["G", "D", "A", "E", "B", "F#", "C#"]
18 | major_flats = ["F", "Bb", "Eb", "Ab", "Db", "Gb", "Cb"]
19 |
20 | def test_key_name_to_fifths_mode(self):
21 | self.assertEqual((0, "minor"), key_name_to_fifths_mode("Am"))
22 | self.assertEqual((0, "major"), key_name_to_fifths_mode("C"))
23 | [
24 | self.assertEqual((i + 1, "minor"), key_name_to_fifths_mode(a))
25 | for i, a in enumerate(self.minor_sharps)
26 | ]
27 | [
28 | self.assertEqual((-(i + 1), "minor"), key_name_to_fifths_mode(a))
29 | for i, a in enumerate(self.minor_flats)
30 | ]
31 | [
32 | self.assertEqual((i + 1, "major"), key_name_to_fifths_mode(a))
33 | for i, a in enumerate(self.major_sharps)
34 | ]
35 | [
36 | self.assertEqual((-(i + 1), "major"), key_name_to_fifths_mode(a))
37 | for i, a in enumerate(self.major_flats)
38 | ]
39 |
40 | def test_fifths_modes_to_key_name(self):
41 | self.assertEqual("Am", fifths_mode_to_key_name(0, "minor"))
42 | self.assertEqual("C", fifths_mode_to_key_name(0, "major"))
43 | [
44 | self.assertEqual(a, fifths_mode_to_key_name(i + 1, "minor"))
45 | for i, a in enumerate(self.minor_sharps)
46 | ]
47 | [
48 | self.assertEqual(a, fifths_mode_to_key_name(-(i + 1), "minor"))
49 | for i, a in enumerate(self.minor_flats)
50 | ]
51 | [
52 | self.assertEqual(
53 | a,
54 | fifths_mode_to_key_name(i + 1, "major"),
55 | )
56 | for i, a in enumerate(self.major_sharps)
57 | ]
58 | [
59 | self.assertEqual(a, fifths_mode_to_key_name(-(i + 1), "major"))
60 | for i, a in enumerate(self.major_flats)
61 | ]
62 |
63 |
64 | class TestKeyEstimation(unittest.TestCase):
65 | """
66 | Test key estimation
67 | """
68 |
69 | score = load_musicxml(EXAMPLE_MUSICXML)
70 |
71 | def test_part(self):
72 | key = estimate_key(self.score)
73 | self.assertTrue(key == "Am", "Incorrect key")
74 |
75 | def test_note_array(self):
76 | key = estimate_key(self.score.note_array())
77 | self.assertTrue(key == "Am", "Incorrect key")
78 |
79 |
80 | if __name__ == "__main__":
81 | unittest.main()
82 |
--------------------------------------------------------------------------------
/tests/test_load_performance.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for the `load_performance` method
5 | """
6 | import unittest
7 | import numpy as np
8 | from tests import MOZART_VARIATION_FILES
9 |
10 |
11 | from partitura import load_performance_midi, EXAMPLE_MIDI
12 | from partitura.io import NotSupportedFormatError
13 | from partitura.performance import Performance
14 |
15 |
16 | class TestLoadPerformance(unittest.TestCase):
17 | def test_load_performance(self):
18 | for fn in [MOZART_VARIATION_FILES["midi"]] + [EXAMPLE_MIDI]:
19 | try:
20 | print(fn)
21 | performance = load_performance_midi(fn)
22 | self.assertTrue(isinstance(performance, Performance))
23 | except NotSupportedFormatError:
24 | self.assertTrue(False)
25 |
26 | def test_array_performance(self):
27 | for fn in [EXAMPLE_MIDI]:
28 | performance = load_performance_midi(fn)
29 | na = performance.note_array()
30 | self.assertTrue(np.all(na["onset_sec"] * 24 == na["onset_tick"]))
31 |
32 |
33 | if __name__ == "__main__":
34 | unittest.main()
35 |
--------------------------------------------------------------------------------
/tests/test_load_score.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for the `load_score` method.
5 | """
6 | import unittest
7 |
8 | from tests import (
9 | MUSICXML_IMPORT_EXPORT_TESTFILES,
10 | MEI_TESTFILES,
11 | KERN_TESTFILES,
12 | MATCH_IMPORT_EXPORT_TESTFILES,
13 | )
14 |
15 |
16 | from partitura import (
17 | load_score,
18 | EXAMPLE_MIDI,
19 | EXAMPLE_KERN,
20 | EXAMPLE_MEI,
21 | EXAMPLE_MUSICXML,
22 | )
23 | from partitura.io import NotSupportedFormatError
24 | from partitura.score import Part, PartGroup, Score
25 |
26 |
27 | EXAMPLE_FILES = [EXAMPLE_MIDI, EXAMPLE_KERN, EXAMPLE_MEI, EXAMPLE_MUSICXML]
28 |
29 |
30 | class TestLoadScore(unittest.TestCase):
31 | def test_load_score(self):
32 |
33 | for fn in (
34 | MUSICXML_IMPORT_EXPORT_TESTFILES
35 | + MEI_TESTFILES
36 | + KERN_TESTFILES
37 | + MATCH_IMPORT_EXPORT_TESTFILES
38 | + EXAMPLE_FILES
39 | ):
40 | self.check_return_type(fn)
41 |
42 | def check_return_type(self, fn):
43 | score = load_score(fn)
44 | self.assertTrue(isinstance(score, Score), f"results of load_score type are not Score for score {fn}.")
45 | for pp in score.part_structure:
46 | self.assertTrue(type(pp) in (Part, PartGroup), f"results of score.part_structure type are neither Part or PartGroup for score {fn}.")
47 | for pp in score.parts:
48 | self.assertTrue(isinstance(pp, Part), f"results of score.parts type are not Part for score {fn}.")
49 |
--------------------------------------------------------------------------------
/tests/test_match_export.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for Matchfile import
5 | """
6 | import unittest
7 | import numpy as np
8 | import re
9 | import os
10 | from tempfile import TemporaryDirectory
11 |
12 | from tests import MOZART_VARIATION_FILES
13 |
14 | from partitura.io.exportmatch import matchfile_from_alignment, save_match
15 | from partitura.io.importmatch import load_match
16 | from partitura import load_score
17 |
18 |
19 | class TestExportMatch(unittest.TestCase):
20 | def test_matchfile_from_alignment(self):
21 | """
22 | test `matchfile_from_alignment`
23 | """
24 | score_fn = MOZART_VARIATION_FILES["musicxml"]
25 |
26 | score = load_score(score_fn)
27 | spart = score[0]
28 | match_fn = MOZART_VARIATION_FILES["match"]
29 | performance, alignment = load_match(match_fn)
30 |
31 | matchfile = matchfile_from_alignment(
32 | alignment=alignment,
33 | ppart=performance[0],
34 | spart=spart,
35 | assume_part_unfolded=True,
36 | )
37 |
38 | sna = spart.note_array()
39 | pna = performance.note_array()
40 |
41 | # assert that matchfile contains the same number of notes
42 | self.assertTrue(len(sna) == len(matchfile.snotes))
43 | self.assertTrue(len(pna) == len(matchfile.notes))
44 |
45 | snote_ids = [n.Anchor for n in matchfile.snotes]
46 | pnote_ids = [n.Id for n in matchfile.notes]
47 | # assert that all snotes in the matchfile are in the note array
48 | self.assertTrue(all([n.Anchor in sna["id"] for n in matchfile.snotes]))
49 |
50 | # assert that all notes in the score are in the matchfile
51 | self.assertTrue(all([nid in snote_ids for nid in sna["id"]]))
52 |
53 | # assert that all notes in the matchfile are in the note array
54 | self.assertTrue(all([n.Id in pna["id"] for n in matchfile.notes]))
55 |
56 | # assert that all notes in the performance are in the matchfile
57 | self.assertTrue(all(nid in pnote_ids for nid in pna["id"]))
58 |
59 | for ml in matchfile.lines:
60 | self.assertTrue(isinstance(ml.matchline, str))
61 |
62 | def test_save_match(self):
63 | """
64 | Test save_match
65 | """
66 | score_fn = MOZART_VARIATION_FILES["musicxml"]
67 |
68 | score = load_score(score_fn)
69 | match_fn = MOZART_VARIATION_FILES["match"]
70 | performance, alignment = load_match(match_fn)
71 | pna1 = performance.note_array()
72 | with TemporaryDirectory() as tmpdir:
73 |
74 | out = os.path.join(tmpdir, "test.match")
75 | save_match(
76 | alignment=alignment,
77 | performance_data=performance,
78 | score_data=score,
79 | out=out,
80 | performer="A Pianist",
81 | composer="W. A. Mozart",
82 | piece="mozart_k265_var1",
83 | score_filename=os.path.basename(score_fn),
84 | performance_filename=os.path.basename(MOZART_VARIATION_FILES["midi"]),
85 | assume_unfolded=True,
86 | )
87 |
88 | perf_from_saved_match, alignment_from_saved_match = load_match(out)
89 |
90 | pna2 = perf_from_saved_match.note_array()
91 |
92 | # Test that performance data is the same
93 | for field in (
94 | "onset_sec",
95 | "duration_sec",
96 | "onset_tick",
97 | "duration_tick",
98 | "pitch",
99 | "velocity",
100 | ):
101 | self.assertTrue(np.allclose(pna2[field], pna1[field]))
102 |
103 | # Test that the alignment info is correct
104 | for al in alignment_from_saved_match:
105 | self.assertTrue(al in alignment)
106 |
107 | for al in alignment:
108 | self.assertTrue(al in alignment_from_saved_match)
109 |
--------------------------------------------------------------------------------
/tests/test_merge_parts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for the utilities for merging parts.
5 | """
6 | import numpy as np
7 | import logging
8 | import unittest
9 | from pathlib import Path
10 |
11 | from partitura import load_musicxml, load_mei
12 | from partitura.score import merge_parts, Part, iter_parts
13 | from partitura.utils.music import ensure_notearray
14 |
15 | from tests import MERGE_PARTS_TESTFILES
16 |
17 | LOGGER = logging.getLogger(__name__)
18 |
19 |
20 | class TestMergeParts(unittest.TestCase):
21 | """
22 | Test merge parts utility
23 | """
24 |
25 | def test_list_of_parts_and_partgroup(self):
26 | score = load_musicxml(MERGE_PARTS_TESTFILES[1])
27 | merged_part = merge_parts(score.parts)
28 | note_array = merged_part.note_array()
29 | expected_onsets = [0, 0, 0, 0, 0, 0, 12, 15, 24, 24, 32, 40, 48]
30 | expected_pitches = [48, 50, 53, 62, 67, 69, 64, 65, 47, 69, 67, 64, 60]
31 | expected_duration = [24, 24, 24, 12, 24, 24, 3, 3, 24, 8, 8, 8, 24]
32 | self.assertTrue(np.array_equal(note_array["onset_div"], expected_onsets))
33 | self.assertTrue(np.array_equal(note_array["pitch"], expected_pitches))
34 | self.assertTrue(np.array_equal(note_array["duration_div"], expected_duration))
35 |
36 | def test_different_divs(self):
37 | score = load_musicxml(MERGE_PARTS_TESTFILES[1])
38 | merged_part = merge_parts(score.parts)
39 | note_array = merged_part.note_array()
40 | expected_onsets = [0, 0, 0, 0, 0, 0, 12, 15, 24, 24, 32, 40, 48]
41 | expected_pitches = [48, 50, 53, 62, 67, 69, 64, 65, 47, 69, 67, 64, 60]
42 | self.assertTrue(np.array_equal(note_array["onset_div"], expected_onsets))
43 | self.assertTrue(np.array_equal(note_array["pitch"], expected_pitches))
44 |
45 | def test_compare_normal_and_different_divs(self):
46 | score_normal = load_musicxml(MERGE_PARTS_TESTFILES[1])
47 | score_diff = load_musicxml(MERGE_PARTS_TESTFILES[2])
48 | merged_part_normal = merge_parts(score_normal.parts)
49 | merged_part_diff = merge_parts(score_diff.parts)
50 | note_array_normal = merged_part_normal.note_array()
51 | note_array_diff = merged_part_diff.note_array()
52 | self.assertTrue(
53 | np.array_equal(
54 | note_array_normal["onset_beat"], note_array_diff["onset_beat"]
55 | )
56 | )
57 |
58 | def test_merge_single_part(self):
59 | score = load_musicxml(MERGE_PARTS_TESTFILES[3])
60 | merged_part = merge_parts(score.parts)
61 | self.assertTrue(merged_part == score[0])
62 |
63 | # def test_merge_interpolation(self):
64 | # parts = load_musicxml(MERGE_PARTS_TESTFILES[4])
65 | # merged_part = merge_parts(parts)
66 | # self.assertTrue(isinstance(merged_part, Part))
67 |
68 | def test_reassign_voices(self):
69 | score = load_musicxml(MERGE_PARTS_TESTFILES[6])
70 | merged_part = merge_parts(score.parts, reassign="voice")
71 | note_array = merged_part.note_array(include_staff=True)
72 | expected_voices = [3, 2, 1, 1]
73 | expected_staves = [1, 1, 1, 1]
74 | self.assertTrue(note_array["voice"].tolist() == expected_voices)
75 | self.assertTrue(note_array["staff"].tolist() == expected_staves)
76 |
77 | def test_reassign_voices2(self):
78 | score = load_musicxml(MERGE_PARTS_TESTFILES[7])
79 | merged_part = merge_parts(score.parts, reassign="voice")
80 | note_array = merged_part.note_array(include_staff=True)
81 | expected_voices = [4, 4, 3, 2, 1, 1]
82 | expected_staves = [2, 1, 1, 1, 1, 1]
83 | self.assertTrue(note_array["voice"].tolist() == expected_voices)
84 | self.assertTrue(note_array["staff"].tolist() == expected_staves)
85 |
86 | def test_reassign_staves(self):
87 | score = load_musicxml(MERGE_PARTS_TESTFILES[6])
88 | merged_part = merge_parts(score.parts, reassign="staff")
89 | note_array = merged_part.note_array(include_staff=True)
90 | expected_voices = [1, 2, 1, 1]
91 | expected_staves = [2, 1, 1, 1]
92 | self.assertTrue(note_array["voice"].tolist() == expected_voices)
93 | self.assertTrue(note_array["staff"].tolist() == expected_staves)
94 |
95 | def test_reassign_staves2(self):
96 | score = load_musicxml(MERGE_PARTS_TESTFILES[7])
97 | merged_part = merge_parts(score.parts, reassign="staff")
98 | note_array = merged_part.note_array(include_staff=True)
99 | expected_voices = [1, 1, 1, 2, 1, 1]
100 | expected_staves = [4, 3, 2, 1, 1, 1]
101 | self.assertTrue(note_array["voice"].tolist() == expected_voices)
102 | self.assertTrue(note_array["staff"].tolist() == expected_staves)
103 |
104 | def test_reassign_auto(self):
105 | score = load_mei(MERGE_PARTS_TESTFILES[8])
106 | merged_part = merge_parts(score.parts, reassign="auto")
107 | note_array = merged_part.note_array(include_staff=True)
108 | expected_voices = [13, 9, 5, 2, 1, 1]
109 | expected_staves = [4, 3, 2, 1, 1, 1 ]
110 | self.assertEqual(note_array["voice"].tolist(),expected_voices)
111 | self.assertEqual(note_array["staff"].tolist(),expected_staves)
112 |
--------------------------------------------------------------------------------
/tests/test_metrical_position.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for the metrical position computation
5 | """
6 |
7 | import unittest
8 | from partitura import load_musicxml
9 | from partitura.utils.music import note_array_from_part
10 | from partitura.score import TimeSignature
11 |
12 | import numpy as np
13 |
14 | from tests import (
15 | METRICAL_POSITION_TESTFILES,
16 | TIME_SIGNATURE_MAP_EDGECASES_TESTFILES,
17 | )
18 |
19 |
20 | class TestMetricalPosition(unittest.TestCase):
21 | def test_measure_map(self):
22 | score = load_musicxml(METRICAL_POSITION_TESTFILES[0])
23 | notes = score[0].notes
24 | measures_for_notes = score[0].measure_map([n.start.t for n in notes])
25 | expected_measures_for_notes = (
26 | np.array( # the start and end of measures that we expect
27 | [(16 - 48, 16) for i in range(2)]
28 | + [(16, 64) for i in range(6)]
29 | + [(64, 128) for i in range(5)]
30 | + [(128, 200) for i in range(8)]
31 | + [(200, 232) for i in range(2)]
32 | )
33 | )
34 | self.assertTrue(np.array_equal(measures_for_notes, expected_measures_for_notes))
35 |
36 | def test_metrical_position_map(self):
37 | score = load_musicxml(METRICAL_POSITION_TESTFILES[0])
38 | note_array = note_array_from_part(score[0], include_metrical_position=True)
39 | expected_notes_on_downbeat = [2, 3, 8, 9, 13, 21]
40 | expected_rel_positions = [
41 | 32,
42 | 40,
43 | 0,
44 | 0,
45 | 24,
46 | 28,
47 | 32,
48 | 40,
49 | 0,
50 | 0,
51 | 24,
52 | 48,
53 | 56,
54 | 0,
55 | 16,
56 | 32,
57 | 33,
58 | 34,
59 | 36,
60 | 40,
61 | 48,
62 | 0,
63 | 16,
64 | ]
65 | expected_measure_duration = (
66 | [48 for i in range(2)]
67 | + [48 for i in range(6)]
68 | + [64 for i in range(5)]
69 | + [72 for i in range(8)]
70 | + [32 for i in range(2)]
71 | )
72 | # test if all downbeats are in the right place
73 | self.assertTrue(
74 | np.array_equal(
75 | np.flatnonzero(note_array["is_downbeat"]), expected_notes_on_downbeat
76 | )
77 | )
78 | self.assertTrue(
79 | np.array_equal(note_array["rel_onset_div"], expected_rel_positions)
80 | )
81 | self.assertTrue(
82 | np.array_equal(
83 | note_array["tot_measure_div"],
84 | expected_measure_duration,
85 | )
86 | )
87 |
88 | def test_measure_number_map(self):
89 | score = load_musicxml(METRICAL_POSITION_TESTFILES[0])
90 | notes = score[0].notes
91 | measure_numbers_for_notes = score[0].measure_number_map(
92 | [n.start.t for n in notes]
93 | )
94 | expected_measure_numbers_for_notes = (
95 | np.array( # the start and end of measures that we expect
96 | [1 for i in range(2)]
97 | + [2 for i in range(6)]
98 | + [3 for i in range(5)]
99 | + [4 for i in range(8)]
100 | + [5 for i in range(2)]
101 | )
102 | )
103 | self.assertTrue(
104 | np.array_equal(
105 | measure_numbers_for_notes, expected_measure_numbers_for_notes
106 | )
107 | )
108 |
109 | def test_anacrusis_downbeat(self):
110 | score = load_musicxml(METRICAL_POSITION_TESTFILES[1])
111 | note_array = note_array_from_part(score[0], include_metrical_position=True)
112 | # first note on the anacrusis is not a downbeat
113 | self.assertTrue(note_array["is_downbeat"][0] == 0)
114 | self.assertTrue(note_array["rel_onset_div"][0] == 3)
115 |
116 |
117 | class TestTimeSignatureMap(unittest.TestCase):
118 | def test_time_signature_map(self):
119 | for fn in TIME_SIGNATURE_MAP_EDGECASES_TESTFILES:
120 | score = load_musicxml(fn)
121 |
122 | for part in score:
123 |
124 | tss = np.array(
125 | [
126 | (ts.start.t, ts.beats, ts.beat_type, ts.musical_beats)
127 | for ts in part.iter_all(TimeSignature)
128 | ]
129 | )
130 |
131 | self.assertTrue(
132 | np.all(part.time_signature_map(part.first_point.t) == tss[0, 1:])
133 | )
134 |
135 |
136 |
137 |
138 | if __name__ == "__main__":
139 | unittest.main()
140 |
--------------------------------------------------------------------------------
/tests/test_musescore.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This file contains test functions for MEI import
5 | """
6 |
7 | import unittest
8 |
9 | from tests import MUSESCORE_TESTFILES
10 | from partitura import load_musicxml, load_mei, EXAMPLE_MEI
11 | import partitura.score as score
12 | from partitura.io.importmei import MeiParser
13 | from partitura.utils import compute_pianoroll
14 | from lxml import etree
15 | from xmlschema.names import XML_NAMESPACE
16 | from partitura.io import load_score, load_via_musescore
17 | from partitura.io.musescore import find_musescore, MuseScoreNotFoundException
18 | import platform
19 |
20 | import numpy as np
21 | from pathlib import Path
22 |
23 | try:
24 | if find_musescore():
25 | class TestImportMusescore(unittest.TestCase):
26 | def test_epfl_scores(self):
27 | score = load_via_musescore(MUSESCORE_TESTFILES[0])
28 | self.assertTrue(len(score.parts) == 1)
29 | # try the generic loading function
30 | score = load_score(MUSESCORE_TESTFILES[0])
31 | self.assertTrue(len(score.parts) == 1)
32 | except MuseScoreNotFoundException:
33 | pass
34 |
--------------------------------------------------------------------------------
/tests/test_nakamura.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for the import of Nakamura et al.'s match and
5 | corresp file formats.
6 | """
7 |
8 | import unittest
9 | from partitura.io.importnakamura import load_nakamuracorresp, load_nakamuramatch
10 |
11 | from tests import NAKAMURA_IMPORT_TESTFILES
12 |
13 |
14 | class TestLoadNakamura(unittest.TestCase):
15 | def test_import(self):
16 | for fn in NAKAMURA_IMPORT_TESTFILES:
17 | if "corresp" in fn:
18 | performance, score, align = load_nakamuracorresp(fn)
19 | performance_ids = set(
20 | item["performance_id"]
21 | for item in align
22 | if item["label"] in ("match", "insertion")
23 | )
24 | score_ids = set(
25 | item["score_id"]
26 | for item in align
27 | if item["label"] in ("match", "deletion")
28 | )
29 | self.assertTrue(len(performance_ids) == len(performance))
30 | self.assertTrue(len(score_ids) == len(score))
31 | else:
32 | performance, score, align = load_nakamuramatch(fn)
33 | performance_ids = set(
34 | item["performance_id"]
35 | for item in align
36 | if item["label"] in ("match", "insertion")
37 | )
38 | score_ids = set(
39 | item["score_id"]
40 | for item in align
41 | if item["label"] in ("match", "deletion")
42 | )
43 | self.assertTrue(len(performance_ids) == len(performance))
44 | self.assertTrue(len(score_ids) == len(score))
45 |
46 |
47 | if __name__ == "__main__":
48 |
49 | unittest.main()
50 |
--------------------------------------------------------------------------------
/tests/test_note_features.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for methods for generating note-level features.
5 | """
6 | import unittest
7 | from tests import (
8 | METRICAL_POSITION_TESTFILES,
9 | MUSICXML_IMPORT_EXPORT_TESTFILES,
10 | MEI_TESTFILES,
11 | MUSICXML_NOTE_FEATURES,
12 | )
13 | from partitura import load_musicxml, load_mei
14 | from partitura.musicanalysis import make_note_feats, compute_note_array
15 | import numpy as np
16 |
17 |
18 | class TestingNoteFeatureExtraction(unittest.TestCase):
19 | def test_metrical_basis(self):
20 | for fn in METRICAL_POSITION_TESTFILES:
21 | score = load_musicxml(fn, force_note_ids = "keep")
22 | make_note_feats(score[0], ["metrical_feature"])
23 |
24 | def test_grace_basis(self):
25 | fn = [f for f in MEI_TESTFILES if f.endswith("test_grace_note.mei")][0]
26 | part = load_mei(fn)
27 | make_note_feats(part, ["grace_feature"])
28 |
29 | def test_all_basis(self):
30 | for fn in MUSICXML_IMPORT_EXPORT_TESTFILES:
31 | score = load_musicxml(fn)
32 | make_note_feats(score[0], "all")
33 |
34 | def test_slur_grace_art_dyn_orn(self):
35 | for fn in MUSICXML_NOTE_FEATURES:
36 | score = load_musicxml(fn, force_note_ids=True)
37 | feats = [
38 | "ornament_feature",
39 | "articulation_feature",
40 | "grace_feature",
41 | "loudness_direction_feature",
42 | "slur_feature",
43 | ]
44 | na = compute_note_array(score[0], feature_functions=feats)
45 | stactest = na["articulation_feature.staccato"] == np.array(
46 | [1, 0, 0, 0, 0, 0]
47 | )
48 | tentest = na["articulation_feature.tenuto"] == np.array([0, 1, 0, 0, 0, 0])
49 | trilltest = na["ornament_feature.trill-mark"] == np.array(
50 | [0, 0, 1, 0, 0, 0]
51 | )
52 | gracetest = na["grace_feature.grace_note"] == np.array([0, 0, 0, 1, 0, 1])
53 | dyntest = na["loudness_direction_feature.f"] == np.array([0, 0, 0, 1, 1, 1])
54 | slurtest = na["slur_feature.slur_decr"] == np.array([0, 0, 0, 1, 1, 1])
55 | self.assertTrue(np.all(stactest), "staccato feature does not match")
56 | self.assertTrue(np.all(tentest), "tenuto feature does not match")
57 | self.assertTrue(np.all(trilltest), "trill feature does not match")
58 | self.assertTrue(np.all(gracetest), "grace feature does not match")
59 | self.assertTrue(np.all(dyntest), "forte feature does not match")
60 | self.assertTrue(np.all(slurtest), "slur feature does not match")
61 |
62 | def test_measure_feature(self):
63 | for fn in MUSICXML_NOTE_FEATURES:
64 | score = load_musicxml(fn, force_note_ids=True)
65 | feats = [
66 | "measure_feature"
67 | ]
68 | na = compute_note_array(score[0], feature_functions=feats)
69 |
70 | numtest = na["measure_feature.measure_number"] == np.array([1, 1, 1, 2, 2, 2])
71 | starttest = na["measure_feature.measure_start_beat"] == np.array([0, 0, 0, 4, 4, 4])
72 | endtest = na["measure_feature.measure_end_beat"] == np.array([4, 4, 4, 8, 8, 8])
73 | self.assertTrue(np.all(numtest), "measure number feature does not match")
74 | self.assertTrue(np.all(starttest), "measure start feature does not match")
75 | self.assertTrue(np.all(endtest), "measure end feature does not match")
76 |
77 |
78 |
79 | if __name__ == "__main__":
80 | unittest.main()
81 |
--------------------------------------------------------------------------------
/tests/test_octave_shift.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from partitura import EXAMPLE_MUSICXML
3 | from partitura import load_score
4 | from partitura.score import OctaveShiftDirection
5 | import numpy as np
6 | from tests import OCTAVE_SHIFT_TESTFILES
7 |
8 |
9 | class OctaveShift(unittest.TestCase):
10 | def test_octave_shift(self):
11 | part = load_score(EXAMPLE_MUSICXML)[0]
12 | na = part.note_array(include_pitch_spelling=True, include_staff=True)
13 | # na["octave"][na["staff"] == 1] += 1
14 | # Octave shift is applied to the 1st staff
15 | shift_part = load_score(OCTAVE_SHIFT_TESTFILES[0])[0]
16 | octave_post_shift = shift_part.note_array(include_pitch_spelling=True)["octave"]
17 | self.assertEqual(np.all(na["octave"] == octave_post_shift), True)
18 |
19 |
20 | if __name__ == '__main__':
21 | unittest.main()
22 |
--------------------------------------------------------------------------------
/tests/test_parangonada.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for Parangonada import and export.
5 | """
6 |
7 | import logging
8 | import unittest
9 | import tempfile
10 | import os
11 |
12 | from partitura import load_score, load_match
13 | from partitura.io.exportparangonada import (
14 | save_parangonada_alignment,
15 | save_alignment_for_ASAP,
16 | save_parangonada_csv,
17 | )
18 |
19 | from partitura.io.importparangonada import (
20 | load_parangonada_alignment,
21 | load_alignment_from_ASAP,
22 | _load_csv,
23 | load_parangonada_csv,
24 | )
25 |
26 |
27 | from tests import MOZART_VARIATION_FILES
28 |
29 | LOGGER = logging.getLogger(__name__)
30 |
31 | test_alignment = [
32 | {"label": "match", "score_id": "n01", "performance_id": "n01"},
33 | {"label": "insertion", "performance_id": "n02"},
34 | {"label": "deletion", "score_id": "n02"},
35 | ]
36 |
37 |
38 | _performance, _alignment = load_match(filename=MOZART_VARIATION_FILES["match"])
39 | MOZART_VARIATION_DATA = dict(
40 | score=load_score(MOZART_VARIATION_FILES["musicxml"]),
41 | performance=_performance,
42 | alignment=_alignment,
43 | parangonada_align=_load_csv(
44 | MOZART_VARIATION_FILES["parangonada_align"],
45 | ),
46 | parangonada_zalign=_load_csv(
47 | MOZART_VARIATION_FILES["parangonada_zalign"],
48 | ),
49 | parangonada_feature=_load_csv(MOZART_VARIATION_FILES["parangonada_feature"]),
50 | parangonada_ppart=_load_csv(MOZART_VARIATION_FILES["parangonada_ppart"]),
51 | parangonada_spart=_load_csv(MOZART_VARIATION_FILES["parangonada_spart"]),
52 | )
53 |
54 |
55 | class Ppart:
56 | def __init__(self):
57 | self.notes = [
58 | {
59 | "id": "n01",
60 | "track": "dummy",
61 | "channel": "dummy",
62 | "midi_pitch": "dummy",
63 | "note_on": "dummy",
64 | },
65 | {
66 | "id": "n02",
67 | "track": "dummy",
68 | "channel": "dummy",
69 | "midi_pitch": "dummy",
70 | "note_on": "dummy",
71 | },
72 | ]
73 |
74 | # Make dummy Ppart iterable
75 | def __getitem__(self, index):
76 | return self
77 |
78 | def __iter__(self):
79 | return self
80 |
81 | def __next__(self):
82 | return self
83 |
84 | def __len__(self):
85 | return 1
86 |
87 |
88 | test_ppart = Ppart()
89 |
90 |
91 | class TestIO(unittest.TestCase):
92 | """
93 | Test if the csv, tsv export and import gives the expected results.
94 |
95 | """
96 |
97 | def test_csv_import_export(self):
98 | with tempfile.TemporaryDirectory() as tmpdirname:
99 | save_parangonada_alignment(
100 | out=os.path.join(tmpdirname, "align.csv"), alignment=test_alignment
101 | )
102 | import_alignment = load_parangonada_alignment(
103 | os.path.join(tmpdirname, "align.csv")
104 | )
105 | equal = test_alignment == import_alignment
106 | self.assertTrue(equal)
107 |
108 | def test_tsv_import_export(self):
109 | with tempfile.TemporaryDirectory() as tmpdirname:
110 | save_alignment_for_ASAP(
111 | out=os.path.join(tmpdirname, "align.tsv"),
112 | performance_data=test_ppart,
113 | alignment=test_alignment,
114 | )
115 | import_alignment = load_alignment_from_ASAP(
116 | os.path.join(tmpdirname, "align.tsv")
117 | )
118 | equal = test_alignment == import_alignment
119 | self.assertTrue(equal)
120 |
121 | def test_save_parangonada_csv(self):
122 |
123 | with tempfile.TemporaryDirectory() as tmpdirname:
124 |
125 | save_parangonada_csv(
126 | alignment=MOZART_VARIATION_DATA["alignment"],
127 | performance_data=MOZART_VARIATION_DATA["performance"],
128 | score_data=MOZART_VARIATION_DATA["score"],
129 | outdir=tmpdirname,
130 | )
131 |
132 | performance, alignment, _, _ = load_parangonada_csv(tmpdirname)
133 |
134 | self.assertTrue(alignment == MOZART_VARIATION_DATA["alignment"])
135 |
136 |
137 | if __name__ == "__main__":
138 | unittest.main()
139 |
--------------------------------------------------------------------------------
/tests/test_part_properties.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains tests for part properties.
5 | """
6 | import unittest
7 | import partitura
8 | from partitura import score
9 |
10 |
11 | class TestingPartProperties(unittest.TestCase):
12 | def test_props(self):
13 | part = score.Part("P0", "My Part")
14 | part.set_quarter_duration(0, 10)
15 | part.add(score.KeySignature(0, ""), start=0)
16 | part.add(score.TimeSignature(3, 4), start=0)
17 | part.add(score.TimeSignature(4, 4), start=30)
18 | part.add(score.Note(id="n0", step="A", octave=4), start=0, end=10)
19 | part.add(score.Rest(id="r0"), start=10, end=20)
20 | part.add(score.Note(id="n1", step="A", octave=4), start=20, end=70)
21 | part.add(score.ImpulsiveLoudnessDirection("sfz", "sfz"), start=20, end=20)
22 | part.add(score.ArticulationDirection("staccato", "staccato"), start=0, end=0)
23 | score.add_measures(part)
24 | score.tie_notes(part)
25 |
26 | self.assertTrue(len(part.notes) == 3)
27 | self.assertTrue(len(part.notes_tied) == 2)
28 | self.assertTrue(len(part.measures) == 2)
29 | self.assertTrue(len(part.time_sigs) == 2)
30 | self.assertTrue(len(part.key_sigs) == 1)
31 | self.assertTrue(len(part.rests) == 1)
32 | self.assertTrue(len(part.articulations) == 1)
33 | self.assertTrue(len(part.dynamics) == 1)
34 | self.assertTrue(len(part.repeats) == 0)
35 |
36 |
37 | if __name__ == "__main__":
38 | unittest.main()
39 |
--------------------------------------------------------------------------------
/tests/test_partial_measures.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | #%%
5 | """
6 | This module contains tests for measures with non-integer IDs in musicxml.
7 |
8 | Such measure IDs can occur in irregular measures (i.e., pickups in the middle of the piece, i.e. variations pieces, measures with fermata or cadenza ornamentations.
9 |
10 | Fix: added 'name' property to measures to reflect non-integer measures.
11 | """
12 | import unittest
13 |
14 | import numpy as np
15 | from partitura.io import load_musicxml
16 | from partitura.score import *
17 |
18 | from tests import MUSICXML_PARTIAL_MEASURES_TESTFILES
19 |
20 |
21 | class TestPartialMeasures(unittest.TestCase):
22 | """
23 | Test parsing of musicxml files with single partial/irregular measures
24 | """
25 |
26 | def test_measure_number_name_single(self):
27 | sc = load_musicxml(MUSICXML_PARTIAL_MEASURES_TESTFILES[0])
28 | spart = sc.parts[0]
29 | spart_variants = make_score_variants(spart)
30 | spart_unfolded = spart_variants[0].create_variant_part()
31 |
32 | unfolded_measure_numbers = [m.number for m in spart_unfolded.measures]
33 | unfolded_measure_names = [m.name for m in spart_unfolded.measures]
34 |
35 | expected_unfolded_measure_numbers = [1,2,3,1,2,4,5,6,7]
36 | expected_unfolded_measure_names = ['1','2','3','1','2','X1','4','X2','5']
37 |
38 | self.assertTrue(
39 | np.array_equal(unfolded_measure_numbers, expected_unfolded_measure_numbers)
40 | )
41 | self.assertTrue(
42 | np.array_equal(unfolded_measure_names, expected_unfolded_measure_names)
43 | )
44 |
45 | def test_measure_number_name_consecutive(self):
46 | sc = load_musicxml(MUSICXML_PARTIAL_MEASURES_TESTFILES[1])
47 | spart = sc.parts[0]
48 |
49 | measure_numbers = [m.number for m in spart.measures]
50 | measure_names = [m.name for m in spart.measures]
51 |
52 | expected_measure_numbers = [1,2,3,4,5,6,7]
53 | expected_measure_names = ['1','2','3','X1','X2','X3','4']
54 |
55 | self.assertTrue(
56 | np.array_equal(measure_numbers, expected_measure_numbers)
57 | )
58 | self.assertTrue(
59 | np.array_equal(measure_names, expected_measure_names)
60 | )
61 |
62 | if __name__ == "__main__":
63 | unittest.main()
--------------------------------------------------------------------------------
/tests/test_performance_codec.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for Performance Array Calculations
5 | """
6 | import unittest
7 | import numpy as np
8 | import numpy.lib.recfunctions as rfn
9 | from tests import MATCH_IMPORT_EXPORT_TESTFILES
10 | from partitura import load_match
11 | from partitura.musicanalysis import encode_performance, decode_performance
12 |
13 |
14 | class TestPerformanceCoded(unittest.TestCase):
15 | def test_encode_decode(self):
16 | for fn in MATCH_IMPORT_EXPORT_TESTFILES:
17 | ppart, alignment, spart = load_match(filename=fn, create_score=True)
18 |
19 | performance_array, _ = encode_performance(spart[0], ppart[0], alignment)
20 | decoded_ppart, decoded_alignment = decode_performance(
21 | spart[0], performance_array, return_alignment=True
22 | )
23 | # normalize ppart notearray onset sec starting from 0.
24 | orig_sec_array = (
25 | ppart[0].note_array()["onset_sec"]
26 | - ppart[0].note_array()["onset_sec"].min()
27 | )
28 | target = np.all(
29 | np.allclose(
30 | np.sort(decoded_ppart.note_array()["onset_sec"]),
31 | np.sort(orig_sec_array),
32 | )
33 | )
34 | self.assertTrue(
35 | target, "The decoded Performed Part doesn't match the original."
36 | )
37 |
38 | def test_beat_normalization(self):
39 | for fn in MATCH_IMPORT_EXPORT_TESTFILES:
40 | ppart, alignment, spart = load_match(filename=fn, create_score=True)
41 |
42 | for normalization in ["beat_period_log",
43 | "beat_period_ratio",
44 | "beat_period_ratio_log",
45 | "beat_period_standardized"]:
46 |
47 | performance_array, _ = encode_performance(spart[0], ppart[0], alignment,
48 | beat_normalization=normalization)
49 | decoded_ppart, decoded_alignment = decode_performance(
50 | spart[0], performance_array, return_alignment=True,
51 | beat_normalization=normalization
52 | )
53 | # normalize ppart notearray onset sec starting from 0.
54 | orig_sec_array = (
55 | ppart[0].note_array()["onset_sec"]
56 | - ppart[0].note_array()["onset_sec"].min()
57 | )
58 | target = np.all(
59 | np.allclose(
60 | np.sort(decoded_ppart.note_array()["onset_sec"]),
61 | np.sort(orig_sec_array),
62 | )
63 | )
64 | self.assertTrue(
65 | target, f"The decoded Performed Part doesn't match the original. (beat_normalization: {normalization})"
66 | )
67 |
68 | def test_custom_tempo(self):
69 | for fn in MATCH_IMPORT_EXPORT_TESTFILES:
70 | ppart, alignment, spart = load_match(filename=fn, create_score=True)
71 |
72 | # TODO: add more custom tempo function to test.
73 | performance_array, _ = encode_performance(spart[0], ppart[0], alignment,
74 | tempo_smooth='derivative')
75 | decoded_ppart, decoded_alignment = decode_performance(
76 | spart[0], performance_array, return_alignment=True
77 | )
78 |
79 | orig_sec_array = (
80 | ppart[0].note_array()["onset_sec"]
81 | - ppart[0].note_array()["onset_sec"].min()
82 | )
83 | target = np.all(
84 | np.allclose(
85 | np.sort(decoded_ppart.note_array()["onset_sec"]),
86 | np.sort(orig_sec_array),
87 | )
88 | )
89 | self.assertTrue(
90 | target, f"The decoded Performed Part doesn't match the original."
91 | )
92 |
93 |
--------------------------------------------------------------------------------
/tests/test_performance_features.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | """
4 | This module contains test functions for Performance Array Calculations
5 | """
6 | import unittest
7 | import numpy as np
8 | from partitura import load_match
9 | from tests import MATCH_EXPRESSIVE_FEATURES_TESTFILES
10 | from partitura.musicanalysis.performance_features import make_performance_features
11 | import os
12 |
13 |
14 | class TestPerformanceFeatures(unittest.TestCase):
15 | def test_performance_features(self):
16 | fields = ['id',
17 | 'articulation_feature.kor', 'pedal_feature.onset_value', 'pedal_feature.offset_value', 'pedal_feature.to_prev_release',
18 | 'pedal_feature.to_next_release', 'onset', 'duration', 'pitch', 'p_onset', 'p_duration', 'velocity', 'beat_period']
19 | True_array = np.array(
20 | [('n1', 0.23374297, 89.74999, 62.000057, 0., 0.16015087, -0.5, 0.5, 59, 4.9925, 0.8775, 44, 1.4700003),
21 | ('n4', 0.03011051, 114.25004, 61.000244, 0.,
22 | 0.4027142, 0., 1., 40, 5.7025, 2.4375, 22, 2.8474998),
23 | ('n3', 0.8451489, 87.500046, 113., 0., 1.5302137, 0., 0.25, 56, 5.77625, 1.23625, 26, 2.8474998)],
24 | dtype=[('id', '