Esempio n. 1
0
 internal ThemeQueueEntry()
 {
     playmode       = PsaiPlayMode.regular;
     themeId        = -1;
     startIntensity = 1.0f;
     restTimeMillis = 0;
     holdIntensity  = false;
 }
 internal ThemeQueueEntry()
 {
     playmode = PsaiPlayMode.regular;
     themeId = -1;
     startIntensity = 1.0f;
     restTimeMillis = 0;
     holdIntensity = false;
 }
Esempio n. 3
0
        private void InitMembersAfterSoundtrackHasLoaded()
        {
            m_themeQueue.Clear();
            m_fadeVoices.Clear();


            foreach (Segment segment in m_soundtrack.m_snippets.Values)
            {
                segment.audioData.filePathRelativeToProjectDir = m_platformLayer.ConvertFilePathForPlatform(segment.audioData.filePathRelativeToProjectDir);
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("converted path of segment " + segment.Name + " to " + segment.audioData.filePathRelativeToProjectDir, LogLevel.debug);
                    }
                }
                #endif
            }

            m_soundtrack.UpdateMaxPreBeatMsOfCompatibleMiddleOrBridgeSnippets();
            m_lastBasicMood = m_soundtrack.getThemeById(GetLastBasicMoodId());

            m_psaiState = PsaiState.silence;
            m_psaiStateIntended = PsaiState.silence;
            m_psaiPlayMode = PsaiPlayMode.regular;
            m_psaiPlayModeIntended = PsaiPlayMode.regular;

            m_returnToLastBasicMoodFlag = false;
            m_holdIntensity = false;

            m_nonInterruptingTriggerOfHighestPriority.themeId = -1;

            m_soundtrack.BuildAllIndirectionSequences();
        }
Esempio n. 4
0
        /** Pops and Plays the next entry in the followingThemeQueue, using the previously stored parameters
	    * for intensity, themeId and SnippetTypes. Removes the themeQueueEntry from the queue afterwards.
	    * @param immediately Play the Theme immediately
	    */ 
	    void PopAndPlayNextFollowingTheme(bool immediately)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("PopAndPlayNextFollowingTheme()  m_themeQueue.size()=");
	                sb.Append(m_themeQueue.Count);
	                sb.Append("  immediately=");
	                sb.Append(immediately);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    if (getFollowingThemeQueueEntry() != null)
		    {
			    ThemeQueueEntry tqe = getFollowingThemeQueueEntry();
			    m_psaiPlayModeIntended = tqe.playmode;
                
			    switch (m_psaiPlayModeIntended)
			    {
			    case PsaiPlayMode.regular:
				    {
					    if (tqe.restTimeMillis == 0)
					    {
						    PlayThemeNowOrAtEndOfCurrentSegment(tqe, immediately);
					    }
					    else
					    {
						    EnterRestMode(tqe.themeId, tqe.themeId);
					    }
				    }
				    break;

			    case PsaiPlayMode.cutScene:
				    {
					    PlayThemeNowOrAtEndOfCurrentSegment(tqe.themeId, tqe.startIntensity, tqe.musicDuration, immediately, tqe.holdIntensity);
				    }
				    break;

			    case PsaiPlayMode.menuMode:
				    {
					    PlayThemeNowOrAtEndOfCurrentSegment(tqe.themeId, tqe.startIntensity, tqe.musicDuration, immediately, tqe.holdIntensity);
				    }
				    break;

			    default:
				    {
				    #if !(PSAI_NOLOG)
                        if (LogLevel.errors <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("unkown PSAIPLAYMODE !", LogLevel.errors);
                        }
				    #endif
				    }
				    break;
			    }
			    removeFirstFollowingThemeQueueEntry();
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
			    {
                    if (LogLevel.errors <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("PopAndPlayNextFollowingTheme() - themeQueue is empty!");
	                    Logger.Instance.Log(sb.ToString(), LogLevel.errors);
                    }
                    //AbortWithFatalErrorMessage("FATAL INTERNAL ERROR: PopAndPlayNextFollowingTheme() - themeQueue is empty! !");
			    }
			    #endif
			
		    }
	    }
