OSDN Git Service

edd260f280cdc18c050b441adc255bd0b329246f
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / music / Music.java
1 package camidion.chordhelper.music;
2
3 /**
4  * 音楽理論ユーティリティ
5  *
6  * Circle-Of-Fifth based music theory functions
7  *
8  * @author Copyright (C) 2004-2014 @きよし - Akiyoshi Kamide
9  */
10 public class Music {
11         /**
12          * 1オクターブの半音数
13          */
14         public static final int SEMITONES_PER_OCTAVE = 12;
15         /**
16          * MIDIノート番号と、
17          * メジャーキー基準の五度圏インデックス値との間の変換を行います。
18          *
19          * <p>双方向の変換に対応しています。
20          * 内部的には、元の値が奇数のときに6(半オクターブ)を足し、
21          * 偶数のときにそのまま返しているだけです。
22          * 値は0~11であるとは限りません。その範囲に補正したい場合は
23          *  {@link #mod12(int)} を併用します。
24          * </p>
25          *
26          * @param n 元の値
27          * @return 変換結果
28          */
29         public static int reverseCo5(int n) {
30                 return (n & 1) == 0 ? n : n+6 ;
31         }
32         /**
33          * ノート番号からオクターブ成分を抜きます。
34          * <p>n % 12 と似ていますが、Java の % 演算子では、
35          * 左辺に負数を与えると答えも負数になってしまうため、n % 12 で計算しても
36          * 0~11 の範囲を外れてしまうことがあります。そこで、
37          * 負数の場合に12を足すことにより 0~11 の範囲に入るよう補正します。
38          * </p>
39          * @param n 元のノート番号
40          * @return オクターブ成分を抜いたノート番号(0~11)
41          */
42         public static int mod12(int n) {
43                 int qn = n % SEMITONES_PER_OCTAVE;
44                 return qn < 0 ? qn + 12 : qn ;
45         }
46         /**
47          * 指定されたMIDIノート番号の音の周波数を返します。
48          * チューニングは A=440Hz とします。
49          *
50          * @param noteNumber MIDIノート番号
51          * @return 音の周波数[Hz]
52          */
53         public static double noteNumberToFrequency(int noteNumber) {
54                 return 55 * Math.pow( 2, (double)(noteNumber - 33)/12 );
55         }
56         /**
57          * MIDIノート番号の示す音階が、
58          * 指定された調(五度圏インデックス値)におけるメジャースケールまたは
59          * ナチュラルマイナースケールの構成音に該当するか調べます。
60          *
61          * <p>調の五度圏インデックス値に0(ハ長調またはイ短調)を指定すると、
62          * 白鍵のときにtrue、黒鍵のときにfalseを返します。
63          * </p>
64          *
65          * @param noteNumber 調べたい音階のノート番号
66          * @param keyCo5 調の五度圏インデックス値
67          * @return スケール構成音のときtrue、スケールを外れている場合false
68          */
69         public static boolean isOnScale(int noteNumber, int keyCo5) {
70                 return mod12(reverseCo5(noteNumber) - keyCo5 + 1) < 7 ;
71         }
72         /**
73          * 五度圏インデックス値で表された音階を、
74          * 指定された半音数だけ移調した結果を返します。
75          *
76          * <p>移調する半音数が0の場合、指定の五度圏インデックス値をそのまま返します。
77          * それ以外の場合、移調結果を -5 ~ 6 の範囲で返します。
78          * </p>
79          *
80          * @param co5 五度圏インデックス値
81          * @param chromaticOffset 移調する半音数
82          * @return 移調結果
83          */
84         public static int transposeCo5(int co5, int chromaticOffset) {
85                 if( chromaticOffset == 0 ) return co5;
86                 int transposedCo5 = mod12( co5 + reverseCo5(chromaticOffset) );
87                 if( transposedCo5 > 6 ) transposedCo5 -= Music.SEMITONES_PER_OCTAVE;
88                 return transposedCo5;
89         }
90         /**
91          * 指定の五度圏インデックス値の真裏にあたる値を返します。
92          * @param co5 五度圏インデックス値
93          * @return 真裏の五度圏インデックス値
94          */
95         public static int oppositeCo5(int co5) {
96                 return co5 > 0 ? co5 - 6 : co5 + 6;
97         }
98 }
99