├── .github └── FUNDING.yml ├── .gitignore ├── images ├── +.png ├── b.png ├── d.png ├── n.png ├── s.png ├── u.png ├── v.png ├── x.png ├── bb.png ├── bbu.png ├── bbv.png ├── bu.png ├── bu1.png ├── bu2.png ├── bu3.png ├── bv.png ├── bv1.png ├── bv2.png ├── bv3.png ├── db.png ├── s+.png ├── su.png ├── su1.png ├── su2.png ├── su3.png ├── sv.png ├── sv1.png ├── sv2.png ├── sv3.png ├── u1.png ├── u2.png ├── u3.png ├── v1.png ├── v2.png ├── v3.png ├── xu.png ├── xu1.png ├── xu2.png ├── xu3.png ├── xv.png ├── xv1.png ├── xv2.png ├── xv3.png ├── bbu1.png ├── bbu2.png ├── bbu3.png ├── bbv1.png ├── bbv2.png ├── bbv3.png ├── new │ ├── ^4.png │ ├── v4.png │ ├── #^4.png │ ├── #v4.png │ ├── b^4.png │ ├── bb^4.png │ ├── bbv4.png │ ├── bv4.png │ ├── x^4.png │ ├── xv4.png │ └── 94 edo demo.png ├── key-sig-example.png └── microtonal-plugin-screenshot.png ├── .idea ├── vcs.xml ├── .gitignore ├── modules.xml └── musescore-31-tet-plugin.iml ├── CHANGELOG.md ├── LICENSE ├── README.md └── tune n-edo.qml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: euwbah 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.qmlc 2 | test.qml 3 | -------------------------------------------------------------------------------- /images/+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/+.png -------------------------------------------------------------------------------- /images/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/b.png -------------------------------------------------------------------------------- /images/d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/d.png -------------------------------------------------------------------------------- /images/n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/n.png -------------------------------------------------------------------------------- /images/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/s.png -------------------------------------------------------------------------------- /images/u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/u.png -------------------------------------------------------------------------------- /images/v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/v.png -------------------------------------------------------------------------------- /images/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/x.png -------------------------------------------------------------------------------- /images/bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bb.png -------------------------------------------------------------------------------- /images/bbu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbu.png -------------------------------------------------------------------------------- /images/bbv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbv.png -------------------------------------------------------------------------------- /images/bu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bu.png -------------------------------------------------------------------------------- /images/bu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bu1.png -------------------------------------------------------------------------------- /images/bu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bu2.png -------------------------------------------------------------------------------- /images/bu3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bu3.png -------------------------------------------------------------------------------- /images/bv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bv.png -------------------------------------------------------------------------------- /images/bv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bv1.png -------------------------------------------------------------------------------- /images/bv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bv2.png -------------------------------------------------------------------------------- /images/bv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bv3.png -------------------------------------------------------------------------------- /images/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/db.png -------------------------------------------------------------------------------- /images/s+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/s+.png -------------------------------------------------------------------------------- /images/su.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/su.png -------------------------------------------------------------------------------- /images/su1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/su1.png -------------------------------------------------------------------------------- /images/su2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/su2.png -------------------------------------------------------------------------------- /images/su3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/su3.png -------------------------------------------------------------------------------- /images/sv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/sv.png -------------------------------------------------------------------------------- /images/sv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/sv1.png -------------------------------------------------------------------------------- /images/sv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/sv2.png -------------------------------------------------------------------------------- /images/sv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/sv3.png -------------------------------------------------------------------------------- /images/u1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/u1.png -------------------------------------------------------------------------------- /images/u2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/u2.png -------------------------------------------------------------------------------- /images/u3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/u3.png -------------------------------------------------------------------------------- /images/v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/v1.png -------------------------------------------------------------------------------- /images/v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/v2.png -------------------------------------------------------------------------------- /images/v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/v3.png -------------------------------------------------------------------------------- /images/xu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xu.png -------------------------------------------------------------------------------- /images/xu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xu1.png -------------------------------------------------------------------------------- /images/xu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xu2.png -------------------------------------------------------------------------------- /images/xu3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xu3.png -------------------------------------------------------------------------------- /images/xv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xv.png -------------------------------------------------------------------------------- /images/xv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xv1.png -------------------------------------------------------------------------------- /images/xv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xv2.png -------------------------------------------------------------------------------- /images/xv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/xv3.png -------------------------------------------------------------------------------- /images/bbu1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbu1.png -------------------------------------------------------------------------------- /images/bbu2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbu2.png -------------------------------------------------------------------------------- /images/bbu3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbu3.png -------------------------------------------------------------------------------- /images/bbv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbv1.png -------------------------------------------------------------------------------- /images/bbv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbv2.png -------------------------------------------------------------------------------- /images/bbv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/bbv3.png -------------------------------------------------------------------------------- /images/new/^4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/^4.png -------------------------------------------------------------------------------- /images/new/v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/v4.png -------------------------------------------------------------------------------- /images/new/#^4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/#^4.png -------------------------------------------------------------------------------- /images/new/#v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/#v4.png -------------------------------------------------------------------------------- /images/new/b^4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/b^4.png -------------------------------------------------------------------------------- /images/new/bb^4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/bb^4.png -------------------------------------------------------------------------------- /images/new/bbv4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/bbv4.png -------------------------------------------------------------------------------- /images/new/bv4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/bv4.png -------------------------------------------------------------------------------- /images/new/x^4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/x^4.png -------------------------------------------------------------------------------- /images/new/xv4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/xv4.png -------------------------------------------------------------------------------- /images/key-sig-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/key-sig-example.png -------------------------------------------------------------------------------- /images/new/94 edo demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/new/94 edo demo.png -------------------------------------------------------------------------------- /images/microtonal-plugin-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euwbah/musescore-microtonal-edo-plugin/HEAD/images/microtonal-plugin-screenshot.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/musescore-31-tet-plugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | ### 2.3.3 4 | - Adopted val calculation to improve extensibility 5 | 6 | ### 2.3.2 7 | - Fixed perfect (sharp-0) EDOs not working properly, 35 EDO infinite loop 8 | - Fixed typo in getOverLimitEnharmonicEquivalent causing overlimit semitone nominals to be calculated 9 | using whole tone nominals/return NaN, which breaks semitone nominals of uncommon EDOs. 10 | - Refactored console logging to improve performance 11 | 12 | ### 2.3.1 13 | - Implemented extensible config object; added showallaccidentals feature to always show courtesy accidentals. 14 | 15 | ### 2.3.0 16 | - Added support for transposing instruments via transposition annotation. Only regular fifth-based transpositions 17 | are supported (regular accidentals only). 18 | - Clean up readme. 19 | 20 | ### 2.2.9 21 | - Fixed pitch down invoking pitch-up command when rests/text/non-note elements are selected 22 | - Fixed pitch up not correcting an exceeded enharmonic (bug fix #31) 23 | 24 | ### 2.2.8 25 | - Fixed critical bug: 26 | - localized name used for staff/system text causing the plugin to not work 27 | when MuseScore is not set to use English. 28 | 29 | ### 2.2.7 30 | - Fixed critical bugs: 31 | - two notes in same segment, voice, tick, and line, yields wrong accidentals when transposed. 32 | (getMostRecentAccidentalInBar did not handle 'before' processing correctly. 'before' was tick based 33 | but should've been based on voice and visual positioning). 34 | - Wayyyy more robust setAccidental function which ensures set accidentals persist in 35 | code even after the note is edited and traversed. 36 | This actually allows for a lot of the parms state nonsense to be removed with some refactoring. 37 | Perhaps in a future version the code base can be a lot cleaner. 38 | 39 | ### 2.2.6 40 | - Fixed critical bugs: 41 | - getMostRecentAcc gave the wrong accidental when there are notes on the same staff line 42 | in different voices, causes pitch up/down to get stuck on one note. 43 | - Tune N-EDO plugin: key signature/edo/frequency center annotation texts broken when multiple voices are present in the bar where the annotation texts are declared (Bug fix #25) 44 | 45 | ### 2.2.5 46 | - Fixed critical bugs: 47 | - Some grace notes break the plugin due to a typo in getMostRecentAccidentalInBar. 48 | Some grace notes were indexed as notes[i] instead of notes[j] due to careless copy-pasting typo. 49 | - Pitch up with arrows not working 50 | 51 | ### 2.2.4 52 | - Fixed critical bug: 53 | - if a note were to have an explicit natural accidental after pitching up/down, 54 | and the inherited accidental prior to the current note was a regular accidental, 55 | any following notes in the selection with the same pitch will be affected by the first regular accidental, 56 | and not the second one. 57 | - Fixed typo in NoteType.APPOGIATURE => NoteType.APPOGGIATURA 58 | 59 | ### 2.2.3 60 | - Fixed issue where an accidental in the next bar affects an accidental before when the accidental in the 61 | next bar is of a lower voice index than the current selected individual note(s). 62 | This issue only happens when noteheads are selected rather than entire group selections, 63 | and the noteheads are of voice 2, 3 or 4. 64 | 65 | ### 2.2.2 66 | - Fixed incorrect tuning of up/down arrows where regular sharps/flats are applicable. 67 | 68 | ### 2.2.1 69 | - Bug fix (#17) 70 | 71 | ### 2.2.0 72 | - Added support for custom tuning centers. 73 | 74 | ### 2.1.2 75 | - Added 'no dt' version, which prioritizes up/down arrows over semi/sesqui sharps and flats wherever possible. 76 | 77 | ### 2.1.1 78 | - Fixed formatted StaffText/SystemText causing tuning system parsing to fail 79 | - Fixed certain accidentals fail to reflect in tuning plugin 80 | - Caused by unexpected coercion of accidentalType to string. 81 | 82 | ### 2.1.0 83 | - Implement generic n-EDO plugin for flat-2 to sharp-8 EDOs. (Most EDOs from 5 to 72 are covered, except 59, 66, and 71) 84 | 85 | ### 2.0.3 86 | - Fixed local vs. global key signatures not working. 87 | 88 | ### 2.0.2 89 | - Fixed transposing breaking down on grace notes 90 | - `note.parent.parent.tick` vs. `note.parent.parent.parent.tick` for grace notes abstracted by `getTick()` 91 | - Fixed grace notes not regarding sibling grace notes and parent chord notes as possible candidates 92 | for followingOldLine and followingNewLine. 93 | - Fixed accidentals on prior grace notes on the current chord segment not accounted for. 94 | - Fixed cursor relocation on getAccidental causing havoc. getAccidental will now return cursor to original position. 95 | - Relocate cursor to individually selected notes when transposing 96 | 97 | ### 2.0.1 98 | - Fixed reading accidentals for transposition doesn't work when accidentals are in 99 | the last bar. 100 | 101 | ### 2.0.0 102 | - Added stepwise note transposition feature for edostep to replace up/down arrow keys 103 | function. 104 | - Refactored accidental state reading to be stateless. (for transposition plugins) 105 | - Fixed up/downs notation accidentals to follow best-fifths convention as per [NOTATION GUIDE FOR EDOS 5-72](http://tallkite.com/misc_files/notation%20guide%20for%20edos%205-72.pdf). 106 | - ~~Handle playback for notes exceeding offset bounds of +/-200 cents.~~ (Unnecessary, 107 | [pitch offset may exceed 200/300 cents even if not reflected in UI](https://www.reddit.com/r/microtonal/comments/gssrnk/made_this_31_22_edo_microtonal_plugin_for/fs7frcg?utm_source=share&utm_medium=web2x)) 108 | - Support for ties in transposition 109 | 110 | ### 1.3.7 111 | - Fixed custom key signatures before selection not being applied to selection. 112 | - Fixed accidentals in same bar before selection not being accounted for 113 | - Fixed partial selection not working 114 | - Improved handling of two notes with the same line at the same time. 115 | - Fixed custom key signatures in partial selections not working. 116 | - Fixed cursor rewind calls to use the Only Right Way That Works :tm: for whatever reason. 117 | 118 | ### 1.3.6 119 | - Fixed fermatas and other non-text annotations breaking the plugin 120 | 121 | ### 1.3.5 122 | - Added 22-edo superpyth version. 123 | - Fixed custom key signatures not affecting other voices (even system text) 124 | - Fixed accidentals on notes of higher voices not affecting lower voices 125 | 126 | ### 1.3.4 127 | - Fixed meantone double accidentals not accounting for accidental's default double 128 | sharp/flat effect (https://musescore.org/en/node/285449) 129 | 130 | ### 1.3.3 131 | - Fixed custom key signatures not working if multiple annotations exist on same segment 132 | (caused by JavaScript insanity) 133 | - Fixed explicit natural accidentals not affecting custom key signatures 134 | 135 | ### 1.3.2 136 | 137 | - Now supports MuseScore version 3! 138 | 139 | ### 1.3 140 | 141 | - Removed unecessary GUI dialog --- planning to make a 31-TET suite of micro-plugin features which 142 | users can take advantage of custom-assigned plugin key bindings to improve workflow. 143 | (E.g. Alt + W to transpose up 1 diesis, Alt + S to transpose down 1 diesis, Alt + E to rotate enharmonical equivalents) 144 | - Added meantone mode 145 | - Fixed microtonal accidentals from notes in same staff not affecting subsequent notes of other voices in same staff in measure. 146 | 147 | ### 1.2 148 | 149 | - Fixed non-naturalised explicit natural accidental in note affected by a custom key signature 150 | - Added support for declaring custom key signature changes in SystemText/StaffText 151 | - Added usage guide in this file 152 | - Preparing for meantone quartertone-accidental mode support 153 | 154 | ### 1.1 155 | 156 | - Fixed occassional bug where microtonal accidentals carry over the bar line when it shouldn't 157 | - Attempted to fix UI bug in Windows, haven't tested it yet though :/ 158 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microtonal plugin for Musescore 3.4+: Retune + Transpose in almost any EDO. 2 | 3 | 4 | 5 | ## ⚠️ This project is deprecated ⚠️ 6 | 7 | This project is no longer maintained. Please use [euwbah/musescore-xen-tuner](https://github.com/euwbah/musescore-xen-tuner) instead, which is a much more powerful and general solution for microtonality in MuseScore 3. Supports JI, EDOs, stretched tunings, non-octave tunings, NEJI, Bohlen-Pierce, negative staves, chromatic staves, custom/variable nominals, accidental ligatures (HEJI & Sagittal). MS 4 support is being worked on. 8 | 9 | ----- 10 | 11 | ![screenshot](images/microtonal-plugin-screenshot.png) 12 | 13 | ## Features 14 | 15 | - Retuning notes to match any [supported edo](#appendix-a-list-of-supported-edos-according-to-sharpness-classification) of choice 16 | - Special thanks to [Flora Canou](https://github.com/FloraCanou/musescore-n-tet-plugins) for providing the generalized method for evaluating cent offsets for any EDO. 17 | - Support for key signatures via [Key signature annotations](#key-signatures) 18 | - Transposing individual notes/selections by 1 EDO step while automatically assigning accidentals 19 | - Tuning, key signatures, and reference pitches can be changed mid score; 20 | - Each staff can be assigned its own tunings, key signatures, and reference pitches independently. 21 | - Based on [Kite Giedraitis' ups and downs notation](http://tallkite.com/misc_files/notation%20guide%20for%20edos%205-72.pdf) 22 | 23 | ## Support me 24 | 25 | Support this plugin + fund my xenharmonic music creation and research. 26 | Any amount would be greatly appreciated! 27 | 28 | [![GitHub Sponsors](https://img.shields.io/github/sponsors/euwbah?style=for-the-badge)](https://github.com/sponsors/euwbah) 29 | 30 | ## Quick start 31 | 32 | **Make sure you are using MuseScore 3.4 or newer. The plugin will not work in previous versions** 33 | 34 | ### 1. [Download the project](https://github.com/euwbah/musescore-n-tet-plugins/archive/master.zip) and unzip into [MuseScore's plugins directory](https://musescore.org/en/handbook/3/plugins#windows) 35 | 36 | ### 2. [Enable](https://musescore.org/en/handbook/3/plugins#enable-disable-plugins) the following plugins 37 | 38 | - `tune n-edo`: Tunes the selected notes, or entire score if nothing selected. Notes are not automatically tuned 39 | as they are entered, so it is important to run this regularly for accurate playback. 40 | - `pitch up` & `pitch down`: Transposes selected notes by 1 edostep, then updates their tuning. 41 | Equivalent to MuseScore's up/down arrow shortcuts. If you prefer arrow notation over semi/sesqui 42 | sharp/flat quartertone notation, use `pitch up no dt` & `pitch down no dt` instead. 43 | 44 | ### 3. Set up keyboard shortcuts for the plugins 45 | (optional, highly recommended for the best experience) 46 | 47 | - First, clear/change the default shortcuts that uses the up/down arrow keys. 48 | You can find these in _Edit -> Preferences -> Shortcuts_. Search for the following shortcut names, 49 | select them and click the _Clear_ button. 50 | - _Pitch up or move text or articulation up_ 51 | - _Pitch down or move text or articulation down_ 52 | - _Select string above_ 53 | - _Select string below_ 54 | - To define a shortcut for a plugin, go to: _Plugins -> Plugin Manager -> Select plugin name in the list -> Define Shortcut_. 55 | - Set `tune n-edo` to use `Alt-R`. 56 | - Set `pitch up`/`pitch up no dt` to use the up arrow. This shortcut should only be assigned on either one of the plugins. 57 | - Set `pitch down`/`pitch down no dt` to use the down arrow. This shortcut should only be assigned on either one of the plugins. 58 | 59 | ### 4. Select a tuning system 60 | 61 | Create a System Text (`Ctrl-Shift-T`) and type `___ edo`, fill in the blank with any 62 | of the [supported edo tunings](#appendix-a-list-of-supported-edos-according-to-sharpness-classification). This will 63 | affect all staves/parts from the bar where the text was placed onwards. 64 | 65 | If you wish to only change the tuning of 66 | one staff, but not the others, use Staff Text (`Ctrl-T`) instead. You should not place a tuning system change 67 | halfway through a bar. 68 | 69 | If a tuning system has not been specified for a part, it defaults to 12 edo. 70 | The text is case-insensitive. 71 | 72 | ### 5. Annotate key signatures 73 | 74 | For each key signature, create one System Text (`Ctrl-Shift-T`) at the start of the same 75 | bar as the key signature, then type `.x.x.x.x.x.x.x`, where each 'x' 76 | represents an [accidental](#accidental-code) applied on the notes C, D, E, F, G, A, and B respectively. 77 | If a note should have no accidental, you can leave it blank or put any other placeholder character. 78 | For example, the key signature for D major can look like: `.#...#...` representing C# and F#. 79 | There should always be 7 dots (`.`) in the key signature annotation. Refer to the 80 | [list of supported key signatures](#accidental-code). 81 | 82 | If there are staves which have a separate key signatures from the others, 83 | as in [local key signatures](https://musescore.org/en/handbook/3/key-signatures#add-key-sig-to-one-staff), 84 | or transposing instruments, you can assign a key signature annotation for just that 85 | staff using Staff Text (`Ctrl-T`) instead of System Text. 86 | 87 | > :warning: Due to current technical limitations of MuseScore, 88 | **all** key signatures, even standard non-custom ones, must be accompanied by key signature annotations. 89 | > 90 | > :warning: It is necessary to adjust the key signature annotations when toggling between concert and tranposing pitch 91 | display modes. 92 | 93 | If a key signature annotation has not been specified, the plugin assumes that there are no accidentals in the key 94 | signature. The text is case-insensitive. 95 | 96 | ### 6. Annotate transposing instruments 97 | 98 | If a part uses a transposing instrument, create a Staff Text (`Ctrl-T`) at 99 | the start of the first bar of the part, or at the start of the bar where an instrument change to 100 | a transposing instrument of a different transposition is performed. In this staff text, 101 | type `t: Bb` for Bb instruments, `t: Eb` for Eb instruments, etc. All fifth-based transpositions 102 | are supported - meaning you can use the accidentals `x`, `#`, `b`, `bb`. 103 | 104 | This step is required as MuseScore implements transpositions as offsets in 12-edo. 105 | Placing the transposition annotation will correct the offset into the current tuning system. 106 | Note that if [Concert Pitch](https://musescore.org/en/handbook/3/concert-pitch) display mode is active, 107 | the transposition annotation will not take effect and all parts will be treated as C instruments. 108 | 109 | If no transposition annotations were specified, the part is assumed to be a C instrument. 110 | The text is case-insensitive. 111 | 112 | ### 7. Select a reference pitch 113 | 114 | This step is optional and reference pitch is defaulted to `A4: 440 Hz`. 115 | 116 | To change reference pitch for all parts, create a System Text (`Ctrl-Shift-T`) and 117 | type `{note}: {f} Hz`: 118 | - `{note}` represents any note A through G followed by 119 | its octave without spaces. Middle C is written as `C4`. 120 | - `{f}` represents the frequency of the above reference note in Hertz 121 | - the _'Hz'_ is optional 122 | 123 | To change reference pitch for only one part, use Staff Text (`Ctrl-T`) instead. 124 | The text is case-insensitive. 125 | 126 | ### 8. Done! 127 | 128 | You can now use the up and down arrow keys to adjust a note according 129 | to the tuning system of choice! Here are some things to take note of: 130 | - You can make the text annotations invisible by selecting them and pressing `V`. 131 | - Make sure each System/Staff Text only contains one modifier; don't combine 132 | tuning selection and key signature annotation in one Text element. 133 | - Remember to run the `tune n-edo` plugin regularly to update the pitches of 134 | notes that are not yet tuned/transposed. 135 | - Recall that: 136 | - System Text (`Ctrl-Shift-T`) = annotation applies to all staves 137 | - Staff Text (`Ctrl-T`) = annotation applies to current staff only. 138 | 139 | ---------------------- 140 | 141 | ### Additional Settings 142 | 143 | In a separate Staff/System Text annotation, type `config: {showallaccidentals: true}` (verbatim) 144 | to turn on courtesy accidentals for all notes (helpful for atonal pieces or scores without barlines). 145 | 146 | ------------------------ 147 | 148 | ## Accidental Code 149 | 150 | ![Staff text custom key sig](images/key-sig-example.png) 151 | 152 | | Accidental | Textual representation | 153 | | ----: | :---- | 154 | | ![Double flat down 3](images/bbv3.png) | `bbv3` | 155 | | ![Double flat down 2](images/bbv2.png) | `bbv2` | 156 | | ![Double flat down](images/bbv1.png) | `bbv` or `bbv1` | 157 | | ![Double flat](images/bb.png) | `bb` | 158 | | ![Double flat up](images/bbu1.png) | `bb^` or `bb^1` | 159 | | ![Double flat up 2](images/bbu2.png) | `bb^2` | 160 | | ![Double flat up 3](images/bbu3.png) | `bb^3` | 161 | | ![Sesqui flat](images/db.png) | `db` or `bd` | 162 | | ![Flat down 3](images/bv3.png) | `bv3` | 163 | | ![Flat down 2](images/bv2.png) | `bv2` | 164 | | ![Flat down](images/bv1.png) | `bv` or `bv1` | 165 | | ![Flat](images/b.png) | `b` | 166 | | ![Flat up](images/bu1.png) | `b^` or `b^1` | 167 | | ![Flat up 2](images/bu2.png) | `b^2` | 168 | | ![Flat up 3](images/bu3.png) | `b^3` | 169 | | ![Down 3](images/v3.png) | `v3` | 170 | | ![Down 2](images/v2.png) | `v2` | 171 | | ![Down](images/v.png) | `v` or `v1` | 172 | | ![Quarter flat](images/d.png) | `d` | 173 | | ![Natural](images/n.png) | Leave blank / any other character | 174 | | ![Quarter sharp](images/+.png) | `+` | 175 | | ![Up](images/u1.png) | `^` or `^1` | 176 | | ![Up2](images/u2.png) | `^2` | 177 | | ![Up3](images/u3.png) | `^3` | 178 | | ![Sharp down3](images/sv3.png) | `#v3` | 179 | | ![Sharp down2](images/sv2.png) | `#v2` | 180 | | ![Sharp down](images/sv1.png) | `#v` or `#v1` | 181 | | ![Sharp](images/s.png) | `#` | 182 | | ![Sharp up](images/su1.png) | `#^` or `#^1` | 183 | | ![Sharp up 2](images/su2.png) | `#^2` | 184 | | ![Sharp up 3](images/su3.png) | `#^3` | 185 | | ![Sesqui sharp](images/s+.png) | `#+` or `+#` | 186 | | ![Double sharp down](images/xv3.png) | `xv3` | 187 | | ![Double sharp down2](images/xv2.png) | `xv2` | 188 | | ![Double sharp down3](images/xv1.png) | `xv` or `xv1` | 189 | | ![Double sharp](images/x.png) | `x` | 190 | | ![Double sharp up](images/xu1.png) | `x^` or `x^1` | 191 | | ![Double sharp up 2](images/xu2.png) | `x^2` | 192 | | ![Double sharp up 3](images/xu3.png) | `x^3` | 193 | 194 | ## Modification 195 | 196 | 原插件issue https://github.com/euwbah/musescore-microtonal-edo-plugin/issues/36 的权宜之计:使用10个Musescore内存在的变音号代替不存在的4箭头变音号,从而使得sharp-9、sharp-10律制可以使用。 197 | 198 | ![94 edo](images/new/94%20edo%20demo.png) 199 | 200 | #### 新的变音号 201 | 202 | | 变音号 | 名称 | 内部名称 | 选择原因 | 203 | | :---- | :---- | :---- | :---- | 204 | | ![v4](images/new/v4.png) | `v4` | `LOWER_ONE_SEPTIMAL_COMMA` | 看起来像还原号的左半边 | 205 | | ![u4](images/new/^4.png) | `^4` | `RAISE_ONE_SEPTIMAL_COMMA` | 和上面那个符号相对应 | 206 | | ![sv4](images/new/%23v4.png) | `#v4` | `RAISE_ONE_TRIDECIMAL_QUARTERTONE` | 升记号少一横,表示少升一点 | 207 | | ![su4](images/new/%23^4.png) | `#^4` | `SHARP_SLASH2` | 同上,升记号多一横,表示多升一点 | 208 | | ![bv4](images/new/bv4.png) | `bv4` | `THREE_TWELFTH_FLAT` | 降记号上面加点东西表示比普通的降记号高 | 209 | | ![bu4](images/new/b^4.png) | `b^4` | `FOUR_TWELFTH_FLAT` | 降记号下面加点东西表示比普通的降记号低 | 210 | | ![bbv4](images/new/bbv4.png) | `bbv4` | `NINE_TWELFTH_FLAT` | 同上,额外加一个普通的降记号 | 211 | | ![bbu4](images/new/bb^4.png) | `bb^4` | `TEN_TWELFTH_FLAT` | 同上,额外加一个普通的降记号 | 212 | | ![xu4](images/new/x^4.png) | `x^4` | `DOUBLE_SHARP_EQUAL_TEMPERED` | 重升号上面加点东西表示比普通的重升号高 | 213 | | ![xv4](images/new/xv4.png) | `xv4` | `SAGITTAL_SHARP25SD` | 实在找不到合适的记号就随便找了个不会混淆的 | 214 | 215 | ### English 216 | 217 | A simple and straight-forward solution to issue https://github.com/euwbah/musescore-microtonal-edo-plugin/issues/36 : Include 10 extra accidentals supported by Musescore representing 4-arrow accidentals so that the plugin can tune sharp-9 & sharp-10 EDOs. 218 | 219 | #### New accidental 220 | 221 | | Accidental | Text | Internal name | Reason | 222 | | :---- | :---- | :---- | :---- | 223 | | ![v4](images/new/v4.png) | `v4` | `LOWER_ONE_SEPTIMAL_COMMA` | It looks like the left half of the natural | 224 | | ![u4](images/new/^4.png) | `^4` | `RAISE_ONE_SEPTIMAL_COMMA` | Pairing with the symbol above | 225 | | ![sv4](images/new/%23v4.png) | `#v4` | `RAISE_ONE_TRIDECIMAL_QUARTERTONE` | The sharp, but missing a bar, indicating less sharped | 226 | | ![su4](images/new/%23^4.png) | `#^4` | `SHARP_SLASH2` | The sharp, but having an extra bar, indicating more sharped | 227 | | ![bv4](images/new/bv4.png) | `bv4` | `THREE_TWELFTH_FLAT` | The flat, but with bars above, indicating sharper than flat | 228 | | ![bu4](images/new/b^4.png) | `b^4` | `FOUR_TWELFTH_FLAT` | The flat, but with signs below, indicating flatter than flat | 229 | | ![bbv4](images/new/bbv4.png) | `bbv4` | `NINE_TWELFTH_FLAT` | As above, an extra flat is added | 230 | | ![bbu4](images/new/bb^4.png) | `bb^4` | `TEN_TWELFTH_FLAT` | As above, an extra flat is added | 231 | | ![xu4](images/new/x^4.png) | `x^4` | `DOUBLE_SHARP_EQUAL_TEMPERED` | The double sharp, but with signs above, indicating sharper than double sharp | 232 | | ![xv4](images/new/xv4.png) | `xv4` | `SAGITTAL_SHARP25SD` | I cannot find an appropriate accidental, so I choose an arbitary one | 233 | 234 | ----------------- 235 | 236 | ## Notation system 237 | 238 | The plugin follows notation standards as per [Kite Giedraitis' ups and downs notation](http://tallkite.com/misc_files/notation%20guide%20for%20edos%205-72.pdf), 239 | which is a generalized system for notating any EDO. 240 | 241 | Here is a brief summary of the contents of the document: 242 | 243 | ### Tuning of nominals C D E F G A B 244 | 245 | In this system, the nominals F C G D A E B are tuned according to a chain of **best fifths**, 246 | which is the best representation of the perfect 3:2 just fifth that the EDO has to offer.\ 247 | The exact pitches of the notes are calculated based on the frequency of the reference note, which is defined by the 248 | reference frequency selector, or A4: 440 Hz by default. 249 | 250 |
251 | How to calculate an EDO's best fifth? 252 | 253 | The number of steps a fifth is in x-edo = `round(x * log2(3/2))` 254 | 255 | `3/2` represents the frequency ratio of a fifth in just intonation.\ 256 | `log2(3/2)` represents how many octaves are there in a fifth (approx 0.584962)\ 257 | `x * log2(3/2)` represents how many steps of x-edo are there in a fifth\ 258 | `round()` rounds it up/down to the nearest whole edostep. 259 | 260 | E.g's: 261 | - The best fifth in 12 edo is 7 steps. Thus, the distance between F-C, C-G, G-D, etc.. is 7 steps of 12 edo. 262 | - The best fifth in 22 edo is 13 steps. Thus, the distance between C-G, etc.. is 13 steps of 22 edo. 263 | 264 |
265 | 266 | 267 | ### Tuning of regular pythagorean accidentals 268 | 269 | ![bb](images/bb.png) ![b](images/b.png) ![s](images/s.png) ![x](images/x.png) 270 | 271 | The standard accidentals Double Flat (`bb`), Flat (`b`), Sharp (`#`), Double Sharp (`x`) are based on 272 | the circle of fifths. 273 | 274 | To give an example in 12-edo, going 7 fifths up from C4 yields C4-G4-D5-A5-E6-B6-F#7-C#8.\ 275 | A best fifth in 12-edo is 7 steps of 12 edo.\ 276 | Going up 7 fifths in 12-edo yields a total of 7*7 = 49 steps (which brings C4 to C#8)\ 277 | Going down 4 octaves to bring C#8 down to C#4 reduces the steps by 4 * 12 = 48 steps.\ 278 | Thus, a sharp symbol in 12-edo is defined as going up 49 steps, then down 48 steps, yielding a +1 step difference. 279 | 280 | The number of edosteps a sharp symbol raises the pitch by is known as an EDO's **sharpness** value, 281 | also known as the size of the **apotome**.\ 282 | Thus, the sharpness of 12-edo is 1, which classifies it as a **sharp-1** EDO.\ 283 | Consequently, a double sharp raises the pitch by 2 times of the sharpness value, thus 2 steps.\ 284 | A flat lowers the pitch by the sharpness value, thus lowering it by 1 step.\ 285 | A double flat lowers the pitch by 2 times of the sharpness value, thus lowering it by 2 steps. 286 | 287 | To give another example in 23-edo: 288 | A best fifth in 23-edo is 13 edosteps.\ 289 | Going up 7 fifths (From C4 to C#8) = going up 7 * 13 = 91 steps.\ 290 | Going down 4 octaves (From C#8 to C#4) = going down 4 * 23 = 92 steps.\ 291 | Thus, a sharp symbol in 23-edo is defined as going up 91 steps and down 92 steps, yielding a -1 step difference.\ 292 | A sharp symbol in 23-edo, surprisingly, __lowers__ the pitch by 1 step, instead of raising it.\ 293 | Consequently, the flat symbol raises the pitch by 1 step.\ 294 | The apotome size of 23-edo is -1, which classifies it as a **flat-1** EDO. 295 | 296 | Note: in EDOs such as 7, 14 and 21, the sharp and flats do not raise nor lower the pitch, and thus 297 | they are known as **perfect** EDOs, i.e. **Sharp-0**. 298 | 299 | [Here is the full list of supported EDOs and their respective sharpness values.](#appendix-a-list-of-supported-edos-according-to-sharpness-classification) 300 | 301 | The plugin only supports up to 2 flats and sharps. Triple flats and sharps and not supported as 302 | MuseScore does not provide these accidentals. 303 | 304 | ### Tuning of up/down arrows 305 | 306 | ![sv3](images/sv3.png) ![u2](images/u2.png) ![bu1](images/bu1.png) 307 | 308 | Arrows on the natural, sharp/flat, double sharp/flat accidentals offsets the pitch of the note by 309 | the same number of steps of the EDO as there are arrows on the accidental. 310 | 311 | An upwards arrow always raises the pitch by 1 step, regardless of whether the sharp symbol raises or lowers the pitch of the 312 | note. Vice versa, a downwards arrow always lowers the pitch by 1 step. 313 | 314 | Thus the interval between C and C^ is +1 step. And so is the interval between C# and C#^, Cbv and Cb, etc.. 315 | 316 | A maximum of 3 arrows are allowed on each accidental, as MuseScore currently does not provide accidentals 317 | with more than 3 arrows. Due to these limitations, and with the help of quartertone accidentals, the plugin 318 | can only handle EDOs with a sharpness rating of up to 8. 319 | 320 | [Here is the full list of supported EDOs and their respective sharpness values.](#appendix-a-list-of-supported-edos-according-to-sharpness-classification) 321 | 322 | The up/down arrow accidentals this plugin uses are Helmholtz-Ellis Just Intonation accidentals.\ 323 | Gould arrow quartertone symbols look very similar to the single up/down arrow Helmholtz-Ellis accidentals, 324 | and may be used interchangeably, although the plugin defaults to Helmholtz-Ellis when transposing. 325 | To differentiate the two, Gould arrow symbols appear slightly larger than the Helmholtz-Ellis ones. 326 | 327 | ### Tuning of quartertone (semisharp/semiflat) accidentals 328 | 329 | ![db](images/db.png) ![d](images/d.png) ![+](images/+.png) ![s+](images/s+.png) 330 | 331 | Stein-Zimmermann quartertone accidentals represent an offset of half or one-and-a-half times of the standard sharpness 332 | of the accidental. They only work when the EDO has an even-number sharpness rating which can be divided 333 | by 2 evenly. 334 | 335 | For example, in 31-edo, where the sharpness rating is sharp-2: 336 | - ![db](images/db.png) lowers the pitch by 1.5 x 2 = -3 steps 337 | - ![d](images/d.png) lowers the pitch by 0.5 x 2 = -1 step 338 | - ![+](images/+.png) raises the pitch by 0.5 x 2 = +1 step 339 | - ![s+](images/s+.png) raises the pitch by 1.5 x 2 = +3 steps 340 | 341 | 342 | -------- 343 | 344 | 345 | ## Known issues: 346 | 347 | - Cross staff notation doesn't work properly, the accidentals in the staff that the notes are transferred to 348 | do not affect the notes that originally belonged in that staff that the notes were transferred to. 349 | Please refrain from using cross-staff notation, or submit a PR for this fix. 350 | 351 | - Accidentals of grace notes that comes after rather than before are handled as if they were before, and also 352 | not in the right order. This causes huge problems when transposing. 353 | Please refrain from using grace notes that attach after main notes, or submit a PR for this fix. 354 | 355 | - The plugin tries its best to handle chords with pairs of mirrored notes that 356 | share the same line (e.g. an F and F# on the same staff line) but due to plugin API 357 | limitations and the way MuseScore natively handles them, its behavior is somewhat janky. 358 | When dealing with them, ALWAYS use explicit accidentals on the mirrored notes to 359 | ensure the Accidentals are all registered correctly. This way it is clear to read 360 | and also for the plugin to read and understand which accidentals belong to which 361 | notes. 362 | - The exact order the plugin reads and performs operations on its notes of each chord segment are as follows: 363 | 1. grace notes (in similar fashion to step 2) 364 | 2. For notes in the same chord, left to right, then bottom to top, as they appear in the score. 365 | 366 | ------------- 367 | 368 | ## Appendix A: List of supported EDOs according to sharpness classification. 369 | 370 | | Sharpness (steps of an apotome) | EDOs | 371 | | -------: | :------- | 372 | | flat-2 | 4, 11 | 373 | | flat-1 | 2, 9, 16, 23 | 374 | | perfect | 7, 14, 21, 28, 35 | 375 | | sharp-1 | 5, 12, 19, 26, 33, 40, 47 | 376 | | sharp-2 | 3, 10, 17, 24, 31, 38, 45, 52 | 377 | | sharp-3 | 1, 8, 15, 22, 29, 36, 43, 50, 57, 64 | 378 | | sharp-4 | 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 76 | 379 | | sharp-5 | 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88 | 380 | | sharp-6 | 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100 | 381 | | sharp-7 | 42, 49, 56, 63, 70, 77, 84, 91, 98, 105 | 382 | | sharp-8 | 54, 61, 68, 75, 82, 89, 96, 103, 110, 117 | 383 | 384 | --------------- 385 | 386 | ## Note to self / developers: 387 | 388 | ### IMPORTANT basic info on undocumented Plugin API mechanics! 389 | 390 | CURSOR REWIND MECHANICS ARE WEIRD! 391 | - If rewinding to start of selection `cursor.rewind(1)`, set `cursor.staffIdx` and `cursor.voice` after 392 | `rewind(1)`. 393 | - If rewinding to start of score, IT IS STILL NECESSARY TO CALL `cursor.rewind(1)`, then set `staffIdx` and `voice`, 394 | THEN call `cursor.rewind(0)` AFTERWARDS. \ 395 | Apparently, based on the (add courtesy accidentals)[https://github.com/heuchi/courtesyAccidentals/blob/master/addCourtesyAccidentals.qml#L160] plugin, `cursor.track` has to be set to 0 in order for `cursor.rewind(0)` to work. 396 | 397 | 398 | It is an invalid operation to set cursor voice/staffIdx without rewinding. 399 | 400 | IMPORTANT! DO NOT USE `===` or `!==` to compare equivalence of accidentalType to Accidental enum values. 401 | 402 | When assigning `Note.accidentalType` to variables or passing it into a function as a parameter, 403 | ensure that the value read is in integer format to invoke the getter of the 404 | integer enumeration instead of the stringified value of the accidental type. 405 | 406 | ```js 407 | noteData.explicitAccidental = note.accidentalType; 408 | console.log(explicitAccidental); // NATURAL_ARROW_UP 409 | noteData.explicitAccidental = 0 + note.accidentalType; 410 | console.log(explicitAccidental); // 11 (enumerated value equivalent of NATURAL_ARROW_UP) 411 | 412 | console.log(Accidental.NATURAL_ARROW_UP); // 11 413 | 414 | console.log(note.accidentalType); // NATURAL_ARROW_UP 415 | console.log(0 + note.accidentalType) // 11 416 | ``` 417 | 418 | There is a very specific method to update an existing note's accidental 419 | such that there are minimal race/state errors. Refer to the ] 420 | [`setAccidental()`](https://github.com/euwbah/musescore-n-tet-plugins/blob/56aa8cc3697ac04d31eff82ba59edc177a55d88f/pitch%20down.qml#L3457) function. 421 | 422 | `Note.accidental` and `Note.accidentalType` properties of transposed notes that contain new accidental values of standardized 423 | accidentals are not present in a new cursor instance. The plugin uses tpc as a workaround, but it makes it impossible to 424 | determine if a prior note's accidental was implicit or explicit.\ 425 | [See this forum post here.](https://musescore.org/en/node/305977) 426 | 427 | ##### Important properties: 428 | 429 | **IMPORTANT `Note.accidental` vs. `Note.accidentalType`**: 430 | : `accidental` represents the accidental Element object itself, 431 | : whereas, accidentalType is a value of the Accidental enumeration!! 432 | 433 | `tpc` 434 | : Tonal pitch class. Circle of fifths starting from Fbb with value of -1. 435 | : Cbb = 0, Gbb = 1, Dbb = 2, etc... 436 | 437 | `segment.annotations[idx].textStyleType` 438 | : 22 if Staff Text, 439 | : 21 if System Text 440 | 441 | `segment.annotations[idx].text` 442 | : Contains given text 443 | 444 | `MuseScore.curScore.selection.elements` 445 | : An array of elements containing individual elements the user has selected 446 | : with ctrl + click. Especially useful for applying an action to certain notes in particular. 447 | 448 | 449 | #### Musescore Enums 450 | 451 | ##### Accidentals (used in project) 452 | 453 | ``` 454 | Accidental.NONE (no explicit accidental) 455 | Accidental.DOUBLE_SHARP_ONE_ARROW_UP x^ 456 | Accidental.DOUBLE_SHARP_TWO_ARROWS_UP x^2 457 | Accidental.DOUBLE_SHARP_THREE_ARROWS_UP x^3 458 | Accidental.SHARP2 x 459 | Accidental.DOUBLE_SHARP_ONE_ARROW_DOWN xv 460 | Accidental.DOUBLE_SHARP_TWO_ARROWS_DOWN xv2 461 | Accidental.DOUBLE_SHARP_THREE_ARROWS_DOWN xv3 462 | Accidental.SHARP_SLASH4 #+ 463 | Accidental.SHARP_ONE_ARROW_UP #^ 464 | Accidental.SHARP_TWO_ARROWS_UP #^2 465 | Accidental.SHARP_THREE_ARROWS_UP #^3 466 | Accidental.SHARP # 467 | Accidental.SHARP_ONE_ARROW_DOWN #v 468 | Accidental.SHARP_TWO_ARROWS_DOWN #v2 469 | Accidental.SHARP_THREE_ARROWS_DOWN #v3 470 | Accidental.SHARP_SLASH + 471 | Accidental.NATURAL_ONE_ARROW_UP ^ 472 | Accidental.NATURAL_TWO_ARROWS_UP ^2 473 | Accidental.NATURAL_THREE_ARROWS_UP ^3 474 | Accidental.NATURAL natural 475 | Accidental.NATURAL_ONE_ARROW_DOWN v 476 | Accidental.NATURAL_TWO_ARROWS_DOWN v2 477 | Accidental.NATURAL_THREE_ARROWS_DOWN v3 478 | Accidental.MIRRORED_FLAT d 479 | Accidental.FLAT_ONE_ARROW_UP b^ 480 | Accidental.FLAT_TWO_ARROWS_UP b^2 481 | Accidental.FLAT_THREE_ARROWS_UP b^3 482 | Accidental.FLAT b 483 | Accidental.FLAT_ONE_ARROW_DOWN bv 484 | Accidental.FLAT_TWO_ARROWS_DOWN bv2 485 | Accidental.FLAT_THREE_ARROWS_DOWN bv3 486 | Accidental.MIRRORED_FLAT2 db 487 | Accidental.DOUBLE_FLAT_ONE_ARROW_UP bb^ 488 | Accidental.DOUBLE_FLAT_TWO_ARROWS_UP bb^2 489 | Accidental.DOUBLE_FLAT_THREE_ARROWS_UP bb^3 490 | Accidental.FLAT2 bb 491 | Accidental.DOUBLE_FLAT_ONE_ARROW_DOWN bbv 492 | Accidental.DOUBLE_FLAT_TWO_ARROWS_DOWN bbv2 493 | Accidental.DOUBLE_FLAT_THREE_ARROWS_DOWN bbv3 494 | ``` 495 | 496 | #### Custom object types in up/down step transposition plugins 497 | 498 | ##### Key signature object: 499 | 500 | ``` 501 | { 502 | c: {steps: , type: Accidental enum value} 503 | d: ... 504 | e: ... 505 | etc... 506 | } 507 | ``` 508 | 509 | ##### Accidental object: 510 | 511 | ``` 512 | { 513 | offset: number of diesis offset, 514 | type: accidental type as Accidental enum value 515 | } 516 | ``` 517 | 518 | ##### Enharmonics object: 519 | 520 | ``` 521 | { 522 | above: {baseNote: 'a' through 'g', offset: diesis offset} 523 | below: {baseNote: 'a' through 'g', offset: diesis offset} 524 | } 525 | ``` 526 | 527 | ##### Note pitch data: 528 | 529 | ``` 530 | { 531 | baseNote: a string from 'a' to 'g', 532 | line: the note.line property referring to height of the note on the staff 533 | tpc: the tonal pitch class of the note (as per note.tpc) 534 | tick: the tick position of the note 535 | explicitAccidental: Accidental enum of the explicit accidental attatched to this note (if any) 536 | implicitAccidental: Accidental enum of the implicit accidental of this note (non null) 537 | (if explicitAccidental exists, implicitAccidental = explicitAccidental) 538 | diesisOffset: the number of edo steps offset from the base note this note is 539 | } 540 | ``` 541 | 542 | ## [Changelog](./CHANGELOG.md) 543 | 544 | ### TODO: 545 | 546 | - Handle cross-staff notation (ctrl + shift + up/down in connected staves, e.g. grand staff) where note appears to be in another staff 547 | other than the cursor's staffIdx. Currently, accidentals in the cross-staff do not work on the notes that came from another staff. 548 | See Add Courtesy Accidentals plugin for how to do this 549 | - Implement toggling between enharmonic equivalences 550 | - Make tune n-edo plugin use stateless accidental detection also. 551 | -------------------------------------------------------------------------------- /tune n-edo.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.1 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Controls.Styles 1.3 4 | import MuseScore 3.0 5 | 6 | MuseScore { 7 | version: "2.3.3" 8 | description: "Retune selection to any EDO temperament, or whole score if nothing selected." 9 | menuPath: "Plugins.n-EDO.Tune" 10 | 11 | // WARNING! This doesn't validate the accidental code! 12 | property variant customKeySigRegex: /\.(.*)\.(.*)\.(.*)\.(.*)\.(.*)\.(.*)\.(.*)/g 13 | 14 | // these lookups are for transposition annotations 15 | property variant fifthsFromC: { 16 | 'f': -1, 17 | 'c': 0, 18 | 'g': 1, 19 | 'd': 2, 20 | 'a': 3, 21 | 'e': 4, 22 | 'b': 5 23 | } 24 | 25 | property variant standardAccFifths: { 26 | 'bb': -14, 27 | 'b': -7, 28 | '': 0, 29 | '#': 7, 30 | 'x': 14 31 | } 32 | 33 | // Enumeration of custom names to map MuseScore symbols, text, and accidentals 34 | // to a consistent accidental enumeration called AccType instead of Accidental. 35 | property variant accType: (function() { 36 | var symbols = 37 | [ 38 | 'NONE', 39 | 'NATURAL', 40 | 'SHARP_SLASH4', 41 | 'SHARP_SLASH', 42 | 'MIRRORED_FLAT', 43 | 'MIRRORED_FLAT2', 44 | 'DOUBLE_SHARP_THREE_ARROWS_UP', 45 | 'DOUBLE_SHARP_TWO_ARROWS_UP', 46 | 'SHARP2_ARROW_UP', 47 | 'DOUBLE_SHARP_ONE_ARROW_UP', 48 | 'SHARP2', 49 | 'SHARP2_ARROW_DOWN', 50 | 'DOUBLE_SHARP_ONE_ARROW_DOWN', 51 | 'DOUBLE_SHARP_TWO_ARROWS_DOWN', 52 | 'DOUBLE_SHARP_THREE_ARROWS_DOWN', 53 | 'SHARP_THREE_ARROWS_UP', 54 | 'SHARP_TWO_ARROWS_UP', 55 | 'SHARP_ARROW_UP', 56 | 'SHARP_ONE_ARROW_UP', 57 | 'SHARP', 58 | 'SHARP_ARROW_DOWN', 59 | 'SHARP_ONE_ARROW_DOWN', 60 | 'SHARP_TWO_ARROWS_DOWN', 61 | 'SHARP_THREE_ARROWS_DOWN', 62 | 'NATURAL_THREE_ARROWS_UP', 63 | 'NATURAL_TWO_ARROWS_UP', 64 | 'NATURAL_ARROW_UP', 65 | 'NATURAL_ONE_ARROW_UP', 66 | 'NATURAL_ARROW_DOWN', 67 | 'NATURAL_ONE_ARROW_DOWN', 68 | 'NATURAL_TWO_ARROWS_DOWN', 69 | 'NATURAL_THREE_ARROWS_DOWN', 70 | 'FLAT_THREE_ARROWS_UP', 71 | 'FLAT_TWO_ARROWS_UP', 72 | 'FLAT_ARROW_UP', 73 | 'FLAT_ONE_ARROW_UP', 74 | 'FLAT', 75 | 'FLAT_ARROW_DOWN', 76 | 'FLAT_ONE_ARROW_DOWN', 77 | 'FLAT_TWO_ARROWS_DOWN', 78 | 'FLAT_THREE_ARROWS_DOWN', 79 | 'DOUBLE_FLAT_THREE_ARROWS_UP', 80 | 'DOUBLE_FLAT_TWO_ARROWS_UP', 81 | 'FLAT2_ARROW_UP', 82 | 'DOUBLE_FLAT_ONE_ARROW_UP', 83 | 'FLAT2', 84 | 'FLAT2_ARROW_DOWN', 85 | 'DOUBLE_FLAT_ONE_ARROW_DOWN', 86 | 'DOUBLE_FLAT_TWO_ARROWS_DOWN', 87 | 'DOUBLE_FLAT_THREE_ARROWS_DOWN', 88 | 89 | // Addon 90 | 'LOWER_ONE_SEPTIMAL_COMMA', // v4 91 | 'RAISE_ONE_SEPTIMAL_COMMA', // ^4 92 | 'RAISE_ONE_TRIDECIMAL_QUARTERTONE', // #v4 93 | 'SHARP_SLASH2', // #^4 94 | 'THREE_TWELFTH_FLAT', // bv4 95 | 'FOUR_TWELFTH_FLAT', // b^4 96 | 'SAGITTAL_SHARP25SD', // xv4 97 | 'DOUBLE_SHARP_EQUAL_TEMPERED', // x^4 98 | 'NINE_TWELFTH_FLAT', // bbv4 99 | 'TEN_TWELFTH_FLAT' // bb^4 100 | ]; 101 | var enumeration = {}; 102 | for (var i = 0; i < symbols.length; i++) { 103 | enumeration[symbols[i]] = i; 104 | } 105 | Object.freeze(enumeration); 106 | return enumeration; 107 | })() 108 | 109 | // An object class for defining all possible accidentals, including 110 | // multi-accidentals, etc... 111 | property var acc: (function() { 112 | var clazz = function() { 113 | this.type = AccType.NONE; 114 | }; 115 | 116 | clazz.prototype.calculatePitchOffset = function(tuningSystem) { 117 | 118 | }; 119 | 120 | clazz.prototype.readFromNote = function(note) { 121 | 122 | }; 123 | })() 124 | 125 | // MuseScore's annotations contain formatting code in angle brackets if the 126 | // annotation text formatting is not default. This function removes 127 | // all text within angle brackets including the brackets themselves 128 | function removeFormattingCode(str) { 129 | if (typeof(str) == 'string') 130 | return str.replace(/<[^>]*>/g, ''); 131 | else 132 | return null; 133 | } 134 | 135 | // Calculates the number of cents to detune the default musescore note by. 136 | // noteName: the note nominal alphabet from 'f' thru 'b' 137 | // stepOffset: offset the nominal by this many steps of the EDO 138 | // regAcc: number of regular accidentals 139 | // edo: how many notes per octave in the tuning system. 140 | // center: the central note and its frequency in Hz (by default A4, 440) 141 | // 142 | // Special credits to @FloraCanou (https://github.com/FloraCanou) for conceiving this method 143 | // method edited by @euwbah to set A as the normalised frequency instead of D 144 | 145 | /** 146 | noteName: nominal of note to tune 147 | stepOffset: number of edosteps away from nominal 148 | regAcc: number of sharps in the accidental of this note is a regular accidental 149 | edo: edo to tune to 150 | center: Reference pitch e.g. {note: 'a4', freq: 440} 151 | transFifths: number of fifths this part is transposed by if transposing instrument and 152 | concert pitch mode is off. E.g. Bb clarinet should be -2. 153 | Only regular fifth-based transpositions can be used. 154 | Rationale for this is that musescore's transposing instruments 155 | are transposed in 12 edo, so an additional offset must be applied 156 | to convert it to a fifth-based transposition in n-edo. 157 | */ 158 | function getCentOffset(noteName, stepOffset, regAcc, edo, center, transFifths) { 159 | var stepSize = 1200.0 / edo; 160 | var val = [2, 3].map (function (q) {return Math.round(edo * Math.log(q) / Math.LN2);}); 161 | var fifthStep = -val[0] + val[1]; 162 | var sharpValue = -11*val[0] + 7*val[1]; 163 | var twelveFifthVsEdoFifthCents = 700 - (fifthStep * stepSize); 164 | var transpositionCorrection = -transFifths * twelveFifthVsEdoFifthCents; 165 | 166 | // Offset caused by custom central frequency 167 | var centOffset = 1200*Math.log (center.freq / 440) / Math.LN2; 168 | // Offset caused by custom central note 169 | var centerValue; 170 | switch (center.note.substring(0, 1)) { 171 | case 'f': 172 | centOffset += 400; 173 | centerValue = 3; 174 | break; 175 | case 'c': 176 | centOffset += 900; 177 | centerValue = 2; 178 | break; 179 | case 'g': 180 | centOffset += 200; 181 | centerValue = 1; 182 | break; 183 | case 'd': 184 | centOffset += 700; 185 | centerValue = 0; 186 | break; 187 | case 'a': 188 | centOffset += 0; 189 | centerValue = -1; 190 | break; 191 | case 'e': 192 | centOffset += 500; 193 | centerValue = -2; 194 | break; 195 | case 'b': 196 | centOffset += -200; 197 | centerValue = -3; 198 | break; 199 | } 200 | centOffset += -1200*(parseInt(center.note.substring(1, 2)) - 4); 201 | 202 | var nominalOffset = 0; 203 | var nominalOffset = 0; 204 | switch (noteName) { 205 | case 'f': 206 | nominalOffset = (centerValue - 3)*(stepSize*fifthStep - 700); 207 | break; 208 | case 'c': 209 | nominalOffset = (centerValue - 2)*(stepSize*fifthStep - 700); 210 | break; 211 | case 'g': 212 | nominalOffset = (centerValue - 1)*(stepSize*fifthStep - 700); 213 | break; 214 | case 'd': 215 | nominalOffset = centerValue*(stepSize*fifthStep - 700); 216 | break; 217 | case 'a': 218 | nominalOffset = (centerValue + 1)*(stepSize*fifthStep - 700); 219 | break; 220 | case 'e': 221 | nominalOffset = (centerValue + 2)*(stepSize*fifthStep - 700); 222 | break; 223 | case 'b': 224 | nominalOffset = (centerValue + 3)*(stepSize*fifthStep - 700); 225 | break; 226 | } 227 | 228 | return stepSize*stepOffset - 100*regAcc + nominalOffset + centOffset + transpositionCorrection; 229 | } 230 | 231 | function convertAccidentalToStepsOrNull(acc, edo) { 232 | var val = [2, 3].map (function (q) {return Math.round(edo * Math.log(q) / Math.LN2);}); 233 | var fifthStep = -val[0] + val[1]; 234 | var sharpValue = -11*val[0] + 7*val[1]; 235 | switch(acc.trim()) { 236 | case 'db': 237 | case 'bd': 238 | return -3*sharpValue/2; 239 | case 'd': 240 | return -sharpValue/2; 241 | case '+': 242 | return sharpValue/2; 243 | case '#+': 244 | case '+#': 245 | return 3*sharpValue/2; 246 | case 'bbv3': 247 | return -2*sharpValue - 3; 248 | case 'bbv2': 249 | return -2*sharpValue - 2; 250 | case 'bbv1': 251 | case 'bbv': 252 | return -2*sharpValue - 1; 253 | case 'bb': 254 | return -2*sharpValue; 255 | case 'bb^': 256 | case 'bb^1': 257 | return -2*sharpValue + 1; 258 | case 'bb^2': 259 | return -2*sharpValue + 2; 260 | case 'bb^3': 261 | return -2*sharpValue + 3; 262 | case 'bv3': 263 | return -sharpValue - 3; 264 | case 'bv2': 265 | return -sharpValue - 2; 266 | case 'bv1': 267 | case 'bv': 268 | return -sharpValue - 1; 269 | case 'b': 270 | return -sharpValue; 271 | case 'b^': 272 | case 'b^1': 273 | return -sharpValue + 1; 274 | case 'b^2': 275 | return -sharpValue + 2; 276 | case 'b^3': 277 | return -sharpValue + 3; 278 | case 'v3': 279 | return -3; 280 | case 'v2': 281 | return -2; 282 | case 'v1': 283 | case 'v': 284 | return -1; 285 | case '': 286 | return 0; 287 | case '^': 288 | case '^1': 289 | return 1; 290 | case '^2': 291 | return 2; 292 | case '^3': 293 | return 3; 294 | case '#v3': 295 | return sharpValue - 3; 296 | case '#v2': 297 | return sharpValue - 2; 298 | case '#v1': 299 | case '#v': 300 | return sharpValue - 1; 301 | case '#': 302 | return sharpValue; 303 | case '#^': 304 | case '#^1': 305 | return sharpValue + 1; 306 | case '#^2': 307 | return sharpValue + 2; 308 | case '#^3': 309 | return sharpValue + 3; 310 | case 'xv3': 311 | return 2*sharpValue - 3; 312 | case 'xv2': 313 | return 2*sharpValue - 2; 314 | case 'xv1': 315 | case 'xv': 316 | return 2*sharpValue - 1; 317 | case 'x': 318 | return 2*sharpValue; 319 | case 'x^': 320 | case 'x^1': 321 | return 2*sharpValue + 1; 322 | case 'x^2': 323 | return 2*sharpValue + 2; 324 | case 'x^3': 325 | return 2*sharpValue + 3; 326 | 327 | // Addon 328 | case '^4': 329 | return 4; 330 | case 'v4': 331 | return -4; 332 | case '#^4': 333 | return sharpValue + 4; 334 | case '#v4': 335 | return sharpValue - 4; 336 | case 'b^4': 337 | return -sharpValue + 4; 338 | case 'bv4': 339 | return -sharpValue - 4; 340 | case 'x^4': 341 | return 2*sharpValue + 4; 342 | case 'xv4': 343 | return 2*sharpValue - 4; 344 | case 'bb^4': 345 | return -2*sharpValue + 4; 346 | case 'bbv4': 347 | return -2*sharpValue - 4; 348 | 349 | default: 350 | return null; 351 | } 352 | } 353 | 354 | // Takes in annotations[].text and returns either 355 | // a key signature object if str is a valid custom key sig code or null. 356 | // 357 | // Valid key sig code is denoted as such: 358 | // .c.d.e.f.g.a.b 359 | // where identifiers c thru b denote a valid accidental code of which 360 | // will apply to the respective notes. 361 | // 362 | // For example, this is F-down major: .v.v.v.v.v.v.bv 363 | // 364 | // whitespace can be placed between dots and accidentals for readability. 365 | // 366 | // For the natural accidental, blank or whitespace will both work. 367 | // 368 | // Assign the key signature object to the parms.currKeySig field! 369 | function scanCustomKeySig(str, edo) { 370 | if (typeof (str) !== 'string') 371 | return null; 372 | str = str.trim(); 373 | var keySig = {}; 374 | var res = str.match(customKeySigRegex); 375 | // For code golfing 376 | var notes = [null, 'c', 'd', 'e', 'f', 'g', 'a', 'b']; 377 | 378 | if (res === null) 379 | return null; 380 | 381 | for (var i = 1; i <= 7; i++) { 382 | var acc = convertAccidentalToStepsOrNull(res[i].trim(), edo); 383 | console.log('keySig ' + i + ', steps: ' + acc); 384 | if (acc !== null) 385 | keySig[notes[i]] = acc; 386 | else 387 | keySig[notes[i]] = 0; 388 | } 389 | return keySig; 390 | } 391 | 392 | // Apply the given function to all notes in selection 393 | // or, if nothing is selected, in the entire score 394 | 395 | function applyToNotesInSelection(func, parms) { 396 | var cursor = curScore.newCursor(); 397 | cursor.rewind(1); 398 | var startStaff; 399 | var endStaff; 400 | var endTick; 401 | var fullScore = false; 402 | if (!cursor.segment) { // no selection 403 | fullScore = true; 404 | startStaff = 0; // start with 1st staff 405 | endStaff = curScore.nstaves - 1; // and end with last 406 | } else { 407 | startStaff = cursor.staffIdx; 408 | cursor.rewind(2); 409 | if (cursor.tick == 0) { 410 | // this happens when the selection includes 411 | // the last measure of the score. 412 | // rewind(2) goes behind the last segment (where 413 | // there's none) and sets tick=0 414 | endTick = curScore.lastSegment.tick + 1; 415 | } else { 416 | endTick = cursor.tick; 417 | } 418 | endStaff = cursor.staffIdx; 419 | } 420 | console.log(startStaff + " - " + endStaff + " - " + endTick); 421 | // -------------- Actual thing here ----------------------- 422 | 423 | 424 | for (var staff = startStaff; staff <= endStaff; staff++) { 425 | 426 | // Reset accidentals at the start of every staff. 427 | parms.accidentals = {}; 428 | 429 | 430 | 431 | // Even if system text is used for key sig, the text 432 | // won't carry over for all voices (if the text was placed on voice 1, only 433 | // voice 1 will see the text) 434 | // 435 | // Therefore, all the diff custom key sig texts across all 4 voices 436 | // need to be aggregated into this array before the notes can be 437 | // tuned. 438 | var staffKeySigHistory = []; 439 | var staffCenterHistory = []; 440 | var staffEDOHistory = []; 441 | var staffTranspositionHistory = []; 442 | 443 | // initial run to populate custom key signatures 444 | for (var voice = 0; voice < 4; voice++) { 445 | 446 | // Note: either ways, it is still necesssary to go to the start of the score before 447 | // applying to notes in selection as custom key signatures may precede the selection 448 | // that should still apply to the score. 449 | 450 | // NOTE: THIS IS THE ONLY RIGHT WAY (TM) TO REWIND THE CURSOR TO THE START OF THE SCORE. 451 | // ANY OTHER METHOD WOULD RESULT IN CATASTROPHIC FAILURE FOR WHATEVER REASON. 452 | cursor.rewind(1); 453 | cursor.voice = voice; 454 | cursor.staffIdx = staff; 455 | cursor.rewind(0); 456 | 457 | var measureCount = 0; 458 | console.log("processing custom key signatures staff: " + staff + ", voice: " + voice); 459 | 460 | while (true) { 461 | if (cursor.segment) { 462 | // scan edo & tuning center first. key signature parsing is dependant on edo used. 463 | for (var i = 0; i < cursor.segment.annotations.length; i++) { 464 | var annotation = cursor.segment.annotations[i]; 465 | console.log("found annotation type: " + annotation.name); 466 | if ((annotation.name == 'StaffText' && Math.floor(annotation.track / 4) == staff) || 467 | (annotation.name == 'SystemText')) { 468 | var text = removeFormattingCode(annotation.text); 469 | if (text.toLowerCase().trim().endsWith('edo')) { 470 | var edo = parseInt(text.substring(0, text.length - 3)); 471 | if (edo !== NaN || edo !== undefined || edo !== null) { 472 | console.log('found EDO annotation: ' + text) 473 | staffEDOHistory.push({ 474 | tick: cursor.tick, 475 | edo: edo 476 | }); 477 | } 478 | } else if (text.trim().search(/[a-g][0-9]:/i) == 0) { 479 | var txt = text.toLowerCase().trim(); 480 | if (txt.endsWith('hz')) 481 | txt = txt.substring(0, txt.length - 2); 482 | var center = {note: txt.substring(0, 2), freq: parseFloat(txt.substring(3))}; 483 | if (center.freq !== NaN || center.freq !== undefined || center.freq !== null) { 484 | console.log('found tuning center annotation: ' + text) 485 | staffCenterHistory.push({ 486 | tick: cursor.tick, 487 | center: center 488 | }); 489 | } 490 | } 491 | } 492 | } 493 | 494 | // Check for StaffText key signature changes, then update staffKeySigHistory 495 | for (var i = 0; i < cursor.segment.annotations.length; i++) { 496 | var annotation = cursor.segment.annotations[i]; 497 | console.log("found annotation type: " + annotation.name); 498 | if ((annotation.name == 'StaffText' && Math.floor(annotation.track / 4) == staff) || 499 | (annotation.name == 'SystemText')) { 500 | var t = annotation.text.toLowerCase().trim(); 501 | if (t.startsWith('t:')) { 502 | t = t.substring(2).trim(); 503 | var nominal = t.substring(0, 1); 504 | var acc = t.substring(1).trim(); 505 | if (fifthsFromC[nominal] !== undefined && standardAccFifths[acc] !== undefined) { 506 | staffTranspositionHistory.push({ 507 | tick: cursor.tick, 508 | fifths: fifthsFromC[nominal] + standardAccFifths[acc] 509 | }); 510 | } 511 | } else { 512 | var text = removeFormattingCode(t); 513 | var mostRecentEDO = staffEDOHistory.length !== 0 ? staffEDOHistory[staffEDOHistory.length - 1].edo : null; 514 | if (!mostRecentEDO) 515 | mostRecentEDO = 12; 516 | var maybeKeySig = scanCustomKeySig(text, mostRecentEDO); 517 | if (maybeKeySig !== null) { 518 | console.log("detected new custom keySig: " + text + ", staff: " + staff + ", voice: " + voice); 519 | staffKeySigHistory.push({ 520 | tick: cursor.tick, 521 | keySig: maybeKeySig 522 | }); 523 | } 524 | } 525 | } 526 | } 527 | 528 | if (cursor.segment.tick == cursor.measure.firstSegment.tick && voice === 0) { 529 | // once new bar is reached, denote new bar in the parms.accidentals.bars object 530 | // so that getAccidental will reset. Only do this for the first voice in a staff 531 | // since voices in a staff shares the same barrings. 532 | if (!parms.accidentals.bars) 533 | parms.accidentals.bars = []; 534 | 535 | parms.accidentals.bars.push(cursor.segment.tick); 536 | measureCount ++; 537 | console.log("New bar - " + measureCount); 538 | } 539 | } 540 | 541 | if (!cursor.next()) 542 | break; 543 | } 544 | } 545 | 546 | // 2 passes - one to ensure all accidentals are represented acorss 547 | // all 4 voices, then the second one to apply those accidentals. 548 | for (var rep = 0; rep < 2; rep++) { 549 | // After every staff, reset the keySig and tuning states back to default 550 | parms.currKeySig = parms.keySig; 551 | parms.currEdo = 12; 552 | parms.currCenter = {note: 'a4', freq: 440}; 553 | parms.currTranspose = 0; 554 | for (var voice = 0; voice < 4; voice++) { 555 | // if first pass go to start of score so that anchors.all 556 | // accidentals are accounted for 557 | // otherwise, go to the start of the selection to begin tuning 558 | 559 | // NOTE: FOR WHATEVER REASON, rewind(1) must be called BEFORE assigning voice and staffIdx, 560 | // and rewind(0) MUST be called AFTER rewind(1), AND AFTER assigning voice and staffIdx. 561 | cursor.rewind(1); 562 | cursor.voice = voice; //voice has to be set after goTo 563 | cursor.staffIdx = staff; 564 | if (fullScore || rep == 0) 565 | cursor.rewind(0); 566 | 567 | var measureCount = 0; 568 | 569 | console.log("processing staff: " + staff + ", voice: " + voice); 570 | 571 | // Loop elements of a voice 572 | while (cursor.segment && (fullScore || cursor.tick < endTick)) { 573 | // Note that the parms.accidentals object now stores accidentals 574 | // from all 4 voices in a staff since microtonal accidentals from one voice 575 | // should affect subsequent notes on the same line in other voices as well. 576 | 577 | var mostRecentKeySigTick = -1; 578 | for (var i = 0; i < staffKeySigHistory.length; i++) { 579 | var keySig = staffKeySigHistory[i]; 580 | if (keySig.tick <= cursor.tick && keySig.tick >= mostRecentKeySigTick) { 581 | parms.currKeySig = keySig.keySig; 582 | mostRecentKeySigTick = keySig.tick; 583 | } 584 | } 585 | 586 | var mostRecentEDOTick = -1; 587 | for (var i = 0; i < staffEDOHistory.length; i++) { 588 | var edo = staffEDOHistory[i]; 589 | if (edo.tick <= cursor.tick && edo.tick >= mostRecentEDOTick) { 590 | parms.currEdo = edo.edo; 591 | mostRecentEDOTick = edo.tick; 592 | } 593 | } 594 | 595 | var mostRecentCenterTick = -1; 596 | for (var i = 0; i < staffCenterHistory.length; i++) { 597 | var center = staffCenterHistory[i]; 598 | if (center.tick <= cursor.tick && center.tick >= mostRecentCenterTick) { 599 | parms.currCenter = center.center; 600 | mostRecentCenterTick = center.tick; 601 | } 602 | } 603 | 604 | var mostRecentTransposeTick = -1; 605 | for (var i = 0; i < staffTranspositionHistory.length; i++) { 606 | var trans = staffTranspositionHistory[i]; 607 | if (trans.tick <= cursor.tick && trans.tick >= mostRecentTransposeTick) { 608 | parms.currTranspose = trans.fifths; 609 | mostRecentTransposeTick = trans.tick; 610 | } 611 | } 612 | 613 | if (cursor.element) { 614 | if (cursor.element.type == Ms.CHORD) { 615 | var graceChords = cursor.element.graceNotes; 616 | for (var i = 0; i < graceChords.length; i++) { 617 | // iterate through all grace chords 618 | var notes = graceChords[i].notes; 619 | for (var j = 0; j < notes.length; j++) 620 | func(notes[j], cursor.segment, parms, rep === 0); 621 | } 622 | var notes = cursor.element.notes; 623 | for (var i = 0; i < notes.length; i++) { 624 | var note = notes[i]; 625 | // find other symbols (aux accidentals) attached to the note 626 | // for (var j = 0; j < note.elements.length; j++) { 627 | // if (note.elements[j].symbol) 628 | // console.log(note.elements[j].symbol); 629 | // } 630 | func(note, cursor.segment, parms, rep === 0); 631 | } 632 | } 633 | } 634 | cursor.next(); 635 | } 636 | } 637 | } 638 | } 639 | } 640 | 641 | // This will register an accidental's offset value and tick position. 642 | // Unified accidental registry is necessary so that special accidentals across 643 | // different voices in the same staff will affect each other as it should. 644 | // 645 | // Only microtonal accidentals need to be registered. Musescore properly handles 646 | // normal accidentals with TPCs. 647 | // 648 | // Remember to reset the parms.accidentals array after every bar & staff! 649 | function registerAccidental(noteLine, tick, stepOffset, parms) { 650 | if (!parms.accidentals[noteLine]) { 651 | parms.accidentals[noteLine] = []; 652 | } 653 | 654 | parms.accidentals[noteLine].push({ 655 | tick: tick, 656 | offset: stepOffset 657 | }); 658 | } 659 | 660 | // Returns the step offset if a prior microtonal accidental exists 661 | // before or at the given tick value. 662 | // Null if there are no explicit microtonal accidentals 663 | // WARNING: DON'T USE !getAccidental() to check for Null because !0 IS TRUE! 664 | function getAccidental(noteLine, tick, parms) { 665 | // Tick of the most recent measure just before current tick 666 | var mostRecentBar = 0; 667 | 668 | for (var i = 0; i < parms.accidentals.bars.length; i++) { 669 | var barTick = parms.accidentals.bars[i]; 670 | 671 | if (barTick > mostRecentBar && barTick <= tick) { 672 | mostRecentBar = barTick; 673 | } 674 | } 675 | 676 | var oldTick = -1; 677 | var offset = null; 678 | 679 | if (!parms.accidentals[noteLine]) 680 | return null; 681 | 682 | for (var i = 0; i < parms.accidentals[noteLine].length; i++) { 683 | var acc = parms.accidentals[noteLine][i]; 684 | 685 | // Accidentals only count if 686 | // 1. They are in the same bar as the current note 687 | // 2. They are before or at the current note's tick 688 | // 3. It is the most recent accidental that fulfills 1. and 2. 689 | if (acc.tick >= mostRecentBar && acc.tick <= tick && acc.tick >= oldTick) { 690 | console.log('note line: ' + noteLine + ', steps: ' + acc.offset + ', tick: ' + acc.tick); 691 | console.log('acc.tick: ' + acc.tick + ', mostRecentBar: ' + mostRecentBar + ', tick: ' + tick + ', oldTick: ' + oldTick); 692 | offset = acc.offset; 693 | oldTick = acc.tick; 694 | } 695 | } 696 | return offset; 697 | } 698 | 699 | // Note: if scanOnly is true, accidentals will be registered but the note 700 | // will not be tuned. 701 | function tuneNote(note, segment, parms, scanOnly) { 702 | var tpc = note.tpc; 703 | var val = [2, 3].map (function (q) {return Math.round(parms.currEdo * Math.log(q) / Math.LN2);}); 704 | var fifthStep = -val[0] + val[1]; 705 | var sharpValue = -11*val[0] + 7*val[1]; 706 | 707 | // If tpc is non-natural, there's no need to go through additional steps, 708 | // since accidentals and key sig are already taken into consideration 709 | // to produce a non-screw-up tpc. 710 | 711 | // However, if tpc is natural, it needs to be checked against acc and 712 | // the key signature to truly determine what note it is. 713 | 714 | switch(tpc) { 715 | case -1: //Fbb 716 | note.tuning = getCentOffset ('f', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 717 | return; 718 | case 0: //Cbb 719 | note.tuning = getCentOffset ('c', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 720 | return; 721 | case 1: //Gbb 722 | note.tuning = getCentOffset ('g', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 723 | return; 724 | case 2: //Dbb 725 | note.tuning = getCentOffset ('d', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 726 | return; 727 | case 3: //Abb 728 | note.tuning = getCentOffset ('a', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 729 | return; 730 | case 4: //Ebb 731 | note.tuning = getCentOffset ('e', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 732 | return; 733 | case 5: //Bbb 734 | note.tuning = getCentOffset ('b', -2*sharpValue, -2, parms.currEdo, parms.currCenter, parms.currTranspose); 735 | return; 736 | 737 | case 6: //Fb 738 | note.tuning = getCentOffset ('f', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 739 | return; 740 | case 7: //Cb 741 | note.tuning = getCentOffset ('c', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 742 | return; 743 | case 8: //Gb 744 | note.tuning = getCentOffset ('g', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 745 | return; 746 | case 9: //Db 747 | note.tuning = getCentOffset ('d', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 748 | return; 749 | case 10: //Ab 750 | note.tuning = getCentOffset ('a', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 751 | return; 752 | case 11: //Eb 753 | note.tuning = getCentOffset ('e', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 754 | return; 755 | case 12: //Bb 756 | note.tuning = getCentOffset ('b', -sharpValue, -1, parms.currEdo, parms.currCenter, parms.currTranspose); 757 | return; 758 | 759 | case 20: //F# 760 | note.tuning = getCentOffset ('f', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 761 | return; 762 | case 21: //C# 763 | note.tuning = getCentOffset ('c', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 764 | return; 765 | case 22: //G# 766 | note.tuning = getCentOffset ('g', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 767 | return; 768 | case 23: //D# 769 | note.tuning = getCentOffset ('d', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 770 | return; 771 | case 24: //A# 772 | note.tuning = getCentOffset ('a', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 773 | return; 774 | case 25: //E# 775 | note.tuning = getCentOffset ('e', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 776 | return; 777 | case 26: //B# 778 | note.tuning = getCentOffset ('b', sharpValue, 1, parms.currEdo, parms.currCenter, parms.currTranspose); 779 | return; 780 | 781 | case 27: //Fx 782 | note.tuning = getCentOffset ('f', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 783 | return; 784 | case 28: //Cx 785 | note.tuning = getCentOffset ('c', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 786 | return; 787 | case 29: //Gx 788 | note.tuning = getCentOffset ('g', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 789 | return; 790 | case 30: //Dx 791 | note.tuning = getCentOffset ('d', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 792 | return; 793 | case 31: //Ax 794 | note.tuning = getCentOffset ('a', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 795 | return; 796 | case 32: //Ex 797 | note.tuning = getCentOffset ('e', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 798 | return; 799 | case 33: //Bx 800 | note.tuning = getCentOffset ('b', 2*sharpValue, 2, parms.currEdo, parms.currCenter, parms.currTranspose); 801 | return; 802 | } 803 | 804 | // in the event that tpc is considered natural by 805 | // MuseScore's playback, it would mean that it is 806 | // either a natural note, or a microtonal accidental. 807 | 808 | var baseNote; 809 | switch(tpc) { 810 | case 13: 811 | baseNote = 'f'; 812 | break; 813 | case 14: 814 | baseNote = 'c'; 815 | break; 816 | case 15: 817 | baseNote = 'g'; 818 | break; 819 | case 16: 820 | baseNote = 'd'; 821 | break; 822 | case 17: 823 | baseNote = 'a'; 824 | break; 825 | case 18: 826 | baseNote = 'e'; 827 | break; 828 | case 19: 829 | baseNote = 'b'; 830 | break; 831 | } 832 | 833 | //NOTE: Only special accidentals need to be remembered. 834 | var accOffset = null; 835 | if (note.accidental) { 836 | console.log('Note: ' + baseNote + ', Line: ' + note.line + 837 | ', Special Accidental: ' + note.accidentalType); 838 | switch(0 + note.accidentalType) { 839 | case Accidental.NATURAL: 840 | accOffset = 0; 841 | break; 842 | case Accidental.SHARP_SLASH4: 843 | accOffset = 3*sharpValue/2; 844 | break; 845 | case Accidental.SHARP_SLASH: 846 | accOffset = sharpValue/2; 847 | break; 848 | case Accidental.MIRRORED_FLAT: 849 | accOffset = -sharpValue/2; 850 | break; 851 | case Accidental.MIRRORED_FLAT2: 852 | accOffset = -3*sharpValue/2; 853 | break; 854 | case Accidental.DOUBLE_SHARP_THREE_ARROWS_UP: 855 | accOffset = 2*sharpValue + 3; 856 | break; 857 | case Accidental.DOUBLE_SHARP_TWO_ARROWS_UP: 858 | accOffset = 2*sharpValue + 2; 859 | break; 860 | case Accidental.SHARP2_ARROW_UP: 861 | case Accidental.DOUBLE_SHARP_ONE_ARROW_UP: 862 | accOffset = 2*sharpValue + 1; 863 | break; 864 | case Accidental.SHARP2_ARROW_DOWN: 865 | case Accidental.DOUBLE_SHARP_ONE_ARROW_DOWN: 866 | accOffset = 2*sharpValue - 1; 867 | break; 868 | case Accidental.DOUBLE_SHARP_TWO_ARROWS_DOWN: 869 | accOffset = 2*sharpValue - 2; 870 | break; 871 | case Accidental.DOUBLE_SHARP_THREE_ARROWS_DOWN: 872 | accOffset = 2*sharpValue - 3; 873 | break; 874 | case Accidental.SHARP_THREE_ARROWS_UP: 875 | accOffset = sharpValue + 3; 876 | break; 877 | case Accidental.SHARP_TWO_ARROWS_UP: 878 | accOffset = sharpValue + 2; 879 | break; 880 | case Accidental.SHARP_ARROW_UP: 881 | case Accidental.SHARP_ONE_ARROW_UP: 882 | accOffset = sharpValue + 1; 883 | break; 884 | case Accidental.SHARP_ARROW_DOWN: 885 | case Accidental.SHARP_ONE_ARROW_DOWN: 886 | accOffset = sharpValue - 1; 887 | break; 888 | case Accidental.SHARP_TWO_ARROWS_DOWN: 889 | accOffset = sharpValue - 2; 890 | break; 891 | case Accidental.SHARP_THREE_ARROWS_DOWN: 892 | accOffset = sharpValue - 3; 893 | break; 894 | case Accidental.NATURAL_THREE_ARROWS_UP: 895 | accOffset = 3; 896 | break; 897 | case Accidental.NATURAL_TWO_ARROWS_UP: 898 | accOffset = 2; 899 | break; 900 | case Accidental.NATURAL_ARROW_UP: 901 | case Accidental.NATURAL_ONE_ARROW_UP: 902 | accOffset = 1; 903 | break; 904 | case Accidental.NATURAL_ARROW_DOWN: 905 | case Accidental.NATURAL_ONE_ARROW_DOWN: 906 | accOffset = -1; 907 | break; 908 | case Accidental.NATURAL_TWO_ARROWS_DOWN: 909 | accOffset = -2; 910 | break; 911 | case Accidental.NATURAL_THREE_ARROWS_DOWN: 912 | accOffset = -3; 913 | break; 914 | case Accidental.FLAT_THREE_ARROWS_UP: 915 | accOffset = -sharpValue + 3; 916 | break; 917 | case Accidental.FLAT_TWO_ARROWS_UP: 918 | accOffset = -sharpValue + 2; 919 | break; 920 | case Accidental.FLAT_ARROW_UP: 921 | case Accidental.FLAT_ONE_ARROW_UP: 922 | accOffset = -sharpValue + 1; 923 | break; 924 | case Accidental.FLAT_ARROW_DOWN: 925 | case Accidental.FLAT_ONE_ARROW_DOWN: 926 | accOffset = -sharpValue - 1; 927 | break; 928 | case Accidental.FLAT_TWO_ARROWS_DOWN: 929 | accOffset = -sharpValue - 2; 930 | break; 931 | case Accidental.FLAT_THREE_ARROWS_DOWN: 932 | accOffset = -sharpValue - 3; 933 | break; 934 | case Accidental.DOUBLE_FLAT_THREE_ARROWS_UP: 935 | accOffset = -2*sharpValue + 3; 936 | break; 937 | case Accidental.DOUBLE_FLAT_TWO_ARROWS_UP: 938 | accOffset = -2*sharpValue + 2; 939 | break; 940 | case Accidental.FLAT2_ARROW_UP: 941 | case Accidental.DOUBLE_FLAT_ONE_ARROW_UP: 942 | accOffset = -2*sharpValue + 1; 943 | break; 944 | case Accidental.FLAT2_ARROW_DOWN: 945 | case Accidental.DOUBLE_FLAT_ONE_ARROW_DOWN: 946 | accOffset = -2*sharpValue - 1; 947 | break; 948 | case Accidental.DOUBLE_FLAT_TWO_ARROWS_DOWN: 949 | accOffset = -2*sharpValue - 2; 950 | break; 951 | case Accidental.DOUBLE_FLAT_THREE_ARROWS_DOWN: 952 | accOffset = -2*sharpValue - 3; 953 | break; 954 | 955 | // Addon 956 | case Accidental.RAISE_ONE_SEPTIMAL_COMMA: // ^4 957 | accOffset = 4; 958 | break; 959 | case Accidental.LOWER_ONE_SEPTIMAL_COMMA: // v4 960 | accOffset = -4; 961 | break; 962 | case Accidental.SHARP_SLASH2: // #^4 963 | accOffset = sharpValue + 4; 964 | break; 965 | case Accidental.RAISE_ONE_TRIDECIMAL_QUARTERTONE: // #v4 966 | accOffset = sharpValue - 4; 967 | break; 968 | case Accidental.FOUR_TWELFTH_FLAT: // b^4 969 | accOffset = -sharpValue + 4; 970 | break; 971 | case Accidental.THREE_TWELFTH_FLAT: // bv4 972 | accOffset = -sharpValue - 4; 973 | break; 974 | case Accidental.DOUBLE_SHARP_EQUAL_TEMPERED: // x^4 975 | accOffset = 2*sharpValue + 4; 976 | break; 977 | case Accidental.SAGITTAL_SHARP25SD: // xv4 978 | accOffset = 2*sharpValue - 4; 979 | break; 980 | case Accidental.TEN_TWELFTH_FLAT: // bb^4 981 | accOffset = -2*sharpValue + 4; 982 | break; 983 | case Accidental.NINE_TWELFTH_FLAT: // bbv4 984 | accOffset = -2*sharpValue - 4; 985 | break; 986 | } 987 | 988 | if (accOffset !== null) { 989 | registerAccidental(note.line, segment.tick, accOffset, parms); 990 | } 991 | } 992 | 993 | // Check for prev accidentals first, will be null if not present 994 | var stepsFromBaseNote = accOffset !== null ? accOffset : getAccidental(note.line, segment.tick, parms); 995 | console.log('steps bef KeySig: ' + stepsFromBaseNote); 996 | if (stepsFromBaseNote === null) { 997 | // No accidentals - check key signature. 998 | stepsFromBaseNote = parms.currKeySig[baseNote]; 999 | console.log('steps on KeySig: ' + stepsFromBaseNote); 1000 | } 1001 | 1002 | console.log("Base Note: " + baseNote + ", steps: " + stepsFromBaseNote + ", tick: " + note.parent.parent.tick); 1003 | var isConcert = note.tpc == note.tpc1; 1004 | note.tuning = getCentOffset(baseNote, stepsFromBaseNote, 0, parms.currEdo, parms.currCenter, isConcert ? 0 : parms.currTranspose); 1005 | return; 1006 | } 1007 | 1008 | onRun: { 1009 | console.log("hello n-edo"); 1010 | 1011 | if (typeof curScore === 'undefined') 1012 | Qt.quit(); 1013 | 1014 | var parms = {}; 1015 | 1016 | /* 1017 | key signature as denoted by the TextFields. 1018 | 1019 | NOTE: parms.keySig has been deprecated, it now serves as a placeholder 1020 | for the natural key signature. 1021 | 1022 | THIS SHOULD BE READONLY! 1023 | */ 1024 | parms.keySig = { 1025 | 'c': 0, 1026 | 'd': 0, 1027 | 'e': 0, 1028 | 'f': 0, 1029 | 'g': 0, 1030 | 'a': 0, 1031 | 'b': 0 1032 | }; 1033 | 1034 | /* 1035 | Used for StaffText declared custom key signature. 1036 | No worries about handling system text vs staff text as 1037 | the annotation automatically applies appropriately. 1038 | 1039 | Will be reset to the original TextField denoted key signature 1040 | at the start of each staff, although using both TextField 1041 | and StaffText(22)/SystemText(21) methods of custom key sig 1042 | entry is STRONGLY DISCOURAGED due to extreme unpredicatability. 1043 | */ 1044 | parms.currKeySig = parms.keySig 1045 | 1046 | parms.accidentals = {}; 1047 | 1048 | applyToNotesInSelection(tuneNote, parms); 1049 | Qt.quit(); 1050 | } 1051 | } 1052 | --------------------------------------------------------------------------------