Esempio n. 5
0
        // creates a themequeue-Entry for the theme currently playing and pushes it on the theme queue stack. 
	    // If a theme change was imminent, the upcoming theme is stored instead.
	    // Used internally for entering Mode Mode and Cut Scenes
	    void PushEffectiveThemeToThemeQueue(PsaiPlayMode playModeToReturnTo)
	    {
		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("PushEffectiveThemeToThemeQueue()  playModeToReturnTo=");
	                sb.Append(playModeToReturnTo);
	                sb.Append("  m_nonInterruptingTriggerCallOfHighestPriority.themeId=");
	                sb.Append(m_nonInterruptingTriggerOfHighestPriority.themeId);
	                sb.Append("  m_currentSegmentPlaying=");                
	                if (m_currentSegmentPlaying != null)
	                {
	                    sb.Append(m_currentSegmentPlaying.Name);
	                }
	                else
	                {
	                    sb.Append("null");
	                }
	                sb.Append("  m_targetSegment=");
	                if (m_targetSegment != null)
	                {
	                    sb.Append(m_targetSegment.Name);
	                }
	                else
	                {
	                    sb.Append("null");
	                }
	
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                } 
		    }
		    #endif


            // if we switch from Rest-Mode into MenuMode, we need to remember the remaining milliseconds until we wake up from rest again
		    if (m_psaiState == PsaiState.rest)
		    {
                int restModeRemainingMillis = GetTimestampMillisElapsedSinceInitialisation() - m_timeStampRestStart;
			    m_timerWakeUpFromRest.Stop();

                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log(".. we were in Rest Mode, restModeRemainingMillis=" + restModeRemainingMillis, LogLevel.debug);
                    }
                }
                #endif

                pushThemeToThemeQueue(m_lastBasicMood.id, m_lastBasicMood.intensityAfterRest, 0, true, restModeRemainingMillis, PsaiPlayMode.regular, false);
                return;
		    }



            if (m_nonInterruptingTriggerOfHighestPriority.themeId != -1)
            {
                // we have received a non-interrupting trigger, so we pack this on the themeQueue.
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("...m_nonInterruptingTrigger was set, themeId=");
	                    sb.Append(m_nonInterruptingTriggerOfHighestPriority.themeId);
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
                }
                #endif

                Theme nonInterruptingTheme = m_soundtrack.getThemeById(m_nonInterruptingTriggerOfHighestPriority.themeId);
                pushThemeToThemeQueue(nonInterruptingTheme.id, m_nonInterruptingTriggerOfHighestPriority.startIntensity, m_nonInterruptingTriggerOfHighestPriority.musicDuration, false, 0, PsaiPlayMode.regular, false);

                // clear non-interrupting trigger call, as we would otherwise return this after the first Snippet of the interrupting Theme would have played
                m_nonInterruptingTriggerOfHighestPriority.themeId = -1;

                return;
            }



            // no trigger is pending, business as usual

            Segment effectiveSegment = GetEffectiveSegment();
            if (effectiveSegment != null)
            {

                // Special case: we have already targeted a Snippet of some other theme, or no snippet is playing right now.
                // This means we have to switch to the target Theme with the maximum music duration
                if (effectiveSegment == m_targetSegment && m_currentSegmentPlaying == null || (m_targetSegment != null && m_currentSegmentPlaying != null && m_targetSegment.ThemeId != m_currentSegmentPlaying.ThemeId))
                {
                    #if !(PSAI_NOLOG)
                    {
                        if (LogLevel.debug <= Logger.Instance.LogLevel)
                        {
	                        StringBuilder sb = new StringBuilder();
	                        sb.Append("setting targetSegment.themeId as the following Theme, storing full music duration of themeId=");
	                        sb.Append(effectiveSegment.ThemeId);
	                        Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                        }
                    }
                    #endif

                    Theme targetTheme = m_soundtrack.getThemeById(m_targetSegment.ThemeId);
                    pushThemeToThemeQueue(m_targetSegment.ThemeId, getUpcomingIntensity(), targetTheme.musicDurationGeneral, false, 0, playModeToReturnTo, m_holdIntensity);
                }
                else
                {
                    // business as usual
                    #if !(PSAI_NOLOG)
                    {
                        if (LogLevel.debug <= Logger.Instance.LogLevel)
                        {
	                        StringBuilder sb = new StringBuilder();
	                        sb.Append("pushing themeId of the Effective Segment to Theme Queue, themeId=");
	                        sb.Append(effectiveSegment.ThemeId);
	                        Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                        }
                    }
                    #endif

                    pushThemeToThemeQueue(effectiveSegment.ThemeId, getCurrentIntensity(), GetRemainingMusicDurationSecondsOfCurrentTheme(), false, 0, playModeToReturnTo, m_holdIntensity);
                }
            }
            else
            {
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append("not pushing anything to themeQueue. effectiveSnippet=");
	                    sb.Append(GetEffectiveSegment());
	                    sb.Append("  m_targetSegment=");
	                    sb.Append(m_targetSegment);
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
                }
                #endif
            }
	    }
