* (アプレットクラス)
*
* @auther
- * Copyright (C) 2004-2016 @きよし - Akiyoshi Kamide
+ * Copyright (C) 2004-2017 @きよし - Akiyoshi Kamide
* http://www.yk.rim.or.jp/~kamide/music/chordhelper/
*/
public class ChordHelperApplet extends JApplet {
*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20170103.1";
+ public static final String VERSION = "Ver.20170104.1";
public static final String COPYRIGHT = "Copyright (C) 2004-2017";
public static final String AUTHER = "@きよし - Akiyoshi Kamide";
public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
* MIDI Chord Helper 用のコードボタンマトリクス
*
* @author
- * Copyright (C) 2004-2016 Akiyoshi Kamide
+ * Copyright (C) 2004-2017 Akiyoshi Kamide
* http://www.yk.rim.or.jp/~kamide/music/chordhelper/
*/
public class ChordMatrix extends JPanel
boolean shiftPressed = false; // True if Shift-key pressed or CapsLocked
char keyChar = e.getKeyChar();
int keyCode = e.getKeyCode();
+ //System.out.println("keyChar="+((int)keyChar)+" keyCode="+keyCode);
ChordLabel cl = null;
Chord chord = null;
int keyCo5 = key.toCo5();
- // System.out.println( keyChar + " Pressed on chord matrix" );
//
if( (i = "6 ".indexOf(keyChar)) >= 0 ) {
selectedChord = selectedChordCapo = null;
pcKeyNextShift7 = null;
return;
}
+ // Center (Major)
else if( (i = "asdfghjkl;:]".indexOf(keyChar)) >= 0 ) {
iCol = i + keyCo5 + 7;
}
iCol = i + keyCo5 + 7;
shiftPressed = true;
}
+ // Bottom (minor)
else if( (i = "zxcvbnm,./\\".indexOf(keyChar)) >=0 ) {
iCol = i + keyCo5 + 7;
iRow = 2;
iRow = 2;
shiftPressed = true;
}
+ // Top (sus4)
else if( (i = "qwertyuiop@[".indexOf(keyChar)) >= 0 ) {
iCol = i + keyCo5 + 7;
iRow = 0;
iRow = 0;
shiftPressed = true;
}
+ // Number
else if( keyChar == '5' ) {
pcKeyNextShift7 = Chord.Interval.MAJOR_SEVENTH; return;
}
else if( keyChar == '7' ) {
pcKeyNextShift7 = Chord.Interval.SEVENTH; return;
}
- // Shift current key-signature
+ // Shift current key-signature with arrow key
else if( keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_KP_LEFT ) {
- // Add a flat
+ // Add a flat to key-signature (Parfect-5th down)
setKeySignature(new Key(keyCo5 - 1));
return;
}
else if( keyCode == KeyEvent.VK_RIGHT || keyCode == KeyEvent.VK_KP_RIGHT ) {
- // Add a sharp
+ // Add a sharp to key-signature (Parfect-5th up)
setKeySignature(new Key(keyCo5 + 1));
return;
}
}
else intervals.add(Chord.Interval.FLAT5);
}
- if( e.isControlDown() ) {
- // TODO: ^Hなど、ここに到達する前に特殊な keyChar がやってきてしまうことがある
- intervals.add(Chord.Interval.NINTH);
- }
chord = new Chord(cl.chord, intervals);
if( selectedChordLabel != null ) clear();
(selectedChordLabel = cl).setSelection(true);
* コード名からコードを構築します。
* @param chordSymbol コード名
* @throws NullPointerException コード名にnullが指定された場合
+ * @throws IllegalArgumentException コード名が空文字列の場合、または音名で始まっていない場合
*/
public Chord(String chordSymbol) {
+ String rootOnBass[] = Objects.requireNonNull(chordSymbol, "Chord symbol must not be null").trim().split("(/|on)");
+ String root = (rootOnBass.length > 0 ? rootOnBass[0].trim() : "");
+ bassNoteSymbol = rootNoteSymbol = new NoteSymbol(root);
+ if( rootOnBass.length > 1 ) {
+ String bass = rootOnBass[1].trim();
+ if( ! root.equals(bass) ) bassNoteSymbol = new NoteSymbol(bass);
+ }
intervalMap = new HashMap<>();
set(Interval.MAJOR);
set(Interval.PARFECT5);
- String rootOnBass[] = chordSymbol.trim().split("(/|on)");
- if( rootOnBass.length == 0 ) {
- bassNoteSymbol = rootNoteSymbol = new NoteSymbol();
- } else {
- String root = rootOnBass[0].trim();
- bassNoteSymbol = rootNoteSymbol = new NoteSymbol(root);
- if( rootOnBass.length > 1 ) {
- String bass = rootOnBass[1].trim();
- if( ! root.equals(bass) ) bassNoteSymbol = new NoteSymbol(bass);
- }
- setSymbolSuffix(root.replaceFirst("^[A-G][#bx]*",""));
- }
+ setSymbolSuffix(root.replaceFirst("^[A-G][#bx]*",""));
fixIntervals();
}
/**
return new Chord(root, bass, intervals);
}
- /**
- * この和音の文字列表現としてコード名を返します。
- * @return この和音のコード名
- */
+ /** この和音の文字列表現としてコード名(例: C、Am、G7)を返します。 */
@Override
public String toString() {
String chordSymbol = rootNoteSymbol + symbolSuffix();
* @param timeSignatureUpper 拍子の分子
*/
public ChordProgression( int measureLength, int timeSignatureUpper ) {
- int keyCo5 = (int)(Math.random() * 12) - 5;
- key = new Key(keyCo5, Key.MajorMinor.MAJOR);
lines = new Vector<Line>();
Line line = new Line();
boolean isEnd;
- Chord chord, prevChord = new Chord(new NoteSymbol(keyCo5));
+ double r = Math.random();
+ int keyCo5 = (int)(r * 12) - 5;
+ Chord prevChord = new Chord(key = new Key(keyCo5, Key.MajorMinor.MAJOR));
+ Chord chord;
int co5Offset, prevCo5Offset;
- double r;
for( int mp=0; mp<measureLength; mp++ ) {
isEnd = (mp == 0 || mp == measureLength - 1); // 最初または最後の小節かを覚えておく
Measure measure = new Measure();
private int majorCo5;
/** ノート番号(0~11) */
private int noteNumber;
- /** 音名 C(ハ音)を構築します。 */
- public NoteSymbol() { }
/**
* 五度圏インデックス値(メジャーキー基準)から音名を構築します。
* @param majorCo5 五度圏インデックス値
/**
* 音名を文字列から構築します。
* @param noteSymbol 音名の文字列
+ * @throws NullPointerException 引数がnullの場合
* @throws IllegalArgumentException 引数が空文字列の場合、または音名で始まっていない場合
*/
public NoteSymbol(String noteSymbol) { this(co5OfSymbol(noteSymbol)); }
* この音階の文字列表現を、引数で指定された言語モードで返します。
* @param language 言語モード
* @return 文字列表現
+ * @throws NullPointerException 言語モードがnullの場合
*/
public String toStringIn(Language language) { return stringOf(majorCo5, language); }
* @param majorCo5 五度圏インデックス値(メジャーキー基準、すなわち0のときC)
* @param language 言語モード
* @return 文字列表現
+ * @throws NullPointerException 言語モードがnullの場合
* @throws IndexOutOfBoundsException
* 五度圏インデックス値がダブルフラット(F♭♭,C♭♭,…)からダブルシャープ(…,Ex,Bx)までの範囲(-15 ~ 19)を外れている場合
*/
* 引数で指定された音名のメジャーキー基準の五度圏インデックスを返します。
* @param noteSymbol 音名の文字列
* @return メジャーキー基準の五度圏インデックス
+ * @throws NullPointerException 引数がnullの場合
* @throws IllegalArgumentException 引数が空文字列の場合、または音名で始まっていない場合
*/
public static int co5OfSymbol(String noteSymbol) {
* 五度圏のC/Amに近いキーでよく使われるほうの表記(C# Eb F# Ab Bb)だけを返します。
* </p>
* <p>ノート番号だけでは物理的な音階情報しか得られないため、
- * 白鍵で#♭のついた音階表現(B#、Cb など)、
- * ダブルシャープ、ダブルフラットを使った表現は返しません。
+ * 白鍵で#♭のついた音階表現(B#、Cb など)、ダブルシャープ、ダブルフラットを使った表現は返しません。
* </p>
* @param noteNumber MIDIノート番号
* @param maxChars 最大文字数(最大がない場合は負数を指定)
return noteNumberToSymbol(noteNumber, -1);
}
/**
- * 指定された五度圏インデックス値(メジャーキー基準)を
- * ノート番号(0~11)に変換します。
+ * 指定された五度圏インデックス値(メジャーキー基準、すなわち0のときC)をノート番号(0~11 : C~B)に変換します。
*
* <p>これはMIDIノート番号からオクターブ情報を抜いた値と同じです。
- * 五度圏インデックス値をノート番号に変換した場合、
- * 異名同音、すなわち同じ音階が♭表記、♯表記のどちらだったか
- * という情報は失われます。
+ * 五度圏インデックス値をノート番号に変換した場合、異名同音、すなわち同じ音階が♭表記、♯表記のどちらだったか、という情報は失われます。
* </p>
- * @return ノート番号(0~11)
+ * @param majorCo5 五度圏インデックス値
+ * @return ノート番号
*/
public static int majorCo5ToNoteNumber(int majorCo5) {
return Music.mod12(Music.toggleCo5(majorCo5));