home *** CD-ROM | disk | FTP | other *** search
Java Source | 2017-09-21 | 8.9 KB | 267 lines |
- public class CMusicLine // Hungarian: mln
- {
- 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;
- 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;
- final char MID_C = 60;
- // Members
- CCompoundMusicLine m_pcmlParent;
- CLayer m_plyrParent;
-
- char m_pvCenterNoteNum;
-
- CNote m_arrpNotesPlayed[]; // Assume sorted by the iBeatNum field.
- int m_iNumNotesPlayed;
- int m_iNumNotesAllocated;
-
- //======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_arrpNotesPlayed[-1] = null; }
- public int rand() { return (int)(Math.random() * 9747); }
- //================================
-
- public CNote pNoteToPlay (int iCurrBeatNum,
- CLineMods plm/*=0*/)
- { // If a note has already been played at this beat number:
- if (m_iNumNotesPlayed > 0 && m_arrpNotesPlayed
- [m_iNumNotesPlayed-1].iBeatNum == iCurrBeatNum) {
- return null;
- }
- if (!m_plyrParent.bActive())
- return null;
-
- CRthmMods rm = new CRthmMods(m_plyrParent.rymodRthmStatus(),
- m_plyrParent.fRthmStatusArg());
- rm.bCadence = m_pcmlParent.bDoCadence();
- rm.pvCoherence = m_pcmlParent.pvGetCohesion();
-
- // See if the rhythm says it's time for a note:
- CRhythm rthm = rthmGetRhythm();
- double fPos = rthm.fPosition(iCurrBeatNum, rm);
- if (fPos <= 0) {
- return null;
- }
-
- int bst;
- int iDuration = 0;
- bst = rthm.bstGetBeatStatus(iCurrBeatNum, rm, iDuration);
- iDuration = rthm.bogus_piDuration;
- if (bst == BST_NO_NOTE)
- return null;
-
- // Find a tentative note. Either by copying or generating:
- boolean bCopy = false;
- if (plm!=null && plm.pCopyLine!=null) {
- int iCopyLen = plm.pCopyLine.iGetNumNotesPlayed();
- if (iCopyLen > m_iNumNotesPlayed) {
- if (plm.iCopyIndex >= iCopyLen/2) {
- if (m_iNumNotesPlayed <= plm.iCopyIndex)
- bCopy = true;
- } else if (plm.iCopyIndex <= m_iNumNotesPlayed)
- bCopy = true;
- }
- }
- if (bCopy)
- m_pvCenterNoteNum = pvCopyLine(plm);
- else m_pvCenterNoteNum = pvGenerate(m_pvCenterNoteNum,
- iDuration*10/rthm.iAveDuration());
-
- // Ok, we have a tentative note. Now see if we want to
- // tweak it:
- if (rthm.bLastNote(iCurrBeatNum, rm))
- { // Final note of line, so make it coherent:
- int kpRound = m_pcmlParent.bDoCadence() ?
- KP_ROOT : KP_PRIMARY;
- m_pvCenterNoteNum = (char)sclGetScale().iRoundNoteNum(
- m_pvCenterNoteNum, kpRound, pvGetKey());
- //tw.spr("%x Last %d: %.2f\n", this, iCurrBeatNum,
- // rthm.fPosition(iCurrBeatNum, rm));
- } else
- { if (plm!=null && plm.bContrast)
- m_pvCenterNoteNum = pvContrast(m_pvCenterNoteNum);
- else if (m_plyrParent.bMatchChord())
- m_pvCenterNoteNum = pvMatchChord(m_pvCenterNoteNum);
- }
-
- if (m_pvCenterNoteNum < 0)
- m_pvCenterNoteNum = 0;
- else if (m_pvCenterNoteNum > 127)
- m_pvCenterNoteNum = 127;
- AppendPlayedNote(iCurrBeatNum, m_pvCenterNoteNum, bst, iDuration);
- assert(iDuration > 0 && iDuration < 1000);
- CSection sec = m_pcmlParent.m_pstzParent.m_psecParent;
- assert(sec.sm_iNumActiveNotes != sec.MAX_ACTIVE_NOTES);
- sec.sm_arrNotesActive[sec.sm_iNumActiveNotes] =
- (m_arrpNotesPlayed[m_iNumNotesPlayed-1]);
- sec.sm_iNumActiveNotes++;
- return m_arrpNotesPlayed[m_iNumNotesPlayed-1];
- }
-
- //-------------------------------------
-
- public CNote pNoteToEnd (int iCurrBeatNum)
- {
- CSection sec = m_pcmlParent.m_pstzParent.m_psecParent;
- for (int C=0; C<sec.sm_iNumActiveNotes; C++) {
- CNote pNote = sec.sm_arrNotesActive[C];
- if (pNote.iBeatNum + pNote.iDuration <= iCurrBeatNum) {
- // First check to see if a duplicate of this note will be on.
- // If so, then delay this note off.
- boolean bWait = false;
- for (int i=0; i<sec.sm_iNumActiveNotes; i++) {
- CNote pNote2 = sec.sm_arrNotesActive[i];
- if (pNote2.iNoteNum == pNote.iNoteNum &&
- pNote2.iBeatNum + pNote2.iDuration > iCurrBeatNum &&
- pNote2.pvInstrument == pNote.pvInstrument) {
- bWait = true;
- pNote.iDuration = pNote2.iBeatNum + pNote2.iDuration
- - pNote.iBeatNum;
- }
- }
- if (bWait)
- continue;
-
- // Otherwise, confirm this note off.
- sec.sm_iNumActiveNotes--;
- if (C != sec.sm_iNumActiveNotes) {
- CNote noteTemp = sec.sm_arrNotesActive[C];
- sec.sm_arrNotesActive[C] = sec.sm_arrNotesActive[sec.sm_iNumActiveNotes];
- // Put dead note at end temporarily so we can point at it.
- sec.sm_arrNotesActive[sec.sm_iNumActiveNotes] = noteTemp;
- }
- //TRACE("%d[%d]=%d ", sec.sm_iNumActiveNotes, C, sec.sm_arrNotesActive[0].iBeatNum);
- return sec.sm_arrNotesActive[sec.sm_iNumActiveNotes];
- }
- }
- if (sec.sm_iNumActiveNotes*2 >= sec.MAX_ACTIVE_NOTES) {
- sec.sm_iNumActiveNotes--;
- return sec.sm_arrNotesActive[sec.sm_iNumActiveNotes];
- }
- return null;
- }
-
- //-------------------------------------
- public boolean bDonePlaying (int iCurrBeatNum)
- { if (!m_plyrParent.bActive()) return true;
- CRthmMods rm = new CRthmMods(m_plyrParent.rymodRthmStatus(),
- m_plyrParent.fRthmStatusArg());
- rm.bCadence = m_pcmlParent.bDoCadence();
- rm.pvCoherence = m_pcmlParent.pvGetCohesion();
- return (rthmGetRhythm().iOutside(iCurrBeatNum, rm) > 0);
- }
-
- public CRhythm rthmGetRhythm () { return m_plyrParent.pRhythm(); }
- public CScale sclGetScale() { return m_plyrParent.Scale(); }
-
- public char pvGetCenterNote () { return m_pvCenterNoteNum; }
- public void SetCenterNote (char pvNoteNum)
- { m_pvCenterNoteNum = pvNoteNum; }
-
- public int iGetNumNotesPlayed () { return m_iNumNotesPlayed; }
- public CNote pGetPlayedNote (int index)
- { assert(0<=index && index<m_iNumNotesPlayed);
- return m_arrpNotesPlayed[index];
- }
-
- public char pvGetKey ()
- { return m_pcmlParent.pvGetKey(); }
-
- // Construction/Destruction
- //-------------------------------------
- CMusicLine (CCompoundMusicLine pcmlParent,
- CLayer plyrParent)
- { m_pcmlParent=pcmlParent;
- m_plyrParent=plyrParent;
- m_pvCenterNoteNum=MID_C;
- m_arrpNotesPlayed=null; m_iNumNotesPlayed=0;
- m_iNumNotesAllocated=0;
- }
-
- // Implementation
- //-------------------------------------
- void AppendPlayedNote (int iBeatNum, int iNoteNum,
- int bstStress, int iDuration)
- {
- if (m_iNumNotesPlayed == m_iNumNotesAllocated)
- {
- m_iNumNotesAllocated += 10;
- CNote[] temp = m_arrpNotesPlayed;
- m_arrpNotesPlayed = new CNote[m_iNumNotesAllocated];
- for(int C=0; C<m_iNumNotesAllocated-10; C++)
- m_arrpNotesPlayed[C] = temp[C];
- }
- m_iNumNotesPlayed++;
- m_arrpNotesPlayed[m_iNumNotesPlayed-1] = new CNote();
- m_arrpNotesPlayed[m_iNumNotesPlayed-1].iBeatNum = iBeatNum;
- m_arrpNotesPlayed[m_iNumNotesPlayed-1].iNoteNum = iNoteNum;
- m_arrpNotesPlayed[m_iNumNotesPlayed-1].bstStress = bstStress;
- m_arrpNotesPlayed[m_iNumNotesPlayed-1].iDuration = iDuration;
- m_arrpNotesPlayed[m_iNumNotesPlayed-1].pvInstrument =
- m_plyrParent.pvInstrument();
- }
- //-------------------------------------
- // Breaking up pNoteToPlay to modular pieces:
- char pvCopyLine (CLineMods plm)
- { int iOldNoteNum = plm.pCopyLine.
- pGetPlayedNote(m_iNumNotesPlayed).iNoteNum;
- int kp = (int)(KP_CHROMATIC -
- (int)((double)(rand()%100)/100.0 +
- (double)(m_plyrParent.pvConsonance()) * 4.0 / 128.0));
- return (char)sclGetScale().iRoundNoteNum(iOldNoteNum + plm.iCLOffset,
- kp, pvGetKey());
- }
-
- //-------------------------------------
- char pvGenerate (char pvRef, int iNoteLen)
- { int rnd1 = rand(), rnd2 = rand();
- int kp = (int)(KP_CHROMATIC -
- (int)((double)(rnd1%100)/100.0 +
- (double)(m_plyrParent.pvConsonance()) * 4.0 / 128.0));
- if (iNoteLen > 20 && kp > KP_PRIMARY && mod(rnd1^rnd2,2)!=0)
- kp = (int)(kp-1);
- double fRand = 7.0 / (double)(1 + mod(rnd2,7));
- int ret = (int)(mod(rnd1^rnd2,128) > m_plyrParent.pvDirection() ?
- pvRef-fRand-.5 : pvRef+fRand+.5);
- assert(null!=m_plyrParent);
- assert(null!=sclGetScale());
- return (char)sclGetScale().iRoundNoteNum(ret, kp, pvGetKey());
- }
-
- //-------------------------------------
- char pvContrast (char pvRef)
- { int kpRound = mod(rand(),3)!=0 ? KP_SECONDARY :
- KP_PRIMARY; // Assuming there ARE 2ndary notes!
- return (char) sclGetScale().iRoundNoteNum(pvRef, kpRound, pvGetKey());
- }
- //-------------------------------------
- char pvMatchChord (char pvCurrNoteNum)
- { // Find the last melodic note that was played:
- CMusicLine pmlnMelody = m_pcmlParent.pmlnGetLine(0);
- if (pmlnMelody != null)
- { int iPrevMelIndex = pmlnMelody.iGetNumNotesPlayed() - 1;
- if (iPrevMelIndex >= 0)
- { CNote pnotePrevMel =
- pmlnMelody.pGetPlayedNote(iPrevMelIndex);
- // Find nearest note with same int:
- return (char) sclGetScale().iMatchNearestChord(
- pvCurrNoteNum, sclGetScale().kpGetPriority(
- pnotePrevMel.iNoteNum, pvGetKey()), pvGetKey());
- }
- }
- return pvCurrNoteNum;
- }
-
- } // end CMusicLine
-