Esempio n. 6
0
        void SetPlayMode(PsaiPlayMode playMode)
	    {
		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("SetPlayMode() ");
	                sb.Append(playMode);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    m_psaiPlayMode = playMode;
	    }
Esempio n. 7
0
	    internal PsaiResult CutSceneLeave(bool immediately, bool reset)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("CutSceneLeave()  immediately=");
	                sb.Append(immediately);
	                sb.Append("  reset=");
	                sb.Append(reset);
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append("  m_themeQueue.size()=");
	                sb2.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

		    if (m_psaiPlayMode == PsaiPlayMode.cutScene && m_psaiPlayModeIntended == PsaiPlayMode.cutScene)
		    {

			    if (reset)
			    {
				    m_themeQueue.Clear();
				    #if !(PSAI_NOLOG)
				    {
                        if (LogLevel.debug <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("m_themeQueue cleared", LogLevel.debug);
                        }
				    }
				    #endif
			    }

			    if (getFollowingThemeQueueEntry() != null)
			    {
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;
				    PopAndPlayNextFollowingTheme(immediately);
				    return PsaiResult.OK;
			    }
			    else
			    {
				    m_psaiStateIntended = PsaiState.silence;
				    m_psaiState = PsaiState.silence;
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;
				    StopMusic(immediately);
				    return PsaiResult.OK;
			    }
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("CutSceneLeave() ignored - no CutScene was active. Call CutSceneEnter() first!", LogLevel.warnings);				    
                    }
			    #endif

			    return PsaiResult.commandIgnored;
		    }
	    }
Esempio n. 8
0
	    internal PsaiResult CutSceneEnter(int themeId, float intensity)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("CutSceneEnter(), theme id=");
	                sb.Append(themeId);
	                sb.Append("  , intensity=");
	                sb.Append(intensity);
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append( "  m_themeQueue.size()=");
	                sb2.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {				    
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////


		    switch(m_psaiPlayModeIntended)		// we use 'intended' here and not m_psaiPlayMode, so immediate switches back to Cutscene after leaving will be ignored and not cause trouble
		    {
		    case PsaiPlayMode.cutScene:
			    {
				    #if !(PSAI_NOLOG)
                        if (LogLevel.warnings <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("Cutscene Mode already active - command ignored !", LogLevel.warnings);					    
                        }
				    #endif

				    return PsaiResult.commandIgnoredCutsceneActive;
			    }
			    //break;

		    case PsaiPlayMode.menuMode:
			    {
				    #if !(PSAI_NOLOG)
                        if (LogLevel.warnings <= Logger.Instance.LogLevel)
                        {
                        	Logger.Instance.Log("MenuMode active - command ignored !", LogLevel.warnings);
                        }
				    #endif

				    return PsaiResult.commandIgnoredMenuModeActive;
			    }
			    //break;

		    default:
			    {
				    PushEffectiveThemeToThemeQueue(PsaiPlayMode.regular);

                    Theme cutSceneTheme = m_soundtrack.getThemeById(themeId);
				    SetPlayMode(PsaiPlayMode.cutScene);
				    m_psaiPlayModeIntended = PsaiPlayMode.cutScene;
				    if (cutSceneTheme != null)
				    {
					    PlayThemeNowOrAtEndOfCurrentSegment(themeId, intensity, cutSceneTheme.musicDurationGeneral, true, true);
					    return PsaiResult.OK;
				    }
				    else
				    {									
					    PlayThemeNowOrAtEndOfCurrentSegment(m_lastBasicMood.id, intensity, m_lastBasicMood.musicDurationGeneral, true, true);
					    return PsaiResult.unknown_theme;
				    }				

			    }
			    //break;
		    }
	    }
