OSDN Git Service

リファクタリング
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 5 Dec 2016 16:02:42 +0000 (01:02 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 5 Dec 2016 16:02:42 +0000 (01:02 +0900)
src/camidion/chordhelper/ChordDisplayLabel.java
src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/midieditor/MidiMessageForm.java
src/camidion/chordhelper/music/Chord.java
src/camidion/chordhelper/music/Key.java
src/camidion/chordhelper/music/MIDISpec.java
src/camidion/chordhelper/music/NoteSymbol.java
src/camidion/chordhelper/music/NoteSymbolLanguage.java

index abb5c95..0376d44 100644 (file)
@@ -96,7 +96,7 @@ public class ChordDisplayLabel extends JLabel {
                        setText("MIDI note No." + noteNumber + " : " + pn);
                }
                else {
-                       String ns = NoteSymbol.noteNoToSymbol(noteNumber);
+                       String ns = NoteSymbol.noteNumberToSymbol(noteNumber);
                        double f = Music.noteNumberToFrequency(noteNumber);
                        setText("Note: "+ns+"  -  MIDI note No."+noteNumber+" : "+Math.round(f)+"Hz");
                }
index c7c5dc5..d1cb75e 100644 (file)
@@ -283,7 +283,7 @@ public class ChordHelperApplet extends JApplet {
         */
        public static class VersionInfo {
                public static final String      NAME = "MIDI Chord Helper";
-               public static final String      VERSION = "Ver.20161127.1";
+               public static final String      VERSION = "Ver.20161205.1";
                public static final String      COPYRIGHT = "Copyright (C) 2004-2016";
                public static final String      AUTHER = "@きよし - Akiyoshi Kamide";
                public static final String      URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
index 4772b50..099bd1c 100644 (file)
@@ -60,9 +60,7 @@ public class MidiMessageForm extends JPanel implements ActionListener {
                new DefaultComboBoxModel<String>() {
                        {
                                for( int i = 0; i<=0x7F; i++ ) addElement(
-                                       String.format(
-                                               "0x%02X : %d : %s", i, i, NoteSymbol.noteNoToSymbol(i)
-                                       )
+                                       String.format("0x%02X : %d : %s", i, i, NoteSymbol.noteNumberToSymbol(i))
                                );
                                // Center note C
                                setSelectedItem(getElementAt(60));
index e20dedc..d5c3e09 100644 (file)
@@ -79,17 +79,17 @@ public class Chord implements Cloneable {
                /** 長13度(長6度の1オクターブ上) */
                THIRTEENTH(21, OffsetIndex.THIRTEENTH);
 
-               private Interval(int offset, OffsetIndex offsetIndex) {
-                       this.offset = offset;
+               private Interval(int chromaticOffset, OffsetIndex offsetIndex) {
+                       this.chromaticOffset = chromaticOffset;
                        this.offsetIndex = offsetIndex;
                }
                private OffsetIndex offsetIndex;
-               private int offset;
+               private int chromaticOffset;
                /**
                 * 半音差を返します。
                 * @return 半音差
                 */
-               public int getChromaticOffset() { return offset; }
+               public int getChromaticOffset() { return chromaticOffset; }
                /**
                 * 対応するインデックスを返します。
                 * @return 対応するインデックス
@@ -491,33 +491,33 @@ public class Chord implements Cloneable {
         * Swing の {@link JLabel#setText(String)} は HTML で指定できるので、
         * 文字の大きさに変化をつけることができます。
         *
-        * @param color_name 色のHTML表現(色名または #RRGGBB 形式)
+        * @param colorName 色のHTML表現(色名または #RRGGBB 形式)
         * @return コード名のHTML
         */
-       public String toHtmlString(String color_name) {
-               String small_tag = "<span style=\"font-size: 120%\">";
-               String end_of_small_tag = "</span>";
+       public String toHtmlString(String colorName) {
+               String span = "<span style=\"font-size: 120%\">";
+               String endSpan = "</span>";
                String root = rootNoteSymbol.toString();
-               String formatted_root = (root.length() == 1) ? root + small_tag :
-                       root.replace("#",small_tag+"<sup>#</sup>").
-                       replace("b",small_tag+"<sup>b</sup>").
-                       replace("x",small_tag+"<sup>x</sup>");
-               String formatted_bass = "";
+               String formattedRoot = (root.length() == 1) ? root + span :
+                       root.replace("#",span+"<sup>#</sup>").
+                       replace("b",span+"<sup>b</sup>").
+                       replace("x",span+"<sup>x</sup>");
+               String formattedBass = "";
                if( ! rootNoteSymbol.equals(bassNoteSymbol) ) {
                        String bass = bassNoteSymbol.toString();
-                       formatted_bass = (bass.length() == 1) ? bass + small_tag :
-                               bass.replace("#",small_tag+"<sup>#</sup>").
-                               replace("b",small_tag+"<sup>b</sup>").
-                               replace("x",small_tag+"<sup>x</sup>");
-                       formatted_bass = "/" + formatted_bass + end_of_small_tag;
+                       formattedBass = (bass.length() == 1) ? bass + span :
+                               bass.replace("#",span+"<sup>#</sup>").
+                               replace("b",span+"<sup>b</sup>").
+                               replace("x",span+"<sup>x</sup>");
+                       formattedBass = "/" + formattedBass + endSpan;
                }
                String suffix = symbolSuffix().
                        replace("-5","<sup>-5</sup>").
                        replace("+5","<sup>+5</sup>");
                return
                        "<html>" +
-                       "<span style=\"color: " + color_name + "; font-size: 170% ; white-space: nowrap ;\">" +
-                       formatted_root + suffix + end_of_small_tag + formatted_bass +
+                       "<span style=\"color: " + colorName + "; font-size: 170% ; white-space: nowrap ;\">" +
+                       formattedRoot + suffix + endSpan + formattedBass +
                        "</span>" +
                        "</html>" ;
        }
@@ -526,11 +526,11 @@ public class Chord implements Cloneable {
         * @return コードの説明(英語)
         */
        public String toName() {
-               String chord_name = rootNoteSymbol.toStringIn(NoteSymbolLanguage.NAME) + nameSuffix() ;
+               String name = rootNoteSymbol.toStringIn(NoteSymbolLanguage.NAME) + nameSuffix() ;
                if( ! rootNoteSymbol.equals(bassNoteSymbol) ) {
-                       chord_name += " on " + bassNoteSymbol.toStringIn(NoteSymbolLanguage.NAME);
+                       name += " on " + bassNoteSymbol.toStringIn(NoteSymbolLanguage.NAME);
                }
-               return chord_name;
+               return name;
        }
        /**
         * コードネームの音名を除いた部分(サフィックス)を組み立てて返します。
index 1ac709b..c8bd9a2 100644 (file)
@@ -36,7 +36,7 @@ public class Key implements Cloneable {
        /**
         * 調号が空のキー(ハ長調またはイ短調)を構築します。
         */
-       public Key() { setKey(0, MAJOR_OR_MINOR); }
+       public Key() { }
        /**
         * 指定の五度圏インデックス値を持つ調を、
         * メジャーとマイナーを指定せずに構築します。
@@ -68,11 +68,11 @@ public class Key implements Cloneable {
        /**
         * C、Am のような文字列から調を構築します。
         * @param keySymbol 調を表す文字列
-        * @throw IllegalArgumentException 調を表す文字列が不正の場合
+        * @throw IllegalArgumentException 引数が空文字列の場合、または音名で始まっていない場合
         */
        public Key(String keySymbol) throws IllegalArgumentException {
                boolean isMinor = keySymbol.matches(".*m");
-               setKey((new NoteSymbol(keySymbol)).toCo5(isMinor), isMinor);
+               setKey((new NoteSymbol(keySymbol)).toCo5ForKey(isMinor), isMinor);
        }
        /**
         * 指定されたコードと同名の調を構築します。
@@ -80,7 +80,7 @@ public class Key implements Cloneable {
         */
        public Key(Chord chord) {
                boolean isMinor = chord.isSet(Chord.Interval.MINOR);
-               setKey(chord.rootNoteSymbol().toCo5(isMinor), isMinor);
+               setKey(chord.rootNoteSymbol().toCo5ForKey(isMinor), isMinor);
        }
        @Override
        public Key clone() { return new Key(co5, majorMinor); }
@@ -138,7 +138,7 @@ public class Key implements Cloneable {
         * 相対ドの音階を返します。
         * @return 相対ドの音階(0~11)
         */
-       public int relativeDo() { return NoteSymbol.toNoteNumber(co5); }
+       public int relativeDo() { return NoteSymbol.majorCo5ToNoteNumber(co5); }
        /**
         * この調のルート音を返します。
         * メジャーキーの場合は相対ド、
index ab59912..0e0cb65 100644 (file)
@@ -713,7 +713,7 @@ public class MIDISpec {
                                                str += getPercussionName(data1);
                                        }
                                        else {
-                                               str += NoteSymbol.noteNoToSymbol(data1);
+                                               str += NoteSymbol.noteNumberToSymbol(data1);
                                        }
                                        str +="] Velocity=" + data2;
                                        break;
index 1639dd4..e9570fc 100644 (file)
@@ -15,31 +15,23 @@ package camidion.chordhelper.music;
 public class NoteSymbol implements Cloneable {
        private static final int INDEX_OF_A = NoteSymbolLanguage.SYMBOL.indexOf("A");
        private static final int INDEX_OF_C = NoteSymbolLanguage.SYMBOL.indexOf("C");
-       /**
-        * メジャーキー基準の五度圏インデックス値
-        */
+       /** メジャーキー基準の五度圏インデックス値 */
        private int majorCo5;
-       /**
-        * ノート番号(0~11)
-        */
+       /** ノート番号(0~11) */
        private int noteNumber;
-       /**
-        * 音名 C(ハ音)を構築します。
-        */
-       public NoteSymbol() {
-       }
+       /** 音名 C(ハ音)を構築します。 */
+       public NoteSymbol() { }
        /**
         * 五度圏インデックス値(メジャーキー基準)から音名を構築します。
         * @param majorCo5 五度圏インデックス値
         */
        public NoteSymbol(int majorCo5) {
-               noteNumber = toNoteNumber(this.majorCo5 = majorCo5);
+               noteNumber = majorCo5ToNoteNumber(this.majorCo5 = majorCo5);
        }
        /**
         * 音名を文字列から構築します。
         * @param noteSymbol 音名の文字列
-        * @throws IllegalArgumentException
-        *  指定の音名が空、またはA~Gの範囲を外れている場合
+        * @throws IllegalArgumentException 引数が空文字列の場合、または音名で始まっていない場合
         */
        public NoteSymbol(String noteSymbol) {
                this(NoteSymbolLanguage.SYMBOL.indexOf(noteSymbol) - INDEX_OF_C);
@@ -83,18 +75,16 @@ public class NoteSymbol implements Cloneable {
         */
        public int toCo5() { return majorCo5; }
        /**
-        * メジャーかマイナーかを指定し、対応する五度圏インデックス値を返します。
-        * <p>マイナーの場合、
-        * メジャー基準の五度圏インデックス値から3が差し引かれます。
-        * 例えば、C major の場合は調号が0個なのに対し、
-        * C minor のときは調号の♭が3個に増えますが、
+        * メジャー/マイナーキーに対応する五度圏インデックス値を返します。
+        * <p>マイナーの場合、メジャー基準の五度圏インデックス値から3が差し引かれます。
+        * 例えば、C major の場合は調号が0個なのに対し、C minor のときは調号の♭が3個に増えますが、
         * 3を差し引くことによってこのズレが補正されます。
         * </p>
         *
         * @param isMinor マイナーのときtrue
         * @return 五度圏インデックス値
         */
-       public int toCo5(boolean isMinor) { return isMinor ? majorCo5 - 3 : majorCo5; }
+       public int toCo5ForKey(boolean isMinor) { return isMinor ? majorCo5 - 3 : majorCo5; }
        /**
         * ノート番号(0~11)を返します。
         * <p>これはMIDIノート番号からオクターブ情報を抜いた値と同じです。
@@ -117,40 +107,16 @@ public class NoteSymbol implements Cloneable {
         * @return 文字列表現
         */
        public String toStringIn(NoteSymbolLanguage language) {
-               return toStringIn(language, false);
+               return language.stringOf(majorCo5 + INDEX_OF_C);
        }
        /**
-        * 指定した言語モードとメジャーマイナー種別における文字列表現を返します。
-        * <p>マイナーが指定された場合、五度圏インデックス値を3つ進めた音階として返します。
-        * 例えば、{@link #toCo5()} の戻り値が0の場合、
-        * メジャーが指定されていれば C を返しますが、
-        * マイナーが指定されると A を返します。
-        * これにより、同じ五度圏インデックス値0で C と Am の両方のルート音を導出できます。
-        * </p>
+        * 指定した言語モードにおける、マイナーキー用の文字列表現を返します。
+        * マイナーキー用の文字列では、例えば五度圏インデックスが0の場合、Cの代わりにAを返します。
         * @param language 言語モード
-        * @param isMinor マイナーのときtrue
         * @return 文字列表現
         */
-       public String toStringIn(NoteSymbolLanguage language, boolean isMinor) {
-               int index = majorCo5 + (isMinor ? INDEX_OF_A : INDEX_OF_C);
-               if( index < 0 || index >= 35 ) {
-                       // インデックスOB発生の恐れがある場合
-                       // 調号 5b ~ 6# の範囲に収まるルート音となるような異名同音(enharmonic)に置き換える
-                       index = Music.mod12(index);  // returns 0(Fbb) ... 7(Fb) 8(Cb) 9(Gb) 10(Db) 11(Ab)
-                       if( isMinor ) {
-                               // 18(Am)
-                               if( index == 0 )
-                                       index += Music.SEMITONES_PER_OCTAVE * 2; // 0(Fbbm) -> 24(D#m 5#)
-                               else
-                                       index += Music.SEMITONES_PER_OCTAVE;  // 1(Cbbm) -> 13(Bbm 5b)
-                       }
-                       else {
-                               // 15(C)
-                               if( index < 10 )  // 0(Fbb) -> 12(Eb 3b), 9(Gb) -> 21(F# 6#)
-                                       index += Music.SEMITONES_PER_OCTAVE;
-                       }
-               }
-               return language.stringOf(index);
+       public String toMinorKeyRootStringIn(NoteSymbolLanguage language) {
+               return language.stringOf(majorCo5 + INDEX_OF_A);
        }
        /**
         * 指定の最大文字数の範囲で、MIDIノート番号が示す音名を返します。
@@ -163,7 +129,7 @@ public class NoteSymbol implements Cloneable {
         * ダブルシャープ、ダブルフラットを使った表現は返しません。
         * </p>
         * @param noteNumber MIDIノート番号
-        * @param maxChars 最大文字数
+        * @param maxChars 最大文字数(最大がない場合は負数を指定)
         * @return MIDIノート番号が示す音名
         */
        public static String noteNumberToSymbol(int noteNumber, int maxChars) {
@@ -171,7 +137,7 @@ public class NoteSymbol implements Cloneable {
                if( co5 == 11 ) co5 -= Music.SEMITONES_PER_OCTAVE; // E# -> F
                if( co5 < 6 ) return (new NoteSymbol(co5)).toString(); // F C G D A E B
 
-               if( maxChars >= "F# / Gb".length() ) return
+               if( maxChars < 0 || maxChars >= "F# / Gb".length() ) return
                                (new NoteSymbol(co5)).toString() + " / " +
                                (new NoteSymbol(co5 - Music.SEMITONES_PER_OCTAVE)).toString();
 
@@ -179,15 +145,14 @@ public class NoteSymbol implements Cloneable {
                return (new NoteSymbol(co5)).toString(); // C# Eb F# Ab Bb
        }
        /**
-        * 最大256文字の範囲で、MIDIノート番号が示す音名を返します。
-        * <p>内部的には
-        * {@link #noteNumberToSymbol(int, int)} を呼び出しているだけです。
+        * MIDIノート番号が示す音名を返します。
+        * 内部的には{@link #noteNumberToSymbol(int,int)}を呼び出しているだけです。
         * </p>
-        * @param noteNo MIDIノート番号
+        * @param noteNumber MIDIノート番号
         * @return MIDIノート番号が示す音名
         */
-       public static String noteNoToSymbol(int noteNo) {
-               return noteNumberToSymbol(noteNo, 256);
+       public static String noteNumberToSymbol(int noteNumber) {
+               return noteNumberToSymbol(noteNumber, -1);
        }
        /**
         * 指定された五度圏インデックス値(メジャーキー基準)を
@@ -200,7 +165,7 @@ public class NoteSymbol implements Cloneable {
         * </p>
         * @return ノート番号(0~11)
         */
-       public static int toNoteNumber(int majorCo5) {
+       public static int majorCo5ToNoteNumber(int majorCo5) {
                return Music.mod12(Music.reverseCo5(majorCo5));
        }
 }
\ No newline at end of file
index 82ef7f6..b10dfff 100644 (file)
@@ -5,19 +5,13 @@ import java.util.List;
 import java.util.Objects;
 
 /**
- * 音階シンボルの言語モードによる違いを定義します。
- * <p>各音階にはインデックス値が割り当てられます。
- * このインデックス値は、五度圏順で並んだ変化記号のない7音階(FCGDAEB)に対するインデックス値
- * x (0~6) と、
- * 変化記号(ダブルフラット、フラット、なし、シャープ、ダブルシャープ)に対するインデックス値
- * y (0~4) に基づいて、次の式で計算されます。</p>
- * <pre>インデックス値 = 5y + x</pre>
- * <p>このインデックス値の範囲は下記のように 0~34 となります。</p>
+ * 音階や調を表すシンボルの言語モードによる違いを定義します。
+ * <p>音名には、下記のような五度圏順のインデックス値(0~34)が割り当てられます。
  * <pre>Fbb=0, Cbb=1, .. Bb=13, F=14, C=15, .. B=20, F#=21, C#=22, .. B#=27, Fx=28, .. Bx=34</pre>
  */
 public enum NoteSymbolLanguage {
        /**
-        * シンボル表記(Bb, F#)
+        * 記号表記(Bb, F#)
         */
        SYMBOL(Arrays.asList("bb","b","","#","x"),"","m"),
        /**
@@ -28,27 +22,7 @@ public enum NoteSymbolLanguage {
         * 日本名表記(変ロ, 嬰ヘ)
         */
        IN_JAPANESE(Arrays.asList("重変","変","","嬰","重嬰"),"長調","短調");
-       /**
-        * ♭や♯の表記を、半音下がる数が多いほうから順に並べたリスト
-        */
-       private List<String> sharpFlatList;
-       /**
-        * 音名を五度圏順で並べた7文字
-        */
-       private String notes;
-       /**
-        * メジャーを表す文字列
-        */
-       private String major;
-       /**
-        * マイナーを表す文字列
-        */
-       private String minor;
-       /**
-        * メジャーとマイナーを併記する場合の区切り文字
-        */
-       private String majorMinorDelimiter;
-
+       //
        private NoteSymbolLanguage(List<String> sharpFlatList, String major, String minor) {
                if( (this.sharpFlatList = sharpFlatList).contains("変") ) {
                        this.notes = "ヘハトニイホロ";
@@ -61,62 +35,91 @@ public enum NoteSymbolLanguage {
                this.minor = minor;
        }
        /**
+        * ♭や♯の表記を、半音下がる数が多いほうから順に並べたリスト
+        */
+       private List<String> sharpFlatList;
+       /**
+        * 引数の先頭にある、♭や♯などの変化記号のインデックス(0~4)を返します。
+        * <p>変化記号がない場合、2 を返します。それ以外は次の値を返します。</p>
+        * <ul>
+        * <li>ダブルシャープ:4</li>
+        * <li>シャープ:3</li>
+        * <li>フラット:1</li>
+        * <li>ダブルフラット:0</li>
+        * </ul>
+        * @param s 変化記号で始まる文字列
+        * @return インデックス
+        */
+       private int sharpFlatIndexOf(String s) {
+               int index = 0;
+               for( String sharpFlat : sharpFlatList ) {
+                       if( ! sharpFlat.isEmpty() && s.startsWith(sharpFlat) ) return index;
+                       index++;
+               }
+               return 2;
+       }
+       /**
+        * 音名を五度圏順で並べた7文字
+        */
+       private String notes;
+       /**
         * インデックス値に該当する音名を返します。
         * @param index インデックス値(定義は{@link NoteSymbolLanguage}参照)
         * @return 音名(例:Bb、B flat、変ロ)
-        * @throws IndexOutOfBoundsException インデックスが範囲を外れている場合
+        * @throws IndexOutOfBoundsException インデックスが範囲を外れている場合
         */
        public String stringOf(int index) {
-               int sharpFlatIndex = index / 7; // 0 1 2 3 4
-               int noteSymbolIndex = index - sharpFlatIndex * 7; // 0 1 2 3 4 5 6
-               String note = notes.substring(noteSymbolIndex, noteSymbolIndex+1);
+               int sharpFlatIndex = index / 7;
+               char note = notes.charAt(index - sharpFlatIndex * 7);
                String sharpFlat = sharpFlatList.get(sharpFlatIndex);
                return this == IN_JAPANESE ? sharpFlat + note : note + sharpFlat;
        }
        /**
-        * 調の文字列表現を返します。メジャー/マイナーの区別が不明な場合、両方の表現を返します。
-        * @param note 音名
-        * @param majorMinor -1:マイナー 0:不明 1:メジャー
-        * @return 調の文字列表現
-        */
-       public String keyStringOf(NoteSymbol note, int majorMinor) {
-               String majorString = note.toStringIn(this, false) + major;
-               if( majorMinor > 0 ) {
-                       return majorString;
-               }
-               else {
-                       String minorString = note.toStringIn(this, true) + minor;
-                       return majorMinor < 0 ? minorString : majorString + majorMinorDelimiter + minorString ;
-               }
-       }
-       /**
-        * 音名の文字列(英字のみ)に対するインデックス値を返します。
-        * 音名は通常大文字ですが、小文字も認識します。
+        * 音名に対するインデックス値を返します。
+        * 音名は通常、英大文字(ABCDEFG)ですが、英小文字(abcdefg)も認識します。
+        * 日本語名(イロハニホヘト)はサポートしていません。
         *
-        * @param noteSymbol é\9f³å\90\8dã\81®文字列
+        * @param noteSymbol é\9f³å\90\8dã\81§å§\8bã\81¾ã\82\8b文字列
         * @return インデックス値(定義は{@link NoteSymbolLanguage}参照)
-        * @throws
-        * UnsupportedOperationException このオブジェクトが {@link #IN_JAPANESE} の場合
-        * @throws
-        * NullPointerException 指定された音名がnullの場合
-        * @throws
-        * IllegalArgumentException 指定された音名が空、または[A~G、a~g]の範囲を外れている場合
+        * @throws UnsupportedOperationException このオブジェクトが {@link #IN_JAPANESE} の場合
+        * @throws NullPointerException 引数がnullの場合
+        * @throws IllegalArgumentException 引数が空文字列の場合、または音名で始まっていない場合
         */
        public int indexOf(String noteSymbol) {
                if( this == IN_JAPANESE ) throw new UnsupportedOperationException();
                Objects.requireNonNull(noteSymbol,"Musical note symbol must not be null");
                String trimmed = noteSymbol.trim();
                if( trimmed.isEmpty() ) throw new IllegalArgumentException("Empty musical note symbol");
-               char prefix = trimmed.charAt(0);
-               int index = notes.indexOf(Character.toUpperCase(prefix));
-               if( index < 0 ) {
-                       throw new IllegalArgumentException("Unknown musical note symbol ["+noteSymbol+"] not in ["+notes+"]");
-               }
-               String suffix = trimmed.substring(1);
-               for( String sf : sharpFlatList ) {
-                       if( suffix.startsWith(sf) ) break; // bb が先にヒットするので b と間違える心配はない
-                       index += 7;
+               int noteIndex = notes.indexOf(Character.toUpperCase(trimmed.charAt(0)));
+               if( noteIndex < 0 ) throw new IllegalArgumentException(
+                               "Unknown musical note symbol ["+noteSymbol+"] not in ["+notes+"]");
+               return 7 * sharpFlatIndexOf(trimmed.substring(1)) + noteIndex;
+       }
+       /**
+        * メジャーを表す文字列
+        */
+       private String major;
+       /**
+        * マイナーを表す文字列
+        */
+       private String minor;
+       /**
+        * メジャーとマイナーを併記する場合の区切り文字
+        */
+       private String majorMinorDelimiter;
+       /**
+        * 調の文字列表現を返します。メジャー/マイナーの区別が不明な場合、両方の表現を返します。
+        * @param note 音名
+        * @param majorMinor 負数:マイナー 0:不明 正数:メジャー
+        * @return 調の文字列表現
+        */
+       public String keyStringOf(NoteSymbol note, int majorMinor) {
+               String s = "";
+               if( majorMinor >= 0 ) {
+                       s = note.toStringIn(this) + major;
+                       if( majorMinor > 0 ) return s;
+                       s += majorMinorDelimiter;
                }
-               return index;
+               return s + note.toMinorKeyRootStringIn(this) + minor;
        }
 }