//int MID_C = 60; // #define NUM_KEYS 12 /* Number of enums in Key */ // Keep these in order (most important first). // Why? See CScale::iStepUpNoteNum /* final int NUM_KEYS = 12; final int KP_ROOT = 0; final int KP_PRIMARY = 1; // "required"? final int KP_SECONDARY = 2; // "auxiliary"? final int KP_TERTIARY = 3; // "modal"? final int KP_CHROMATIC = 4; //} KeyPriority; // Hungarian: kp final int BST_NO_NOTE=0; // No note on this beat final int BST_WHISPER=1; final int BST_LIGHT=2; // Faint note final int BST_MEDIUM=3; // Normal note final int BST_HEAVY=4; // Emphsized note final int BST_BANG=5; } BeatStress; // Hungarian: bst */ //----------------------------------------------------- // Value between 0 & 127 (MIDI), so sign doesn't matter. // typedef char PARAMVAL; // Hungarian: pv //----------------------------------------------------- public class CScale /* Hungarian: scl */ { // Members int m_arrkpPriorities[]; // Constants final int NUM_KEYS = 12; final int KP_ROOT = 0; final int KP_PRIMARY = 1; // "required"? final int KP_SECONDARY = 2; // "auxiliary"? final int KP_TERTIARY = 3; // "modal"? final int KP_CHROMATIC = 4; //======bogus global functions===== public int mod (int x, int y) { if (x>=0) return x%y; int iNegMod = (-x) % y; return (0==iNegMod) ? y-iNegMod : 0; } public void assert(boolean b) { if (!b) m_arrkpPriorities[-1] = 0; } public int rand() { return (int)(Math.random() * 9747); } //================================ // Construction/Destruction CScale (String szInputString) { m_arrkpPriorities = new int[NUM_KEYS]; if (!bSet(szInputString)) assert(false); } public boolean bSet (String szInputString) { int pChar = 0; m_arrkpPriorities[0] = KP_ROOT; for(int C=1; C= 0) ? 1 : -1; for (int C = 0; C != iNumSteps; C += iIncrement) for (iNewIndex += iIncrement; m_arrkpPriorities[mod(iNewIndex,NUM_KEYS)] > kpThreshold; iNewIndex += iIncrement) ; return iCurrNoteNum + iNewIndex - iOldIndex; } public int iRoundNoteNum (int iCurrNoteNum, int kpRound, int iRootNoteNum) { assert(KP_ROOT <= kpRound && kpRound <= KP_CHROMATIC); int iOldIndex = iNoteNumToIndex(iCurrNoteNum, iRootNoteNum); for (int C=0; C < NUM_KEYS; C++) { if (kpRound >= m_arrkpPriorities[mod(iOldIndex + C, NUM_KEYS)]) return iCurrNoteNum + C; if (kpRound >= m_arrkpPriorities[mod(iOldIndex - C, NUM_KEYS)]) return iCurrNoteNum - C; } assert(false); return -1; } private boolean bKP_SAME(int kp1, int kp2) { return ((kp1==KP_PRIMARY || kp1==KP_ROOT) ? (kp2==KP_PRIMARY || kp2==KP_ROOT) : (kp2==KP_SECONDARY || kp2==KP_TERTIARY)); } public int iMatchNearestChord (int iCurrNoteNum, int kpRound, int iRootNoteNum) { int iOldIndex = iNoteNumToIndex(iCurrNoteNum, iRootNoteNum); // There's a chance we'll just match to the scale instead... if ((m_arrkpPriorities[iOldIndex] == KP_ROOT || m_arrkpPriorities[iOldIndex] == KP_PRIMARY) && rand()%3 == 0) return iCurrNoteNum; if (kpRound == KP_CHROMATIC || bKP_SAME(kpRound, m_arrkpPriorities[iOldIndex])) return iCurrNoteNum; for (int C=1; C < NUM_KEYS; C++) { if (bKP_SAME(kpRound, m_arrkpPriorities[mod(iOldIndex + C, NUM_KEYS)])) return iCurrNoteNum + C; if (bKP_SAME(kpRound, m_arrkpPriorities[mod(iOldIndex - C, NUM_KEYS)])) return iCurrNoteNum - C; } assert(false); return -1; } // Return the priority of the given note number in this scale. public int kpGetPriority(int iNoteNum, int iRootNoteNum) { return m_arrkpPriorities[iNoteNumToIndex(iNoteNum, iRootNoteNum)]; } // Implementation //protected void AddToScale (Key ky, int kp); int iNoteNumToIndex (int iCurrNoteNum, int iRootNoteNum) { iRootNoteNum %= NUM_KEYS; iCurrNoteNum %= NUM_KEYS; if (iRootNoteNum <= iCurrNoteNum) return iCurrNoteNum - iRootNoteNum; return iCurrNoteNum + NUM_KEYS - iRootNoteNum; } } // CScale //-------------------------------------------------------