Esempio n. 9
0
	    internal PsaiResult MenuModeLeave()
	    {
		   // boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
                	Logger.Instance.Log("MenuModeLeave", LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append(" m_themeQueue.size()=");
	                sb.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }			    
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    #if !(PSAI_NOLOG)
			    {
                    Logger.Instance.Log(LOGMESSAGE_ABORTION_DUE_TO_INITIALIZATION_FAILURE, LogLevel.errors);
			    }
			    #endif

			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

            if (m_paused)
            {
                setPaused(false);
            }

		    if (m_psaiPlayMode == PsaiPlayMode.menuMode)
		    {
			    if (getFollowingThemeQueueEntry() != null)
			    {
				    PopAndPlayNextFollowingTheme(true);
				    return PsaiResult.OK;
			    }
			    else
			    {
				    m_psaiStateIntended = PsaiState.silence;
				    m_psaiState = PsaiState.silence;
				    SetPlayMode(PsaiPlayMode.regular);
				    m_psaiPlayModeIntended = PsaiPlayMode.regular;

				    StopMusic(true);
				    return PsaiResult.OK;
			    }
		    }
		    else
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("MenuModeLeave() ignored - MenuMode wasn't active. Call MenuModeEnter() first !", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnored;
		    }
	    }
Esempio n. 10
0
        internal PsaiResult MenuModeEnter(int menuThemeId, float menuIntensity)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("entering Menu Mode, menuTheme id=");
	                sb.Append(menuThemeId);
	                sb.Append("  , intensity=");
	                sb.Append(menuIntensity);
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }

                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append("MenuModeEnter()  m_themeQueue.size()=");
	                sb2.Append(m_themeQueue.Count);
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug);
                }
		    }
		    #endif

		    if (m_initializationFailure)
		    {
			    return PsaiResult.initialization_error;
		    }

		    //////////////////////////////////////////////////////////////////////////

            if (m_paused)
            {
                setPaused(false);
            }


		    if (m_psaiPlayMode != PsaiPlayMode.menuMode)
		    {

			    // special case: we were leaving a cutscene and the cutscene theme is still playing,
			    // so we don't want to return to the cutscene afterwards
			    if (m_psaiPlayMode == PsaiPlayMode.cutScene && m_psaiPlayModeIntended == PsaiPlayMode.regular)
			    {
				    #if !(PSAI_NOLOG)
				    {
                        if (LogLevel.debug <= Logger.Instance.LogLevel)
                        {
	                        StringBuilder sb = new StringBuilder();
	                        sb.Append("special case: Menu Mode entered when we were just returning from the cutscene.");
	                        sb.Append("  m_currentTheme->id=");
	                        sb.Append(m_effectiveTheme.id);
	                        sb.Append("  m_targetSegment=");
	                        sb.Append(m_targetSegment);
	                        Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                        }
				    }
				    #endif

				    PushEffectiveThemeToThemeQueue(m_psaiPlayModeIntended);
			    }
			    else
			    {
                    PushEffectiveThemeToThemeQueue(m_psaiPlayMode);
			    }

                Theme menuTheme = m_soundtrack.getThemeById(menuThemeId);
			    if (menuTheme != null)
			    {
				    PlayThemeNowOrAtEndOfCurrentSegment(menuThemeId, menuIntensity, 666, true, true);
			    }
			    else
			    {				
				    // TODO: kein Menu Thema wurde gesetzt, d.h. der Menu Mode soll ohne Musik gestartet werden. Hier muss die Musik pausiert und ergo der psai status irgendwie eingefroren werden. Timer killen, timestamps neu berechnen
				    PlayThemeNowOrAtEndOfCurrentSegment(m_lastBasicMood.id, menuIntensity, 666, true, true);  // kommt raus sobald die pause funzt
			    }

			    SetPlayMode(PsaiPlayMode.menuMode);					
			    m_psaiPlayModeIntended = PsaiPlayMode.menuMode;
			    return PsaiResult.OK;
		    }		
		    else
		    {
			    #if !(PSAI_NOLOG)
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("Menu Mode already active", LogLevel.warnings);
                    }
			    #endif

			    return PsaiResult.commandIgnoredMenuModeActive;
		    }
	    }
