Ability to Transpose via CLI

• Apr 17, 2019 - 22:00

This is probably a bit on the ridiculous side of things, but I figured it wouldn't hurt to ask.

I'd like to be able to transpose a score and its parts via the command-line interface, and export the result to a separate file. So if I provided a score that was in like, Concert Bb, I could say:

musescore -i SongName.mscz -transpose-up D -o SongNameInConcertD.mscz

which would transpose the entire score up a third, or

musescore -i SongName.mscz -transpose-down D -o SongNameInConcertD.mscz

which would transpose the entire score down a minor 6th.


Comments

In reply to by Marr11317

If that repo is yours, then take another look at the git workflow.
You should never merge the upstream (MuseScore) master into your own master branch, but always rebase/fast-forward it.
If not, chances are any of your future PRs won't work because of a different history.

A command-line option was added to MuseScore for this purpose just last week. It was really only intended to be used by the server rather than actual users, as the output requires some extra processing, but with the help of a python script (attached below), anyone can make use of it.

On my system, I can use the following command to transpose a score named Canon_in_D.mscz to the key of E:

mscore Canon_in_D.mscz --score-transpose '{"mode": "by_key", "direction": "up", "targetKey": 4, "transposeKeySignatures": true}' | ./extract.py Canon_in_E.mscz Canon_in_E.pdf

This works for me because
- mscore has been aliased to the full path of the mscore executable.
- extract.py resides in the current directory, and has been given execute permissions.
- python is in /usr/bin.

The --score-transpose option to mscore takes one argument, which is a JSON string. Double quotes are required around all keys and string values. Do not use quotes around integer or boolean values. The entire JSON string is enclosed in single quotes in order for it to be interpreted as one string.

"mode" can be "by_key", "by_interval", or "diatonically". This may not be omitted, as there is no default value.

"direction" can be "up", "down", or "closest". This may not be omitted, as there is no default value.

If "mode" is "by_key", then you must specify a "targetKey". This is an integer from -7 (7 flats) to 7 (7 sharps).
-7 = C flat major / A flat minor
-6 = G flat major / E flat minor
-5 = D flat major / B flat minor
-4 = A flat major / F minor
-3 = E flat major / C minor
-2 = B flat major / G minor
-1 = F major / D minor
0 = C major / A minor
1 = G major / E minor
2 = D major / B minor
3 = A major / F sharp minor
4 = E major / C sharp minor
5 = B major / G sharp minor
6 = F sharp major
7 = C sharp major

If "mode" is "by_interval" or "diatonically", then you must specify a "transposeInterval". This is an integer from 0 to 25:
0 = Perfect Unison
1 = Augmented Unison
2 = Diminished Second
3 = Minor Second
4 = Major Second
5 = Augmented Second
6 = Diminished Third
7 = Minor Third
8 = Major Third
9 = Augmented Third
10 = Diminished Fourth
11 = Perfect Fourth
12 = Augmented Fourth
13 = Diminished Fifth
14 = Perfect Fifth
15 = Augmented Fifth
16 = Diminished Sixth
17 = Minor Sixth
18 = Major Sixth
19 = Augmented Sixth
20 = Diminished Seventh
21 = Minor Seventh
22 = Major Seventh
23 = Augmented Seventh
24 = Diminished Octave
25 = Perfect Octave

"transposeKeySignatures" may be true or false. If omitted, it defaults to false, which is probably not what you want if you are transposing the score to a new key.

There is also a "transposeChordNames" option, which may be true or false. If omitted, it defaults to false.

Finally, there is a "useDoubleSharpsFlats" option which may be true or false. If omitted, it defaults to false.

The extract.py script takes output from mscore --score-transpose and saves the transposed score to a file with the name that you specify as an argument. The score data is available in pdf and mscz formats. You can choose to save either the mscz or the pdf, or both.

Attachment Size
extract.py.txt 575 bytes

In reply to by mattmcclinch

If you use #!/usr/bin/env python in your python script, it would be independant of where python is living, as long as it is in PATH

I wonder why that addition to MuseScore hasn't been coded to allow for -o outputfile though, thus not needing external help.

This "by_key" reminded me to add this to my PR https://github.com/musescore/MuseScore/pull/5617 (to fix #299727: Change "Transpose by key" to "Transpose to key")

In reply to by Jojo-Schmitz

Thanks for that info and script Jojo-Schmitz. I would also appreciate getting that -o option to save as mscz instead of json. I wonder if it is planned.. ??

I get errors when I run that script. My Python installation is
Python 3.8.5 (default, Jul 31 2020, 00:00:00)
[GCC 10.2.1 20200723 (Red Hat 10.2.1-1)] on linux

The errors are:
File "./convertMscoreOutput", line 8
except Exception,info:
^
SyntaxError: invalid syntax
(I "fixed" this by removing the ",info"), then...

File "./convertMscoreOutput", line 19
print 'No', extension, 'available'
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('No', extension, 'available')?
(I fixed this by adding in brackets on all the print calls), then...

Traceback (most recent call last):
File "./convertMscoreOutput", line 16, in
f.write(data)
TypeError: write() argument must be str, not bytes
(I don't know how to fix this)

I would love to get the script working as it would help me immensly!

Thank you for you work.

Kind regards,

Conor.

In reply to by Jojo-Schmitz

Indeed, the script was written using Python 2 syntax. It should be possible to have both Python 2 and Python 3 installed at the same time, and you may even already have Python 2 installed already. If so, the only thing you need to change is the path to the python executable.

In reply to by mattmcclinch

Ah great, I'm up and running! Thank you so much, this script will save me a lot of time! On my Fedora system, if I change

"#!/usr/bin/python"
to
"#!/usr/bin/python2"

and use command in comment from mattmcclinch • Jan 23, 2020 - 15:08:

mscore Canon_in_D.mscz --score-transpose '{"mode": "by_key", "direction": "up", "targetKey": 4, "transposeKeySignatures": true}' | ./extract_v2.py Canon_in_E.mscz Canon_in_E.pdf

then it works for me. The change is added to attached file "extract_v2.py_.txt"

Thank you again,

Conor.

Attachment Size
extract_v2.py_.txt 569 bytes

In reply to by Muso Dojo

Would anyone know if it is possible to script a change of title too?
I see
score.addText("title", "==Test-Score==");
is used in createscore.qml, but I don't know how to access the score title without
var score = newScore("Test-Score", "piano", 5);
which is declared above it. I would like to access score.addText("title", "==Test-Score=="); from within a modified notenames.qml plugin script. If anyone can guide me on that, that would be great!
Thanks,
Conor.

In reply to by jeetee

Thanks!
I am finding it difficult to understand what I can do and how to do it from within plugins. Is there a way to interpret the documentation that would make it clearer? I've been trying to work out how to insert a measure before the current first one but I am struggling!
Cheers,
Conor.

Do you still have an unanswered question? Please log in first to post your question.