/Users/lyon/j4p/src/sound/musica/MusicalScaleToMidi.java
|
1 package sound.musica;
2 /**
3 * Created by IntelliJ IDEA.
4 * User: Carl
5 * Date: Oct 3, 2003
6 * Time: 3:34:29 PM
7 * To change this template use Options | File Templates.
8 */
9 public class MusicalScaleToMidi {
10 public static final int midiMinNote = 0;
11 public static final int midiMaxNote = 127;
12 public static final int midiNoteRange = 128; // 0-127 possible midi notes
13 public static final int midiOctaveSpan = 12; // intrinsic 12 tone chromatic intervalScale
14 public static final int numMidiOctaves = 2 + midiNoteRange / midiOctaveSpan; //round up midi range on both ends
15
16 private int[] intervalScale;// Programmer chooses type of intervalScale from Scales.java
17 private int[] sequenceScale;// Scale sequence (ref to one octave) derived here from intervalScale
18 private int lengthOfScale; // simplify clumsy references to array length
19 private int userSequenceLo; // Lowest note in sequence scale, ref to 0 of scale
20 private int userSequenceHi; // Highest note in sequence scale, ref to 0 of scale
21 private int midiStartOfUserScale; // Programmer chooses where to start interval Scale
22 private int[][] midiUserScaleProgression; // "keyboard" [octave][note] mapping to midi output
23 // Program computes limits of octave-note inputs
24 private int lowestUserOctave; // Lowest within midi, in user octave numbers
25 private int highestUserOctave; // Highest within midi, in user octave numbers
26 private int lowestUserNote = midiMinNote; // Lowest note within midi in lowest octave
27 private int highestUserNote = midiMaxNote; // Highest note within midi in highest octave
28 /**
29 * @param _intervalScale choice of intervalScale from Scales class
30 * @param _midiStartOfScale insertion point of intervalScale[0] in midi 0-127
31 */
32 public MusicalScaleToMidi(int _intervalScale[], int _midiStartOfScale) {
33 this.intervalScale = _intervalScale; // Programmer responsible for reasonable numbers
34 this.midiStartOfUserScale = _midiStartOfScale; // 0 - 127
35 lengthOfScale = intervalScale.length;
36 sequenceScale = new int[intervalScale.length];
37 computeSequenceScale();
38 midiUserScaleProgression = new int[numMidiOctaves][lengthOfScale];
39 computeUserToMidiOctaveOffsets();
40 createNoteArray();
41 }
42 /**
43 * Computes actual scale sequence from interval scale
44 */
45 private void computeSequenceScale() {
46 sequenceScale[0] = intervalScale[0];
47 for (int i = 1; i < intervalScale.length; i++) {
48 sequenceScale[i] = sequenceScale[i - 1] + intervalScale[i];
49 }
50 userSequenceLo = sequenceScale[0]; // 1st note may not be at scale base (e.g. black notes)
51 userSequenceHi = sequenceScale[lengthOfScale - 1]; // top note in scale, under octave top
52 }
53
54 private void computeUserToMidiOctaveOffsets() {
55 int pointer = midiStartOfUserScale; //midi of user note 0 in any octave
56 int counter = 0; // counts octave offset from user octave 0
57
58 // First: Drop the pointer to below the midi range, if not there already
59 while (pointer + userSequenceHi >= midiMinNote) {
60 pointer -= midiOctaveSpan;
61 counter--;
62 }
63
64 // Second: Raise pointer until first scale notes appear in midi range
65 while (pointer + userSequenceHi < midiMinNote) {
66 pointer += midiOctaveSpan;
67 counter++;
68 }
69 lowestUserOctave = counter;
70 int i = 0;
71 while (pointer + sequenceScale[i] < midiMinNote) { // find first note above midiMin
72 i++;
73 }
74 lowestUserNote = i;
75
76 // Third: Raise the pointer above the midi range
77 while (pointer + userSequenceLo <= midiMaxNote) {
78 pointer += midiOctaveSpan;
79 counter++;
80 }
81
82 // Fourth: Drop back within range
83 pointer -= midiOctaveSpan;
84 counter--;
85 highestUserOctave = counter;
86 i = lengthOfScale - 1; // point to top of scale
87 while (pointer + sequenceScale[i] > midiMaxNote) { // find first note within range
88 i--;
89 }
90 highestUserNote = i;
91 }
92
93 private void createNoteArray() {
94 int tempNote;
95 for (int arrayOctaveNumber = 0; arrayOctaveNumber < numMidiOctaves; arrayOctaveNumber++) {
96 for (int noteNumber = 0; noteNumber < lengthOfScale; noteNumber++) {
97 tempNote = mapToMidi(arrayOctaveNumber + lowestUserOctave, sequenceScale[noteNumber]);
98 midiUserScaleProgression[arrayOctaveNumber][noteNumber] = tempNote;
99 }
100 }
101 }
102
103 private int mapToMidi(int playersOctaveNumber, int noteInOctave) {
104 // return midiNote;
105 return midiStartOfUserScale + midiOctaveSpan * playersOctaveNumber + noteInOctave;
106 }
107
108 // Getters, toString, main
109 public int[][] getMidiUserScaleProgression() {
110 return midiUserScaleProgression;
111 }
112
113 public int[] getIntervalScale() {
114 return intervalScale;
115 }
116
117 public int getMidiStartOfUserScale() {
118 return midiStartOfUserScale;
119 }
120
121 public int getLowestUserOctave() {
122 return lowestUserOctave;
123 }
124
125 public int getHighestUserOctave() {
126 return highestUserOctave;
127 }
128
129 public int getLowestUserNote() {
130 return lowestUserNote;
131 }
132
133 public int getHighestUserNote() {
134 return highestUserNote;
135 }
136
137 public String toString() {
138 String s = "";
139 for (int octaveNumber = 0; octaveNumber < midiUserScaleProgression.length; octaveNumber++) {
140 s += "\n";
141 for (int noteNumber = 0; noteNumber < midiUserScaleProgression[0].length; noteNumber++) {
142 s += midiUserScaleProgression[octaveNumber][noteNumber] + "\t";
143 }
144 }
145 s += "\nmidiStartOfUserScale: " + midiStartOfUserScale;
146 s+= "\nlowOctave; " + lowestUserOctave + "; \tlowNote = " + lowestUserNote;
147 s+= "\nhighOctave; " + highestUserOctave + "; \thighNote = " + highestUserNote;
148 return s;
149 }
150
151 public static void main(String[] args) {
152 int startNote = 127;
153 MusicalScaleToMidi pro =
154 new MusicalScaleToMidi(ScaleManager.BLACK_KEYS, startNote);
155 System.out.println(pro.toString());
156 }
157 }