Esempio n. 11
0
        /* This method will play the target Segment with minimum delay, and set the m_targetSnipet to m_currentSnippet, and m_targetVoice to m_currentVoice.
         */        
	    void PlayTargetSegmentImmediately()
	    {
            #if !(PSAI_NOLOG)
            {
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("PlayTargetSegmentImmediately()  m_targetSegmentTypesRequested=");
	                sb.Append(Segment.GetStringFromSegmentSuitabilities(m_targetSegmentSuitabilitiesRequested));
	                sb.Append("  targetSegment=");
	                sb.Append(m_targetSegment.Name);
	                sb.Append("  id=");
	                sb.Append(m_targetSegment.Id);
	                sb.Append("  m_targetVoice=");
	                sb.Append(m_targetVoice);
	                sb.Append("  themeId=");
	                sb.Append(m_targetSegment.ThemeId);
	                sb.Append("  playbackChannel.Segment=" );
	                sb.Append(m_playbackChannels[m_targetVoice].Segment.Name);
	                sb.Append("  millisSinceSegmentLoad=");
	                sb.Append(  m_playbackChannels[m_targetVoice].GetMillisecondsSinceSegmentLoad());
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                }
            }
            #endif

            int snippetPlaybackDelayMillis = 0;            
            if (m_playbackChannels[m_targetVoice].CheckIfSegmentHadEnoughTimeToLoad())
            {
                snippetPlaybackDelayMillis = m_estimatedTimestampOfTargetSnippetPlayback - GetTimestampMillisElapsedSinceInitialisation();

                #if !(PSAI_NOLOG)
                   if (LogLevel.debug <= Logger.Instance.LogLevel)
                   {
                       Logger.Instance.Log("Segment had enough time to load.   m_estimatedTimestampOfTargetSnippetPlayback=" + m_estimatedTimestampOfTargetSnippetPlayback.ToString(), LogLevel.debug);
                   }
                #endif                
            }
            else
            {
                int millisUntilLoadingWillHaveFinished = m_playbackChannels[m_targetVoice].GetMillisecondsUntilLoadingWillHaveFinished();
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
                    	Logger.Instance.Log("Segment DID NOT have enough time to load!  missing milliSeconds=" + millisUntilLoadingWillHaveFinished, LogLevel.debug);
                    }
                }
                #endif

                snippetPlaybackDelayMillis = millisUntilLoadingWillHaveFinished + s_audioLayerMaximumLatencyForPlayingbackPrebufferedSounds;
            }

            m_playbackChannels[m_targetVoice].FadeOutVolume = 1.0f;
            m_playbackChannels[m_targetVoice].ScheduleSegmentPlayback(m_targetSegment, snippetPlaybackDelayMillis);            

            if (m_scheduleFadeoutUponSnippetPlayback)
            {
                startFade(m_currentVoiceNumber, PSAI_FADEOUTMILLIS_PLAYIMMEDIATELY, m_targetSegment.audioData.GetPreBeatZoneInMilliseconds() + snippetPlaybackDelayMillis);
                m_scheduleFadeoutUponSnippetPlayback = false;
            }

            m_psaiPlayMode = m_psaiPlayModeIntended;
            m_currentVoiceNumber = m_targetVoice;

            m_currentSegmentPlaying = m_targetSegment;
            m_currentSnippetTypeRequested = m_targetSegmentSuitabilitiesRequested;
            m_currentSegmentPlaying.Playcount++;			//TODO: this should not be increased within menu mode, should it?

            m_timeStampCurrentSnippetPlaycall = GetTimestampMillisElapsedSinceInitialisation() + snippetPlaybackDelayMillis;

            // now set the timers for snippet end approaching and snippet end reached	
            int millisUntilUpcomingSnippetEnd = m_targetSegment.audioData.GetFullLengthInMilliseconds() + snippetPlaybackDelayMillis;            
            int millisUntilNextCalculateCall = (int)(millisUntilUpcomingSnippetEnd 
                - m_targetSegment.audioData.GetPostBeatZoneInMilliseconds() 
                - m_targetSegment.MaxPreBeatMsOfCompatibleSnippetsWithinSameTheme 
                - s_audioLayerMaximumLatencyForPlayingBackUnbufferedSounds      // deterministic calculation up to here...
                -  2 * s_updateIntervalMillis);  // ... now add some extra headroom for processing time


            if (millisUntilNextCalculateCall < 0)
            {                
                #if !(PSAI_NOLOG)
                {
                    if (LogLevel.warnings <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append(" psai did not have enough time to evaluate the next Segment in time (missing milliseconds: ");
	                    sb.Append(millisUntilNextCalculateCall);
	                    sb.Append(").");
	                    sb.Append(" This means that either the main region of Segment '");
                        sb.Append(m_currentSegmentPlaying.Name);
                        sb.Append("' (ThemeId=");
                        sb.Append(m_currentSegmentPlaying.ThemeId);
                        sb.Append(") is too short, or that the Prebeat region of at least one of its compatible Segments is too long. ");
                        sb.Append("See the 'best practice' section in the psai manual for more information.");
	                    Logger.Instance.Log(sb.ToString(), LogLevel.warnings);
                    }
                }
#endif

                millisUntilNextCalculateCall = 0;
            }          

            m_targetSegment = null;
            m_psaiState = PsaiState.playing;

            if (millisUntilNextCalculateCall < 0)
            {
                millisUntilNextCalculateCall = 0;
            }
            m_timerSegmentEndApproaching.SetTimer(millisUntilNextCalculateCall, s_updateIntervalMillis);


            // at the moment the SnippetEndReached Timer only fires for the very last snippet
            // so it will be extended with every following snippet
            m_timerSegmentEndReached.SetTimer(millisUntilUpcomingSnippetEnd, 0);

            #if !(PSAI_NOLOG)
            {
                /*
                if (LogLevel.debug <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("m_timer_SegmentEndApproaching should fire in ");
	                sb.Append(millisUntilNextCalculateCall);
	                sb.Append(" ms");
	                Logger.Instance.Log(sb.ToString(), LogLevel.debug);
	
	                
	                StringBuilder sb2 = new StringBuilder();
	                sb2.Append("m_timer_SegmentEndReached should fire in ");
	                sb2.Append(millisUntilUpcomingSnippetEnd);
	                sb2.Append(" ms");
	                Logger.Instance.Log(sb2.ToString(), LogLevel.debug); 
                }               
                */
            }
            #endif            
	    }
