14 #include "MusicStringParser.h"
15 #include "ChannelPressure.h"
20 #include "PitchBend.h"
21 #include "PolyphonicPressure.h"
23 #include "TimeToken.h"
50 #define Verbose(x) { MString _str; _str << x; MusicStringParser::Trace(_str); }
55 #define Warning(x) { MString _str; _str << x; MusicStringParser::Trace(_str); }
62 inline int LoadValueFromString(
const TCHAR* sz, T* pRetVal)
64 assert(_T(
"LoadValueFromString called with Unknown Type") == NULL);
72 inline int LoadIntegralValueFromString(
const TCHAR* sz, T* pRetVal)
76 const TCHAR* psz = sz;
78 while( *psz >= _T(
'0') && *psz <= _T(
'9'))
80 nVal = (nVal * 10) + (*psz - _T(
'0'));
84 if(psz != sz) *pRetVal = nVal;
86 return (
int)(psz - sz);
90 inline int LoadValueFromString(
const TCHAR* sz,
unsigned char* pRetVal)
92 return LoadIntegralValueFromString(sz, pRetVal);
96 inline int LoadValueFromString(
const TCHAR* sz,
unsigned short* pRetVal)
98 return LoadIntegralValueFromString(sz, pRetVal);
102 inline int LoadValueFromString(
const TCHAR* sz,
unsigned long* pRetVal)
104 return LoadIntegralValueFromString(sz, pRetVal);
108 inline int LoadValueFromString(
const TCHAR* sz,
double* pRetVal)
112 const TCHAR* psz = sz;
114 while(*psz >= _T(
'0') && *psz <= _T(
'9'))
116 nVal = (nVal * 10) + (*psz - _T(
'0'));
122 double nFracIndex = 10;
124 while(*psz >= _T(
'0') && *psz <= _T(
'9'))
126 nVal = nVal + ((*psz - _T(
'0')) / nFracIndex);
132 if(psz != sz) *pRetVal = nVal;
134 return (
int)(psz - sz);
137 inline bool IsOneOf(
const TCHAR ch,
const TCHAR* chrArr)
139 return _tcschr(chrArr, ch) != NULL;
142 inline void EatWhiteSpace(
const TCHAR* & psz,
const TCHAR* chWhiteSpaces = _T(
" \t\n\r"))
144 if(psz)
while(*psz && IsOneOf(*psz, chWhiteSpaces)) psz++;
147 inline void EatComments(
const TCHAR* & psz)
149 if(psz && *psz == _T(
'/'))
151 const TCHAR* pchEndDelimiter = NULL;
int nSkipLen=0;
154 case _T(
'*'): pchEndDelimiter = _T(
"*/"); nSkipLen = 2;
break;
155 case _T(
'/'): pchEndDelimiter = _T(
"\n"); nSkipLen = 1;
break;
158 const TCHAR* pszEndComment = _tcsstr(psz+2, pchEndDelimiter);
160 psz = pszEndComment + nSkipLen;
166 inline TCHAR* CreateToken(
const TCHAR* psz,
int& nTokenLen,
const TCHAR* szDelim = _T(
" \t\n\r"))
171 const TCHAR* pszStart = psz;
172 while(*psz && !IsOneOf(*psz, szDelim)) psz++;
174 int nLen = (int)(psz - pszStart);
175 TCHAR* pszNewCopy =
new TCHAR[nLen + 4];
176 memset(pszNewCopy, 0,
sizeof(TCHAR) * (nLen+4));
178 _tcsncpy(pszNewCopy, pszStart, nLen);
190 if(szTokens == NULL)
return true;
192 bool bNonContinuableErrorOccured =
false;
194 int nTokenLen, nReadLen;
195 const TCHAR* psz = szTokens;
205 nTokenLen=0, nReadLen=0;
207 TCHAR* pszToken = CreateToken(psz, nTokenLen);
209 if(nTokenLen <= 0 || pszToken == NULL) { bNonContinuableErrorOccured= (pszToken==NULL);
break;}
211 while(nReadLen < nTokenLen)
213 int nLen =
ParseToken(pszToken, &bNonContinuableErrorOccured);
214 if(-1 == nLen &&
true == bNonContinuableErrorOccured)
220 psz = psz + nReadLen;
222 }
while(*psz && !bNonContinuableErrorOccured);
224 return !bNonContinuableErrorOccured;
229 bool bNonContinuableErrorOccured =
false;
int nLen = 0;
231 TCHAR* szUppercaseToken = _tcsupr(szToken);
233 Verbose(_T(
"MusicStringParser::ParseToken: ") << szUppercaseToken);
235 switch(szUppercaseToken[0])
239 case TOKEN_DOUBLESPEED_START: nLen = ParseSpeedModulatorToken(szUppercaseToken, &bNonContinuableErrorOccured);
break;
240 case TOKEN_START_VOICE: nLen = ParseVoiceToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
241 case TOKEN_START_TEMPO: nLen = ParseTempoToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
242 case TOKEN_START_INSTRUMENT: nLen = ParseInstrumentToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
243 case TOKEN_START_LAYER: nLen = ParseLayerToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
244 case TOKEN_START_KEYSIGNATURE: nLen = ParseKeySignatureToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
245 case TOKEN_START_CONTROLLER: nLen = ParseControllerToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
246 case TOKEN_START_TIME: nLen = ParseTimeToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
247 case TOKEN_START_KEYPRESSURE: nLen = ParseKeyPressureToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
249 case TOKEN_START_PITCHBEND: nLen = ParsePitchBendToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
250 case TOKEN_START_MEASURE: nLen = ParseMeasureToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
251 case TOKEN_START_DICTIONARY: nLen = ParseDictionaryToken(szUppercaseToken+1, &bNonContinuableErrorOccured) + 1;
break;
252 case TOKEN_START_NOTE: nLen = ParseNoteToken(szUppercaseToken, &bNonContinuableErrorOccured);
break;
253 default: nLen = ParseNoteToken(szUppercaseToken, &bNonContinuableErrorOccured);
break;
256 if(pbNonContinuableErrorOccured != NULL)
257 *pbNonContinuableErrorOccured = bNonContinuableErrorOccured;
262 int MusicStringParser::ParsePitchBendToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
264 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned int nVal = 0;
267 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
271 if(*szToken == _T(
','))
273 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nHighVal = 0;
276 if(nLen2 == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
279 PitchBend pbObj((
unsigned char) nVal, (
unsigned char) nHighVal);
286 PitchBend pbObj((
unsigned char)(nVal % 128), (
unsigned char)(nVal / 128));
294 int MusicStringParser::ParseSpeedModulatorToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
296 TCHAR* pszToken = szToken;
298 unsigned short nSpeed = m_KeySig.
Speed();
307 if(nSpeed > 6 || nSpeed <= 0)
310 str << _T(
"Speed ") << nSpeed << _T(
" is beyond the range [1, 6]");
318 m_KeySig.
Speed() = nSpeed;
320 Verbose(_T(
"MusicStringParser::ParseSpeedModulatorToken Speed = ") << m_KeySig.
Speed());
325 int MusicStringParser::ParseVoiceToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
327 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nVoice = 0;
330 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
333 Verbose(_T(
"MusicStringParser::ParseVoiceToken: Voice = ") << nVoice);
338 str << _T(
"Voice ") << nVoice << _T(
" is beyond the range [0, 15]");
343 Voice voiceObj((
unsigned char) nVoice);
352 int MusicStringParser::ParseTempoToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
354 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nTempo = 0;
357 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
360 Verbose(_T(
"MusicStringParser::ParseTempoToken: Tempo = ") << nTempo);
362 Tempo tempoObj(nTempo);
371 int MusicStringParser::ParseTimeToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
373 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned long nTime = 0;
376 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
379 Verbose(_T(
"MusicStringParser::ParseTimeToken: Time = ") << nTime);
390 int MusicStringParser::ParseChannelPressureToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
392 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nPressure = 0;
395 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
398 Verbose(_T(
"MusicStringParser::ParseChannelPressureToken: Pressure = ") << nPressure);
400 ChannelPressure cpObj((
unsigned char) nPressure);
414 int MusicStringParser::ParseInstrumentToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
416 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nInstrument = 0;
419 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
422 Verbose(_T(
"MusicStringParser::ParseInstrumentToken: Instrument = ") << nInstrument);
424 Instrument instrumentObj((
unsigned char) nInstrument);
439 int MusicStringParser::ParseKeyPressureToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
445 int nLen = ParseNoteRoot(szToken, ctx);
446 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
447 szToken += nLen; nReadLen += nLen;
449 nLen = ParseNoteOctave(szToken, ctx);
450 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
451 szToken += nLen; nReadLen += nLen;
453 if(ComputeNoteValue(ctx) == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
455 TCHAR* pszPressure = szToken;
456 while(*pszPressure != _T(
'\0') && *pszPressure == _T(
',')) { pszPressure++; nReadLen++; }
458 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nKeyPressure = 0;
462 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
465 Verbose(_T(
"MusicStringParser::ParseKeyPressureToken: Key = ") << ctx.noteNumber <<
" Pressure = " << nKeyPressure);
467 PolyphonicPressure ppObj((
unsigned char) ctx.noteNumber, (
unsigned char) nKeyPressure);
477 int MusicStringParser::ParseLayerToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
479 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nLayer = 0;
482 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
485 Verbose(_T(
"MusicStringParser::ParseLayerToken: Layer = ") << nLayer);
487 Layer layerObj((
unsigned char) nLayer);
520 int MusicStringParser::ParseKeySignatureToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
522 bool bSuccess = *pbNonContinuableErrorOccured =
false;
unsigned short nValue = 0;
525 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
530 nValue = nValue - 128;
532 if(nValue > 72 || nValue <= 0)
535 str << _T(
"KeySignature ") << nValue << _T(
" is beyond the range [0~14 / 64~78 / 129~200]");
537 nValue = KeySignature::DEFAULT_RAGAM;
540 Verbose(_T(
" Mela = ") << nValue);
548 KeySignature::Scale bScale = ((nValue >= 64) ? KeySignature::MAJOR_SCALE : KeySignature::MINOR_SCALE);
550 if(nValue >= 64) nValue = nValue - 64;
552 Verbose(_T(
" KeySignature = ") << nValue <<
553 _T(
" Scale = ") << (bScale == KeySignature::MAJOR_SCALE ? _T(
"Major") : _T(
"Minor")) );
558 str << _T(
"KeySignature ") << nValue << _T(
" is beyond the range [0~14 / 64~78 / 129~200]");
560 nValue = KeySignature::DEFAULT_KEY;
563 KeySignature keyObj(nValue > 7 ? (7-nValue) : nValue, bScale);
573 if(m_KeySig.
GetMode() != KeySignature::CARNATIC)
return 0;
578 szToken += nLen;
unsigned short nTalam = m_KeySig.
GetTalam();
579 if(szToken[0] == _T(
'T'))
582 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return false; }
588 str << _T(
"Talam ") << nTalam << _T(
" is beyond the range [0 ~ 35]");
595 Verbose(_T(
" Talam = ") << nTalam);
597 else { nLen = 0; Warning(_T(
" No Talam Specified !! Using Talam: ") << nTalam); }
602 szToken += nLen;
unsigned short nSpeed = m_KeySig.
Speed();
603 if(szToken[0] == _T(
'S'))
606 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
612 str << _T(
"Speed ") << nSpeed << _T(
" is beyond the range [1 ~ 6]");
614 nSpeed = m_KeySig.
Speed();
619 Verbose(_T(
" Speed = ") << nSpeed);
621 else { Warning(_T(
" No Speed Specified !! Using Speed: ") << nSpeed ); }
623 m_KeySig.
Speed() = nSpeed;
635 int MusicStringParser::ParseControllerToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
637 TCHAR* pszAssignSymbol = _tcschr(szToken, ASSIGNMENT_SYMBOL);
638 if(pszAssignSymbol == NULL)
640 MString str(ASSIGNMENT_SYMBOL + MString(_T(
" Symbol Not found")));
645 *pszAssignSymbol = _T(
'\0');
647 TCHAR* pszKey = szToken;
648 TCHAR* pszValue = pszAssignSymbol + 1;
650 bool bSuccess =
false;
int nControllerIndex=-1;
int nReadLen = 0;
653 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
656 if(nControllerIndex >= 128)
658 int nControllerCoarse = nControllerIndex % 128;
659 int nControllerFine = nControllerIndex / 128;
661 int nControllerValue=0;
663 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
665 int coarseValue = (nControllerValue / 128);
666 int fineValue = (nControllerValue % 128);
668 ControllerEvent evObjCoarse((
unsigned char) nControllerCoarse, (
unsigned char) coarseValue);
671 ControllerEvent evObjFine((
unsigned char) nControllerFine, (
unsigned char) fineValue);
674 nReadLen = (int)(pszValue + nLen - szToken);
676 Verbose(_T(
"MusicStringParser::ParseControllerToken: [") << nControllerCoarse << _T(
"]=") + coarseValue);
677 Verbose(_T(
"MusicStringParser::ParseControllerToken: [") << nControllerFine << _T(
"]=") << fineValue);
681 unsigned short nControllerValue=0;
683 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1; }
685 ControllerEvent evObj((
unsigned char) nControllerIndex, (
unsigned char) nControllerValue);
688 nReadLen = (int)(pszValue + nLen - szToken);
690 Verbose(_T(
"MusicStringParser::ParseControllerToken: [") << pszKey << _T(
"]=") << pszValue);
698 int MusicStringParser::ParseMeasureToken(TCHAR* szToken,
bool* )
703 Verbose(_T(
"MusicStringParser::ParseMeasureToken"));
708 int MusicStringParser::ParseDictionaryToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
710 TCHAR* pszAssignSymbol = _tcschr(szToken, ASSIGNMENT_SYMBOL);
711 if(pszAssignSymbol == NULL)
714 str << ASSIGNMENT_SYMBOL << _T(
" Symbol Not found");
719 *pszAssignSymbol = _T(
'\0');
721 const TCHAR* pszKey = szToken;
722 const TCHAR* pszValue = pszAssignSymbol + 1;
724 m_Dictionary[pszKey] = pszValue;
726 Verbose(_T(
"MusicStringParser::ParseDictionaryToken: Defined [") << pszKey << _T(
"]=") << pszValue);
728 return (
int) (_tcslen(pszKey) + _tcslen(pszValue) + 1);
733 int MusicStringParser::ParseNoteToken(TCHAR* szToken,
bool* pbNonContinuableErrorOccured)
737 int nLen = 0, nReadLen = 0;
739 while(ctx.existsAnotherNote && *szToken)
741 Verbose(_T(
"MusicStringParser::ParseNote: ") << szToken);
743 DecideSequentialOrParallel(ctx);
745 nLen = ParseNoteRoot(szToken, ctx);
746 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
747 szToken += nLen; nReadLen += nLen;
749 nLen = ParseNoteOctave(szToken, ctx);
750 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
751 szToken += nLen; nReadLen += nLen;
753 nLen = ParseNoteChord(szToken, ctx);
754 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
755 szToken += nLen; nReadLen += nLen;
757 if(ComputeNoteValue(ctx) == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
759 nLen = ParseNoteChordInversion(szToken, ctx);
760 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
761 szToken += nLen; nReadLen += nLen;
763 nLen = ParseNoteDuration(szToken, ctx);
764 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
765 szToken += nLen; nReadLen += nLen;
767 nLen = ParseNoteVelocity(szToken, ctx);
768 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
769 szToken += nLen; nReadLen += nLen;
771 nLen = ParseNoteConnector(szToken, ctx);
772 if(nLen == -1) { *pbNonContinuableErrorOccured =
true;
return -1;}
773 szToken += nLen; nReadLen += nLen;
775 RaiseNoteEvents(ctx);
786 void MusicStringParser::DecideSequentialOrParallel(NoteContext& ctx)
790 if(ctx.anotherIsSequential)
793 Verbose(_T(
"About to read a sequential Note ..."));
795 if(ctx.anotherIsParallel)
798 Verbose(_T(
"About to read a parallel Note ..."));
809 int MusicStringParser::ParseNoteRoot(TCHAR* szToken, NoteContext& ctx)
813 case MACRO_START :
return ParseNumericNote(szToken, ctx);
816 Verbose(_T(
"This Note is a Rest"));
823 Verbose(_T(
"This is a Rest note for Two swara durations"));
830 if(m_KeySig.
GetMode() == KeySignature::WESTERN)
832 Verbose(_T(
"This Note is a Rest"));
834 ctx.isRest =
true;
return 1;
840 return ParseLetterNote(szToken, ctx);
845 int MusicStringParser::ParseNumericNote(TCHAR* szToken, NoteContext& ctx)
847 bool bSuccess =
false;
unsigned short nNoteNumber=0;
850 if(nLen == -1)
return -1;
853 ctx.isNumeric =
true;
854 ctx.noteNumber = nNoteNumber;
855 Verbose(_T(
"Numeric Note with value: ") << ctx.noteNumber);
863 int MusicStringParser::ParseRest(TCHAR* szToken, NoteContext& ctx)
865 Verbose(_T(
"This Note is a Rest"));
874 int MusicStringParser::ParseLetterNote(TCHAR* szToken, NoteContext& ctx)
876 if(m_KeySig.
GetMode() == KeySignature::CARNATIC)
878 const TCHAR* pszToken = szToken;
883 pszToken++; ctx.noteNumber = SWARA_S_Value;
884 if(pszToken[0] == _T(
'A')) { pszToken++; ctx.numSwaras = 2; }
889 pszToken++; ctx.noteNumber = SWARA_P_Value;
890 if(pszToken[0] == _T(
'A')) { pszToken++; ctx.numSwaras = 2; }
895 pszToken++; ctx.noteNumber = SWARA_M_Value;
896 if(pszToken[0] == _T(
'A')) { pszToken++; ctx.numSwaras = 2; }
897 if(pszToken[0] == _T(
'1')) { pszToken++; ctx.noteNumber = 5; ctx.isNatural =
true; }
898 else if(pszToken[0] == _T(
'2')) { pszToken++; ctx.noteNumber = 6; ctx.isNatural =
true; }
903 pszToken++; ctx.noteNumber = SWARA_R_Value;
904 if(pszToken[0] == _T(
'I')) { pszToken++; ctx.numSwaras = 2; }
905 if(pszToken[0] == _T(
'1')) { pszToken++; ctx.noteNumber = 1; ctx.isNatural =
true; }
906 else if(pszToken[0] == _T(
'2')) { pszToken++; ctx.noteNumber = 2; ctx.isNatural =
true; }
907 else if(pszToken[0] == _T(
'3')) { pszToken++; ctx.noteNumber = 3; ctx.isNatural =
true; }
912 pszToken++; ctx.noteNumber = SWARA_G_Value;
913 if(pszToken[0] == _T(
'A')) { pszToken++; ctx.numSwaras = 2; }
914 if(pszToken[0] == _T(
'1')) { pszToken++; ctx.noteNumber = 2; ctx.isNatural =
true; }
915 else if(pszToken[0] == _T(
'2')) { pszToken++; ctx.noteNumber = 3; ctx.isNatural =
true; }
916 else if(pszToken[0] == _T(
'3')) { pszToken++; ctx.noteNumber = 4; ctx.isNatural =
true; }
921 pszToken++; ctx.noteNumber = SWARA_D_Value;
922 if(pszToken[0] == _T(
'A')) { pszToken++; ctx.numSwaras = 2; }
923 if(pszToken[0] == _T(
'1')) { pszToken++; ctx.noteNumber = 8; ctx.isNatural =
true; }
924 else if(pszToken[0] == _T(
'2')) { pszToken++; ctx.noteNumber = 9; ctx.isNatural =
true; }
925 else if(pszToken[0] == _T(
'3')) { pszToken++; ctx.noteNumber = 10; ctx.isNatural =
true; }
930 pszToken++; ctx.noteNumber = SWARA_N_Value;
931 if(pszToken[0] == _T(
'I')) { pszToken++; ctx.numSwaras = 2; }
932 if(pszToken[0] == _T(
'1')) { pszToken++; ctx.noteNumber = 9; ctx.isNatural =
true; }
933 else if(pszToken[0] == _T(
'2')) { pszToken++; ctx.noteNumber = 10; ctx.isNatural =
true; }
934 else if(pszToken[0] == _T(
'3')) { pszToken++; ctx.noteNumber = 11; ctx.isNatural =
true; }
941 str << _T(
"Invalid Note: ") << pszToken[0];
946 Verbose(_T(
"Note number within octave: ") << ctx.noteNumber);
948 return (
int)(pszToken - szToken);
954 case NOTE_C: ctx.noteNumber = NOTE_C_Value;
break;
955 case NOTE_D: ctx.noteNumber = NOTE_D_Value;
break;
956 case NOTE_E: ctx.noteNumber = NOTE_E_Value;
break;
957 case NOTE_F: ctx.noteNumber = NOTE_F_Value;
break;
958 case NOTE_G: ctx.noteNumber = NOTE_G_Value;
break;
959 case NOTE_A: ctx.noteNumber = NOTE_A_Value;
break;
960 case NOTE_B: ctx.noteNumber = NOTE_B_Value;
break;
965 str << _T(
"Invalid Note: ") << szToken[0];
971 bool bCheckForModifiers =
true;
const TCHAR* pszSymbol = szToken + 1;
972 while(bCheckForModifiers)
980 default: bCheckForModifiers = false;
break;
984 Verbose(_T(
"Note number within octave: ") << ctx.noteNumber);
986 return (
int)(pszSymbol - szToken);
990 int MusicStringParser::ParseNoteOctave(TCHAR* szToken, NoteContext& ctx)
993 if(ctx.isRest || ctx.isNumeric)
return 0;
995 ctx.octaveNumber = ctx.isChord ? this->m_nDefChordOctave : this->m_nDefNoteOctave;
999 if(m_KeySig.
GetMode() == KeySignature::CARNATIC)
1010 bool bCheckForModifiers =
true;
const TCHAR* pszSymbol = szToken;
1011 while(bCheckForModifiers)
1013 switch(pszSymbol[0])
1017 default: bCheckForModifiers =
false;
break;
1020 nLen = (int)(pszSymbol - szToken);
1029 bool bSuccess =
false;
unsigned short nOctave=0;
1032 if(nLen == -1)
return -1;
1034 ctx.octaveNumber = nOctave;
1037 if(ctx.octaveNumber < 0 || ctx.octaveNumber > 10)
1040 str << _T(
"Octave ") << ctx.octaveNumber << _T(
" is beyond the range [0, 10]");
1043 if(ctx.octaveNumber < 0) ctx.octaveNumber = 0;
1044 else if(ctx.octaveNumber > 10) ctx.octaveNumber = 10;
1047 Verbose( _T(
"Octave Number: ") << ctx.octaveNumber);
1052 int MusicStringParser::ParseNoteChord(TCHAR* szToken, NoteContext& ctx)
1056 Verbose(_T(
"ParseNoteChord: Skipping Chords inspection for Rest Note..."));
1060 unsigned int nChordNameLen = m_pChords != NULL ?
1063 if(nChordNameLen > 0)
1066 Verbose(_T(
"ParseNoteChord: Found Chord ") << ctx.chord.szChordName);
1069 return nChordNameLen;
1072 int MusicStringParser::ParseNoteChordInversion(TCHAR* szToken, NoteContext& ctx)
1074 if(ctx.isChord ==
false)
1076 Verbose(_T(
"ParseNoteChordInversion: Skipping Chord Inversions..."));
1080 TCHAR* pszToken = szToken;
1082 int nInversionCount = 0;
1083 int nInversionRootNote = -1;
1084 int nInversionOctave = -1;
1085 bool bCheckForInversion =
true;
1087 while(bCheckForInversion && *pszToken != _T(
'\0'))
1091 case _T(
'^'): pszToken++; nInversionCount++;
break;
1092 case _T(
'C'): pszToken++; nInversionRootNote = NOTE_C_Value;
break;
1093 case _T(
'D'): pszToken++; nInversionRootNote = NOTE_D_Value;
break;
1094 case _T(
'E'): pszToken++; nInversionRootNote = NOTE_E_Value;
break;
1095 case _T(
'F'): pszToken++; nInversionRootNote = NOTE_F_Value;
break;
1096 case _T(
'G'): pszToken++; nInversionRootNote = NOTE_G_Value;
break;
1097 case _T(
'A'): pszToken++; nInversionRootNote = NOTE_A_Value;
break;
1098 case _T(
'B'): pszToken++;
1099 if(nInversionRootNote == -1) nInversionRootNote = NOTE_B_Value;
1100 else nInversionRootNote--;
1102 case _T(
'#'): pszToken++; nInversionRootNote++;
break;
1103 case _T(
'1'): pszToken++; nInversionOctave = 1;
break;
1104 case _T(
'2'): pszToken++; nInversionOctave = 2;
break;
1105 case _T(
'3'): pszToken++; nInversionOctave = 3;
break;
1106 case _T(
'4'): pszToken++; nInversionOctave = 4;
break;
1107 case _T(
'5'): pszToken++; nInversionOctave = 5;
break;
1108 case _T(
'6'): pszToken++; nInversionOctave = 6;
break;
1109 case _T(
'7'): pszToken++; nInversionOctave = 7;
break;
1110 case _T(
'8'): pszToken++; nInversionOctave = 8;
break;
1111 case _T(
'9'): pszToken++; nInversionOctave = 9;
break;
1112 case _T(
'0'): pszToken++;
1113 if(nInversionOctave == -1) nInversionOctave = 0;
1114 else nInversionOctave *= 10;
break;
1117 unsigned short nRoot = 0;
bool bSuccess =
false;
1119 if(nLen == -1) {
return -1; }
1122 nInversionRootNote = nRoot;
1128 default: bCheckForInversion =
false;
break;
1133 if(nInversionCount > 0)
1135 if(nInversionRootNote == -1)
1137 Verbose(_T(
"Chord Inversion based on count: ") << nInversionCount);
1139 ctx.noteNumber += 12;
1140 for(
int i = nInversionCount -1; i < ctx.chord.nIntervalCount; ++i)
1142 Verbose(_T(
" Inverting ") << ctx.chord.Intervals[i] << _T(
" to be ") << (ctx.chord.Intervals[i] - 12));
1143 ctx.chord.Intervals[i] -= 12;
1148 if(nInversionOctave != -1)
1149 nInversionRootNote += (nInversionOctave * 12);
1150 else if(nInversionRootNote < 12)
1152 int nCurOctave = ctx.noteNumber / 12;
1153 nInversionRootNote += (nCurOctave * 12);
1157 Verbose(_T(
"Chord Inversion is based on note: ") << nInversionRootNote);
1159 if((nInversionRootNote > ctx.noteNumber + ctx.chord.Intervals[ctx.chord.nIntervalCount -1])
1160 || (nInversionRootNote < ctx.noteNumber))
1165 Verbose(_T(
" Adjusted the inversion root note to be ") << ctx.noteNumber <<_T(
" and continuing..."));
1167 nInversionRootNote = ctx.noteNumber;
1170 Verbose(_T(
" Inverting ") << ctx.noteNumber << _T(
" to be ") << (ctx.noteNumber + 12));
1171 ctx.noteNumber += 12;
1173 for(
int i=0; i < ctx.chord.nIntervalCount; ++ i)
1175 if(ctx.noteNumber + ctx.chord.Intervals[i] >= nInversionRootNote + 12)
1177 Verbose(_T(
" Inverting ") << ctx.chord.Intervals[i] << _T(
" to be ") << (ctx.chord.Intervals[i] - 12));
1178 ctx.chord.Intervals[i] -= 12;
1184 return (
int)(pszToken - szToken);
1187 int MusicStringParser::ComputeNoteValue(NoteContext& ctx)
1189 if(ctx.isRest)
return 0;
1202 int nKeySig = m_KeySig.
GetKey();
1204 if(m_KeySig.
GetMode() == KeySignature::CARNATIC)
1206 if(!ctx.isNatural && !ctx.isNumeric)
1211 if ((nKeySig != 0) && (!ctx.isNatural) && (!ctx.isNumeric))
1213 if ((nKeySig <= -1) && (ctx.noteNumber == 11)) ctx.noteNumber = 10;
1214 if ((nKeySig <= -2) && (ctx.noteNumber == 4)) ctx.noteNumber = 3;
1215 if ((nKeySig <= -3) && (ctx.noteNumber == 9)) ctx.noteNumber = 8;
1216 if ((nKeySig <= -4) && (ctx.noteNumber == 2)) ctx.noteNumber = 1;
1217 if ((nKeySig <= -5) && (ctx.noteNumber == 7)) ctx.noteNumber = 6;
1218 if ((nKeySig <= -6) && (ctx.noteNumber == 0)) { ctx.noteNumber = 11; ctx.octaveNumber--; }
1219 if ((nKeySig <= -7) && (ctx.noteNumber == 5)) ctx.noteNumber = 4;
1220 if ((nKeySig >= +1) && (ctx.noteNumber == 5)) ctx.noteNumber = 6;
1221 if ((nKeySig >= +2) && (ctx.noteNumber == 0)) ctx.noteNumber = 1;
1222 if ((nKeySig >= +3) && (ctx.noteNumber == 7)) ctx.noteNumber = 8;
1223 if ((nKeySig >= +4) && (ctx.noteNumber == 2)) ctx.noteNumber = 3;
1224 if ((nKeySig >= +5) && (ctx.noteNumber == 9)) ctx.noteNumber = 10;
1225 if ((nKeySig >= +6) && (ctx.noteNumber == 4)) ctx.noteNumber = 5;
1226 if ((nKeySig >= +7) && (ctx.noteNumber == 11)) { ctx.noteNumber = 0; ctx.octaveNumber++; }
1230 Verbose(_T(
"After adjusting for Key, Note Number=") << ctx.noteNumber);
1234 ctx.noteNumber = (ctx.octaveNumber * 12) + ctx.noteNumber;
1236 Verbose(_T(
"Computed Note Number:") << ctx.noteNumber);
1240 if(ctx.noteNumber > 127 || ctx.noteNumber < 0)
1243 str << _T(
"Computed Note Number") << ctx.noteNumber << _T(
" is going beyond the range [0, 127]");
1247 if(ctx.noteNumber > 127)
1248 ctx.noteNumber = 127;
1249 else if(ctx.noteNumber < 0)
1252 Warning(_T(
" Adjusted the value to") << ctx.noteNumber << _T(
" and continuing..."));
1258 int MusicStringParser::ParseNoteDuration(TCHAR* szToken, NoteContext& ctx)
1260 TCHAR* pszDuration = szToken;
1262 if(m_KeySig.
GetMode() == KeySignature::WESTERN)
1266 bool bSuccess =
false;
1272 pszDuration = szToken + 1 + nLen;
1276 MString str(_T(
"Error while reading Numeric Duration Value"));
1279 pszDuration = szToken + 1;
1282 Warning(_T(
" Ignoring / and proceeding with ") << pszDuration);
1288 if(!ctx.decimalDuration)
1289 pszDuration += ParseLetterDuration(pszDuration, ctx);
1292 if(m_KeySig.
GetMode() == KeySignature::CARNATIC)
1294 ctx.decimalDuration = ctx.numSwaras * 1.0f / (4.0 * pow((
double)2.0f, (
double)m_KeySig.
Speed()-1));
1298 if(ctx.decimalDuration == 0)
1299 ctx.decimalDuration = 1.0 / 4.0;
1301 Verbose(_T(
"Decimal Duration is: ") << ctx.decimalDuration);
1304 int nTupletLen = ParseTuplet(pszDuration, ctx);
1305 if(nTupletLen < 0)
return -1;
1307 ctx.duration = (long) (128.0 * ctx.decimalDuration);
1309 Verbose(_T(
"Actual Duration is: ") << ctx.duration);
1311 return (
int)(pszDuration - szToken) + nTupletLen;
1315 int MusicStringParser::ParseLetterDuration(TCHAR* szToken, NoteContext& ctx)
1317 TCHAR* pszDuration = szToken;
1319 while(*pszDuration != _T(
'\0'))
1323 if(!ctx.decimalDuration)
1324 ctx.isEndOfTie =
true;
1328 ctx.isEndOfTie =
false;
1330 ctx.isStartOfTie =
true;
1336 double nDurationNumber = 0;
1338 switch(pszDuration[0])
1351 if(nDurationNumber > 0)
1353 double durVal = 1.0/nDurationNumber;
1354 ctx.decimalDuration += durVal;
1357 ctx.decimalDuration += (durVal/2.0);
1367 return (
int)(pszDuration - szToken);
1371 int MusicStringParser::ParseTuplet(TCHAR* szToken, NoteContext& ctx)
1375 Verbose(_T(
"Scanning a Tuplet..."));
1377 TCHAR* pszTuplet = szToken + 1;
1379 double dNumerator = 2.0;
1380 double dDenominator = 3.0;
1383 if(pszTupletRatioMark != NULL)
1385 *pszTupletRatioMark = _T(
'\0');
1387 if(!LoadValueFromString(pszTuplet, &dNumerator))
1389 MString str(MString(_T(
"Error while reading Numerator of tuplet")));
1391 Warning(_T(
" Defaulting to Numerator Value: ") << dNumerator);
1394 int nLen = LoadValueFromString(pszTupletRatioMark+1, &dDenominator);
1397 MString str(_T(
"Error while reading Denominator of tuplet"));
1399 Warning(_T(
" Defaulting to Denominator Value: ") << dDenominator);
1402 pszTuplet = pszTupletRatioMark + 1 + nLen;
1405 double tupletRatio = dNumerator / dDenominator;
1407 ctx.decimalDuration *= tupletRatio;
1409 Verbose(_T(
"Tuplet Ratio is: ") << (
unsigned int)dNumerator << _T(
":") << (
unsigned int)dDenominator);
1410 Verbose(_T(
"Decimal Duration after applying Tuplet: ") << ctx.decimalDuration);
1412 return (
int)(pszTuplet - szToken);
1427 int MusicStringParser::ParseNoteVelocity(TCHAR* szToken, NoteContext& ctx)
1431 Verbose(_T(
"This is a Rest note .. Skipping the Velocities"));
1435 TCHAR* pszVelocity = szToken;
bool bAttackRead =
false;
1439 bool bAttack =
false, bDecay =
false;
1441 switch(pszVelocity[0])
1443 case NOTE_VELOCITY: bAttack = !bAttackRead; bDecay = bAttackRead; bAttackRead = bAttack;
break;
1448 Verbose(_T(
"Attack Velocity: ") << (
int)ctx.attackVelocity << _T(
" Decay Velocity: ") << (
int)ctx.decayVelocity);
1449 return (
int)(pszVelocity - szToken);
1455 bool bSuccess =
false;
unsigned short nVelocity = 0;
1458 if(nLen == -1)
return -1;
1461 if(bAttack) ctx.attackVelocity = nVelocity;
1462 if(bDecay) ctx.decayVelocity = nVelocity;
1464 else Warning(_T(
"Unable to find Attack/Decay velocity for note, while parsing: ") << szToken);
1466 pszVelocity += nLen;
1469 return (
int)(pszVelocity - szToken);
1473 int MusicStringParser::ParseNoteConnector(TCHAR* szToken, NoteContext& ctx)
1475 ctx.existsAnotherNote =
true;
1481 default: Verbose(_T(
"No Connector Notes Found in: ") << szToken);
break;
1484 ctx.existsAnotherNote =
false;
1491 void MusicStringParser::RaiseNoteEvents(NoteContext& ctx)
1495 ctx.attackVelocity = ctx.decayVelocity = 0;
1502 for(
unsigned short i=0; i < ctx.chord.nIntervalCount; ++i)
1505 noteObj.noteNumber = ctx.noteNumber + ctx.chord.Intervals[i];
1506 noteObj.duration = ctx.duration;
1507 noteObj.decimalDuration = ctx.decimalDuration;
1523 template<
typename T>
1524 int MusicStringParser::GetValueFromDictionary(
const TCHAR* szKey, T* pRetVal)
1526 DICTIONARY::const_iterator dictEntry = m_Dictionary.find(szKey);
1529 const TCHAR* pszVal = (dictEntry == m_Dictionary.end() ? szKey : (
const TCHAR*)dictEntry->second);
1533 return LoadValueFromString(pszVal, pRetVal);
1536 template<
typename T>
1537 int MusicStringParser::ParseNumber(TCHAR* szToken, T* pRetVal,
bool& bSuccess,
1538 TCHAR MacroBracketStart, TCHAR MacroBracketEnd, ErrorCode MacroReadErrorCode, ErrorCode NumberParseErrorCode)
1542 const TCHAR* pszNumberStart = szToken;
1544 if(szToken[0] == MacroBracketStart)
1546 TCHAR* pszEndBracket = _tcschr(szToken, MacroBracketEnd);
1547 if(pszEndBracket == NULL)
1550 str << _T(
"No Matching ") << MacroBracketEnd << _T(
" found for ") << MacroBracketStart;
1551 if(
Error(MacroReadErrorCode, str, szToken))
return -1;
1554 pszNumberStart = szToken+1;
1556 Warning(_T(
" Ignoring ") << MacroBracketStart);
1562 *pszEndBracket = _T(
'\0');
1564 if(
false == GetValueFromDictionary(szToken + 1, pRetVal))
1567 str << _T(
"Unable to retrieve Number from ") << (szToken + 1);
1568 if(
Error(NumberParseErrorCode, str, szToken))
return -1;
1571 Warning(_T(
" Ignoring ") << (szToken + 1));
1573 return (
int)(pszEndBracket - szToken) +1;
1579 return (
int)(pszEndBracket - szToken) +1;
1586 int nStrLen = LoadValueFromString(pszNumberStart, pRetVal);
1599 return (
int)(pszNumberStart - szToken) + nStrLen;
Specifies the start of 2x speed.
Signifies the Macro end symbol.
MACRO_END missing while parsing a Voice Macro.
MACRO_END missing while parsing a Velocity Macro.
Failure while converting/retrieving a Controller Value number.
void SetRagam(const unsigned short nRagam)
Computed Note Value is going beyond the permitted range [0, 127].
Failure while converting/retrieving a PitchBend number.
OIL::CEventT< const CParser, const Voice > evVoice
Event Raised when Parser encounters a Voice command.
Specifies a Channel pressure token.
Failure while converting/retrieving a numeric note number.
Failure while conveting/retrieving the Numerator of Tuplet fraction.
unsigned int ExtractMatchingChord(const TCHAR *szToken, ChordDef *retVal) const
Indicates a Tuplet start.
OIL::CEventT< const CParser, const PitchBend > evPitchBend
Event Raised when Parser encounters a PitchBend command.
Note Attack Velocity specifier (Obsolete. only for compatability with JFugue)
Specifies the end of 2x speed.
Failure while conveting/retrieving a Duration number.
const Talam & GetTalam() const
Returns the Talam Value. Valid only when the Mode is CARNATIC. Use GetMode() to find the Mode;...
Increments Note Shruti one level upward the Tara Sthayi.
MACRO_END missing while parsing a Speed Macro.
Signifies a Macro start symbol.
static unsigned short LookupSwaraSthanaForMela(short nSwara, unsigned short nMela)
Failure while converting/retrieving a Instrument number.
OIL::CEventT< const CParser, const Tempo > evTempo
Event Raised when Parser encounters a Tempo command.
MACRO_END missing while parsing a Key Signature Macro.
Specifies a seperator token for readability.
Specifies a Controller token.
Specifies a Instrument token.
Specifies 1.5 times the normal duration.
signed char GetKey() const
Returns the Key Signature value. Based on the Mode, Value will be in the range [-7, 7] or [1, 72]. Use GetMode() to find the Mode.
bool Parse(const TCHAR *szTokens)
No Assignment symbol found.
Specified a KeySignature beyond permitted range [0, 14] , [64, 78], [129, 200].
void SetTalam(const Talam &talam)
Failure while converting/retrieving a Speed number.
Specified a Talam beyond permitted range [0, 35].
Failure while conveting/retrieving the Denominator of Tuplet fraction.
OIL::CEventT< const CParser, const ControllerEvent > evController
Event Raised when Parser encounters a MIDI Controller Event.
Used when Duration is to be expressed as a numeric value.
Used when decorating durations for ties.
Note Attack Velocity specifier (Carnatic Mode)
Specifies a KeySignature token.
MACRO_END missing while parsing a Controller Index Macro.
Failure while conveting/retrieving an Octave macro number.
Invalid Alphabet encountering while trying to read a Note Symbol.
MACRO_END missing while parsing an Duration Macro.
Note Decay Velocity specifier.
Indicates if this is a Sequential note in a group of notes.
Specified a voice that is beyond the permitted range [0, 15].
Specifies a Rest Note of one duration.
OIL::CEventT< const CParser > evMeasure
Event Raised when Parser encounters a Measure bar.
OIL::CEventT< const CParser, const KeySignature > evKeySignature
Event Raised when Parser encounters a Key Signature command.
Declares MIDI Controller Events used in MusicStrings.
unsigned short & Speed()
Returns the current Song speed. Valid only for Carnatic Mode. Use GetMode() to verify the Mode...
Specified a Speed beyond permitted range [1, 6].
MACRO_END missing while parsing a Polyphonic Pressure Macro.
static unsigned int GetDefaultMatchingChord(const TCHAR *szToken, ChordDef *retVal)
Indicates two extra time units [Carnatic Music Only].
MACRO_END missing while parsing a numeric note.
OIL::CEventT< const CParser, const Note > evNote
Event Raised when Parser encounters a Note.
MACRO_END missing while parsing a PitchBend Macro.
Specifies a Measure token.
Specifies a Rest Note token [Western Music Only].
MACRO_END missing while parsing an Octave Macro.
Declares Instrument class.
Failure while converting/retrieving a Polyphonic Pressure number.
Mode GetMode() const
Returns if the KeySignature refers to Carnatic Mode or Western Mode.
Indicates if this is a Parallel note in a group of notes.
MACRO_END missing while parsing a Tempo Macro.
OIL::CEventT< const CParser, const ChannelPressure > evChannelPressure
Event Raised when Parser encounters a Channel Pressure command.
Specified an inversion root note that is not with in acceptable range of values.
Failure while converting/retrieving a Time number.
MACRO_END missing while parsing a Layer Macro.
Specifies a Keypressure token.
OIL::CEventT< const CParser, const PolyphonicPressure > evPolyphonicPressure
Event Raised when Parser encounters a Key Pressure command.
OIL::CEventT< const CParser, const Time > evTime
Event Raised when Parser encounters a Time command.
Specifies a Rest Note of two durations.
Indicates one extra time unit [Carnatic Music Only].
Failure while converting/retrieving a Controller Value number.
Failure while conveting/retrieving a Velocity number.
Note Parallel connector symbol.
Failure while converting/retrieving a Voice number.
Indicates the Tuplet Ratio.
Failure while converting/retrieving a Chord Inversion Root Note number.
Specified an octave that is beyond the permitted range [0, 10].
MACRO_END missing while parsing a Chord Inversion.
Declares Tempo class used in Western music.
OIL::CEventT< const CParser, const Instrument > evInstrument
Event Raised when Parser encounters an Instrument command.
Failure while converting/retrieving a Layer number.
OIL::CEventT< const CParser, const Layer > evLayer
Event Raised when Parser encounters a Layer command.
Failure while converting/retrieving a Key Signature number.
Failure while converting/retrieving a Talam number.
MACRO_END missing while parsing a Talam Macro.
Note Sequential connector symbol.
Specifies One-ThirtySecond Note.
Specifies One-Sixteenth Note.
Indicates if this is a First note in a group of notes.
Specifies One-Eight Note.
void RaiseEvent(CEventT< TEventSource, TEventHandlerArgs > *pEvent, TEventHandlerArgs *pArgs)
int ParseToken(TCHAR *szToken, bool *pbNonContinuableErrorOccured=NULL)
Decrements Note Shruti one level downward the Mandra Sthayi.
MACRO_END missing while parsing a Time Macro.
Specifies a Pitchbend token.
Specifies One-SixtyFourth Note.
virtual bool Error(ErrorCode argErrCode, const TCHAR *szTraceMsg, const TCHAR *szToken)
MACRO_END missing while parsing a Controller Index Macro.
MACRO_END missing while parsing a Instrument Macro.
Failure while converting/retrieving a Tempo number.
Specifies a Dictionary token.