aumouvantsillage / TablaZinc

Generate guitar tablatures using a constraint solver
Mozilla Public License 2.0
138 stars 2 forks source link

TablaZinc

This is an experiment to generate tablatures for fretted string instruments -- such as the guitar, bass, mandolin, banjo, etc -- using a constraint solver.

The input is a melody, represented by an array of MIDI note numbers with no duration indication. The output is a tablature with fingering annotations for the fretting hand.

The src and data folders contain model files and data files written in the MiniZinc language.

Disclaimer

I have no prior experience with constraint programming in general, and MiniZinc in particular.

If you are a beginner in this field and are looking for well-written examples, this repository might not be the right place.

If you are an expert, your feedback will be welcome. Please open a new issue.

Usage

The following command outputs a tablature from two data files (an instrument definition file, and a melody file) using a set of constraints specified in a model file:

minizinc src/<model-file> data/<instrument-file> data/<melody-file>

Example

We provide the following data files:

Three model files are currently available:

-8i--3i--5i--6i--4i--0---1i--3i--0---1i--0---1i--3i--0-----------0---1i--3i--5i--0---1i--3i-
---------------------------------------------------------1i--3i-----------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
-8i-----------------------------------------------------------------------------------------
-----8i-10i-11i--9i----------8i------------------8i--5i-------------------------------------
---------------------9i-10i------9i-10i--9i-10i----------5i--7i--9i-10i-12i-14i-------------
--------------------------------------------------------------------------------14i-15i-17i-
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
-8i-----------------------------------------------------------------------------------------
-----8i-10r-11r--9i---------------------------------------------------------10m-------------
---------------------9i-10m-12p--9i-10m--9i-10m-12p--9i----------9i-10m-12p------9i-10m-12p-
--------------------------------------------------------10m-12p-----------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------

The fingering annotations use the letters i (index), m (middle), r (ring), and p (pinky). If you have a different number of fingers, or if you want to use other letters, you can change the parameter finger_ids in the instrument definition file guitar-std.dzn.

Performance

The tables below show the computation time, in seconds, of the following command with each model file and each supported optimization level. We are using the default solver Gecode with one or two threads.

minizinc -p <n> -O<m> --output-time src/<model-file> data/guitar-std.dzn data/yardbird-suite.dzn

Using one thread (-p 1):

Model file / Optimization -O1 -O2 -O3 -O4 -O5
tablazinc-satisfy.mzn 0.05 0.10 0.09 0.10 0.09
tablazinc-fret-distance.mzn 11.51 12.21 12.04 0.12 0.11
tablazinc-finger-distance.mzn 269.53 234.25 251.93 3.36 3.27

Using two threads (-p 2):

Model file / Optimization -O1 -O2 -O3 -O4 -O5
tablazinc-satisfy.mzn 0.04 0.09 0.09 0.10 0.09
tablazinc-fret-distance.mzn 6.64 7.06 7.05 0.14 0.13
tablazinc-finger-distance.mzn 123.26 106.84 140.68 20.13 17.64

Platform: computer with an Intel Core i5 CPU (2.7 GHz) running Ubuntu 18.04.

Optimization levels -O4 and -O5 show a huge improvement compared to the other levels. Using two threads usually result in longer solving times at the highest optimization levels, but the performance can vary a lot between runs for no obvious reasons.

For instance, I have run the model tablazinc-finger-distance.mzn with options -p 2 -O4 three times in a row and got: 0.76sec, 6.95sec, and 38.17sec.