Esempio n. 12
0
        	/** basic internal function for setting the first theme that will be played as soon as the
	    * current theme's intensity has dropped (or has been set) to zero. This method behaves as a push operation, so the parameter will be
	    * the first theme on the theme queue stack.
	    * @param clearThemeQueue pass true to clear the themeQueue, false to enqueue the followingTheme in the themeQueue
	    * @param restTimeMillis if the theme should start in rest mode, pass the resting millis. 0 otherwise.
	    * @param playMode the playMode that will be entered when the theme is popped.
	    * @param holdIntensity true for holding the intensity at a constant level
	    */
	    bool pushThemeToThemeQueue(int themeId, float intensity, int musicDuration, bool clearThemeQueue, int restTimeMillis, PsaiPlayMode playMode, bool holdIntensity)
	    {
		    //boost::recursive_mutex::scoped_lock block(m_pnxLogicMutex);

		    #if !(PSAI_NOLOG)
		    {
                if (LogLevel.info <= Logger.Instance.LogLevel)
                {
	                StringBuilder sb = new StringBuilder();
	                sb.Append("setting the Following Theme to ");
	                sb.Append(themeId);

                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
        	            sb.Append("  intensity= ");
	                    sb.Append(intensity);
	                    sb.Append("  clearThemeQueue=");
	                    sb.Append(clearThemeQueue);
	                    sb.Append("  playmode=");
	                    sb.Append(playMode);
	                    sb.Append("  holdIntensity=");
	                    sb.Append(holdIntensity);
	                    sb.Append("  musicDuration=");
	                    sb.Append(musicDuration);
                    }
	                Logger.Instance.Log(sb.ToString(), LogLevel.info);
                }
		    }
#endif

            if (clearThemeQueue)
		    {
			    m_themeQueue.Clear();
		    }

            Theme theme = m_soundtrack.getThemeById(themeId);
		    if (theme != null)
		    {
			    ThemeQueueEntry newEntry = new ThemeQueueEntry();
			    newEntry.themeId = themeId;
			    newEntry.startIntensity = intensity;
                newEntry.musicDuration = musicDuration;
			    newEntry.restTimeMillis = restTimeMillis;
			    newEntry.playmode = playMode;
			    newEntry.holdIntensity = holdIntensity;

			    #if !(PSAI_NOLOG)
			    {
                    if (LogLevel.debug <= Logger.Instance.LogLevel)
                    {
	                    StringBuilder sb = new StringBuilder();
	                    sb.Append(" m_themeQueue.size()=");
	                    sb.Append(m_themeQueue.Count);
	               	    for (int i=0; i<m_themeQueue.Count; i++)
					    {
						    ThemeQueueEntry tmpEntry = m_themeQueue[i];
	                        sb.Append("   [");
	                        sb.Append(i);
	                        sb.Append("] themeId=");
	                        sb.Append(tmpEntry.themeId);
	                        sb.Append(" startIntensity=");
	                        sb.Append(tmpEntry.startIntensity);
	                    }
	                    Logger.Instance.Log(sb.ToString(), LogLevel.debug);
                    }
			    }
			    #endif

                m_themeQueue.Insert(0, newEntry);
                m_psaiStateIntended = PsaiState.playing;		// in case IntensityZeroHandler() had already been called, we need to reset the psaiStateIntended here
                return true;
		    }
		    else
		    {
			    return false;
		    }
	    }