I’m quite unsure about what you’re actual question is, as clearly you’ve already found a way to notate such, and clearly you may extend the note names however you like.
A custom clef will not be really possible in MuseScore unless you create you own Notation font file that substitutes an existing clef with what you want.
Regarding playback: Simply create a small MuseScore plugin like this:
import MuseScore 3.0
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.1
MuseScore {
version: "3.0.5"
title: "To Nonic"
pluginType: "dialog"
categoryCode: "playback"
property var offsetTextWidth: 200;
property var offsetLabelAlignment: 0x02 | 0x80;
property var offset: [ 0, 150, 300, 450, 600, 750, 900, 1050 ];
onRun: {
if (!curScore) {
error("No score open.\nThis plugin requires an open score to run.\n")
quit()
}
}
function applyTemperament()
{
var selection = new scoreSelection()
curScore.startCmd()
selection.map(filterNotes, reTune(getFinalTuning()))
curScore.endCmd()
return true
}
function filterNotes(element)
{
return element.type == Element.CHORD
}
function reTune(tuning) {
return function(chord, cursor) {
for (var i = 0; i < chord.notes.length; i++) {
var note = chord.notes[i]
note.tuning = tuning(note)
}
}
}
function scoreSelection() {
const SCORE_START = 0
const SELECTION_START = 1
const SELECTION_END = 2
var fullScore
var startStaff
var endStaff
var endTick
var inRange
var rewind
var cursor = curScore.newCursor()
cursor.rewind(SELECTION_START)
if (cursor.segment) {
startStaff = cursor.staffIdx
cursor.rewind(SELECTION_END)
endStaff = cursor.staffIdx;
endTick = 0 // unused
if (cursor.tick === 0) {
endTick = curScore.lastSegment.tick + 1;
} else {
endTick = cursor.tick;
}
inRange = function() {
return cursor.segment && cursor.tick < endTick
}
rewind = function (voice, staff) {
// no idea why, but if there is a selection then
// we need to rewind the cursor *before* setting
// the voice and staff index.
cursor.rewind(SELECTION_START)
cursor.voice = voice
cursor.staffIdx = staff
}
} else {
startStaff = 0
endStaff = curScore.nstaves - 1
inRange = function () {
return cursor.segment
}
rewind = function (voice, staff) {
// no idea why, but if there's no selection then
// we need to rewind the cursor *after* setting
// the voice and staff index.
cursor.voice = voice
cursor.staffIdx = staff
cursor.rewind(SCORE_START)
}
}
this.map = function(filter, process) {
for (var staff = startStaff; staff <= endStaff; staff++) {
for (var voice = 0; voice < 4; voice++) {
rewind(voice, staff)
while (inRange()) {
if (cursor.element && filter(cursor.element)) {
process(cursor.element, cursor)
}
cursor.next()
}
}
}
}
}
function error(errorMessage) {
errorDialog.text = qsTr(errorMessage)
errorDialog.open()
}
function getFinalTuning() {
return function(note) {
var tpc = note.tpc; // Pitch class = circle of fifths position with C == 14
var refpc = (((tpc - 13) % 7) + 7) % 7; // f = 0, c = 1, ..., b = 6
var alt = (tpc - 13 - refpc) / 7; // 0 = nat, -1 = flat, 1 = sharp, ...
var refpc2 = ((4 * refpc) + 3) % 7; // c = 0, d = 1, ...
var pitch = note.pitch; // midi pitch, C4 = 60
var refpitch = pitch - alt; // e.g. Dbb4 = 60, refpitch = D = 62
var octave = (refpitch - (refpitch % 12) - 60) / 12; // Octave from C4 (note: Cbbbbbbbbbbbb5 is still an octave up!)
var nonpc = (((refpc2 - octave) % 8) + 8) % 8; // c4, ..., a4, b4 -> c4, ..., h4, a4, then c5 -> b4, c6 -> a4, ... . Also c3 -> d3, ...
var deltanonave = (refpc2 - octave - nonpc) / 8;
var nonave = octave + deltanonave;
var tuning_refpc = 200 * refpc2 + 1200 * octave;
if (refpc2 > 2) {
tuning_refpc = tuning_refpc - 100;
}
var tuning = getOffset(nonpc) + 1200 * nonave;
return tuning - tuning_refpc;
}
}
function getOffsetS(id) {
switch (id) {
case 0:
return final_c.text
case 1:
return final_d.text
case 2:
return final_e.text
case 3:
return final_f.text
case 4:
return final_g.text
case 5:
return final_h.text
case 6:
return final_a.text
case 7:
return final_b.text
}
}
function getOffset(id) {
return parseFloat(getOffsetS(id))
}
Rectangle {
color: "transparent"
anchors.fill: parent
ColumnLayout {
ColumnLayout {
ColumnLayout {
Label {
text: "C"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_c
text: offset[0]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "D"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_d
text: offset[1]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "E"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_e
text: offset[2]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "F"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_f
text: offset[3]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "G"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_g
text: offset[4]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "H"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_h
text: offset[5]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "A"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_a
text: offset[6]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
Label {
text: "B"
Layout.alignment: offsetLabelAlignment
}
TextField {
Layout.maximumWidth: offsetTextWidth
id: final_b
text: offset[7]
readOnly: false
validator: DoubleValidator { bottom: -99.9; decimals: 1; notation: DoubleValidator.StandardNotation; top: 99.9 }
}
}
RowLayout {
Button {
id: applyButton
text: qsTranslate("PrefsDialogBase", "Apply")
onClicked: {
if (applyTemperament()) {
quit()
}
}
}
Button {
id: cancelButton
text: qsTranslate("PrefsDialogBase", "Cancel")
onClicked: {
quit()
}
}
}
}
}
}
MessageDialog {
id: errorDialog
title: "Error"
text: ""
onAccepted: {
errorDialog.close()
}
}
}
This will then allow you to quickly tune each note to the desired value. This plugin takes C4 as base point.