📄 soundscheduler.java
字号:
debugPrint(": scheduling action calculated " + "as "+ soundAtom.schedulingAction); debugPrint(" dirtyFlag test of LISTENER_CHANGED " + testListenerFlag() ); } // If state has not changed but parameters have, set // action to UPDATE. // This test includes checking that SoundScheduler dirtyFlag // set when Eye, Ear or ImagePlate-to-Vworld Xform changed // even for non-BackgroundSounds if ((soundAtom.schedulingAction == SoundSchedulerAtom.LEAVE_AUDIBLE) && (soundAtom.testDirtyFlags() || (testListenerFlag() && !(sound instanceof BackgroundSoundRetained)))) { if (debugFlag) { if (testListenerFlag()) { debugPrint(" testListenerFlag = " + testListenerFlag()); } debugPrint(": action changed from " + "as LEAVE_AUDIBLE to UPDATE"); } soundAtom.schedulingAction = SoundSchedulerAtom.UPDATE; } // Update prioritized list of sounds whose scheduling action // demands processing... // Ensure sound are not stopped while looping thru prioritized sounds switch (soundAtom.schedulingAction) { case SoundSchedulerAtom.TURN_OFF: soundAtom.status = SoundSchedulerAtom.SOUND_OFF; turnOff(soundAtom); // Stop sound that need to be turned off if (debugFlag) debugPrint(": sound " + soundAtom.sampleId + " action OFF results in call to stop"); soundAtom.schedulingAction = SoundSchedulerAtom.LEAVE_OFF; break; case SoundSchedulerAtom.MAKE_AUDIBLE: case SoundSchedulerAtom.MAKE_SILENT: case SoundSchedulerAtom.LEAVE_AUDIBLE: case SoundSchedulerAtom.LEAVE_SILENT: case SoundSchedulerAtom.PAUSE_AUDIBLE: case SoundSchedulerAtom.PAUSE_SILENT: case SoundSchedulerAtom.RESUME_AUDIBLE: case SoundSchedulerAtom.RESUME_SILENT: case SoundSchedulerAtom.UPDATE: // Test for sound finishing playing since the last // thru the run() loop. // // test current time against endTime of sound to determine // if sound is Completely finished playing long currentTime = J3dClock.currentTimeMillis(); if (soundAtom.endTime>0 && soundAtom.endTime<=currentTime) { // sound's completed playing, force action soundAtom.schedulingAction = SoundSchedulerAtom.COMPLETE; if (debugFlag) debugPrint(": sample complete;"+ " endTime = " + soundAtom.endTime + ", currentTime = " + currentTime + " so turned off"); soundAtom.status = SoundSchedulerAtom.SOUND_COMPLETE; turnOff(soundAtom); // Stop sound in device that are complete if (debugFlag) debugPrint(": sound "+soundAtom.sampleId+ " action COMPLETE results in call to stop"); } break; case SoundSchedulerAtom.RESTART_AUDIBLE: case SoundSchedulerAtom.START_AUDIBLE: case SoundSchedulerAtom.RESTART_SILENT: case SoundSchedulerAtom.START_SILENT: break; default: // includes COMPLETE, DO_NOTHING soundAtom.schedulingAction = SoundSchedulerAtom.DO_NOTHING; break; } // switch if (debugFlag) debugPrint(": final scheduling action " + "set to " + soundAtom.schedulingAction); } /** * Determine scheduling action for each live sound */ int calcSchedulingAction() { // Temp variables SoundRetained sound; SoundRetained mirSound; SoundSchedulerAtom soundAtom; SoundRetained jSound; int nSounds = 0; boolean processSound; // number of sounds to process including scene graph and immediate nodes int numSoundsToProcess = 0; if (universe == null) { if (debugFlag) debugPrint( ": calcSchedulingAction: univ NULL"); return 0; } if (universe.soundStructure == null) { if (debugFlag) debugPrint( ": calcSchedulingAction: soundStructure NULL"); return 0; } // List of prioritized "live" sounds taken from universe list of sounds. // Maintained as an expandable array - start out with a small number of // elements for this array then grow the list larger if necessary... synchronized (prioritizedSounds) { nSounds = prioritizedSounds.size(); if (debugFlag) debugPrint( ": calcSchedulingAction: soundsList size = " + nSounds); // (Large) Loop over all switched on sounds and conditionally put // these into a order prioritized list of sound. // Try throw out as many sounds as we can: // Sounds finished playing (reached end before stopped) // Sounds still yet to be loaded // Positional sounds whose regions don't intersect view // Sound to be stopped // Those sounds remaining are inserted into a prioritized list for (int i=0; i<nSounds; i++) { soundAtom = ((SoundSchedulerAtom)prioritizedSounds.get(i)); mirSound = soundAtom.sound; sound = mirSound.sgSound; if (debugFlag) { debugPrint(" calcSchedulingAction: sound at " + sound); printAtomState(soundAtom); } // First make a list of switched on live sounds // make sure to process turned-off sounds even if they are // NOT active processSound = false; if ( (!sound.source.isLive() && !sound.getInImmCtx() ) ) { if (debugFlag) { debugPrint(" calcSchedulingAction sound " + sound + " is NOT Live"); if (mirSound.source != null) { if (mirSound.source.isLive()!=sound.source.isLive()) debugPrint( " !=!=!= sound.isLive != mirSound"); } } if (soundAtom.playing || (soundAtom.enabled == SoundSchedulerAtom.ON)) { soundAtom.setEnableState(SoundSchedulerAtom.PENDING_OFF); processSound = true; if (debugFlag) debugPrint(" calcSchedulingAction !isLive: " + "sound playing or ON, so set PENDING_OFF"); } else if (soundAtom.enabled==SoundSchedulerAtom.PENDING_OFF){ processSound = true; if (debugFlag) debugPrint(" calcSchedulingAction !isLive: " + "sound == PENDING_OFF so process"); } else if (soundAtom.enabled==SoundSchedulerAtom.PENDING_ON) { soundAtom.setEnableState(SoundSchedulerAtom.OFF); if (debugFlag) debugPrint(" calcSchedulingAction !isLive: " + "sound == PENDING_ON so set OFF"); } } else { // live and switched on retained node or // non-retained (immediate mode) node processSound = true; } if (processSound) { numSoundsToProcess++; if (debugFlag) { debugPrint(".testListenerFlag = " + testListenerFlag() + "...."); debugPrint(" contents of live sound " + soundAtom.sampleId + " before processing," ); debugPrint(" >>>>>>sound using sgSound at " + sound); printAtomState(soundAtom); } processSoundAtom(soundAtom); } // end of process sound else { soundAtom.schedulingAction = SoundSchedulerAtom.DO_NOTHING; } // end of not process sound } // end loop over all sound in soundList } // sync if (debugFlag) { if (numSoundsToProcess > 0) debugPrint(": number of liveSounds = " + numSoundsToProcess); else debugPrint(": number of liveSounds <= 0"); } return numSoundsToProcess; } /** * Mute sounds that are to be played silently. * * Not all the sound in the prioritized enabled sound list * may be able to be played. Due to low priority, some sounds * must be muted/silenced (if such an action frees up channel * resources) to make way for sounds with higher priority. * For each sound in priority list: * For sounds whose actions are X_SILENT: * Mute sounds to be silenced * Add the number of channels used by this muted sound to * current total number of channels used * For all remaining sounds (with actions other than above) * The number of channels that 'would be used' to play * potentially audible sounds is compared with * the number left on the device: * If this sound would use more channels than available * Change it's X_AUDIBLE action to X_SILENT * Mute sounds to be silenced * Add the number of channels used by this sound, muted * or not, to current total number of channels used * * NOTE: requests for sounds to play beyond channel capability of * the audio device do NOT throw an exception when more sounds are * started than can be played. Rather the unplayable sounds are * muted. It is up to the AudioDevice3D implementation to determine * how muted/silent sounds are implememted (playing with gain zero * and thus using up channel resources, or stop and restarted with * correct offset when inactivated then re-actived. */ void muteSilentSounds() { // Temp variables SoundRetained sound; SoundRetained mirSound; int totalChannelsUsed = 0; SoundSchedulerAtom soundAtom; int nAtoms; synchronized (prioritizedSounds) { nAtoms = prioritizedSounds.size(); if (debugFlag) debugPrint(".muteSilentSounds(): Loop over prioritizedSounds list, " + "size = " + nAtoms); for (int i=0; i<nAtoms; i++) { soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); mirSound = (SoundRetained)soundAtom.sound; sound = mirSound.sgSound; int sampleId = soundAtom.sampleId; int status = soundAtom.status; if (debugFlag) { debugPrint(": contents of current sound " + soundAtom.sampleId + " before switch on sAction" ); printAtomState(soundAtom); } if (soundAtom.status == SoundSchedulerAtom.SOUND_COMPLETE) { continue; } if (soundAtom.schedulingAction == SoundSchedulerAtom.DO_NOTHING) { continue; } if (sampleId == SoundRetained.NULL_SOUND) { // skip it until next time thru calcSchedulingAction continue; } if ( (soundAtom.schedulingAction == SoundSchedulerAtom.MAKE_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.RESTART_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.LEAVE_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.START_SILENT) ) { // Mute sounds that are not already silent if (status != SoundSchedulerAtom.SOUND_SILENT) { // old status is not already muted/silent audioDevice3D.muteSample(sampleId); if (debugFlag) debugPrint(": sound " + sampleId + " action is x_SILENT, sound muted"); } // now that the exact muting state is known get the actual // number of channels used by this sound and add to total int numberChannels = audioDevice3D.getNumberOfChannelsUsed(sampleId); soundAtom.numberChannels = numberChannels; // used in audio device totalChannelsUsed += numberChannels; // could return zero } // scheduling is for silent sound else { // First, test to see if the sound can play as unmuted. int numberChannels = audioDevice3D.getNumberOfChannelsUsed(sampleId, false); // Mute sounds that have too low priority if ((totalChannelsUsed+numberChannels)>totalChannels) { if ((soundAtom.schedulingAction == SoundSchedulerAtom.MAKE_AUDIBLE) || (soundAtom.schedulingAction == SoundSchedulerAtom.LEAVE_AUDIBLE)) { soundAtom.schedulingAction = SoundSchedulerAtom.MAKE_SILENT; } else if (soundAtom.schedulingAction == SoundSchedulerAtom.RESTART_AUDIBLE) soundAtom.schedulingAction = SoundSchedulerAtom.RESTART_SILENT; else if (soundAtom.schedulingAction == SoundSchedulerAtom.START_AUDIBLE) soundAtom.schedulingAction = SoundSchedulerAtom.START_SILENT; else if (soundAtom.schedulingAction == SoundSchedulerAtom.PAUSE_AUDIBLE) soundAtom.schedulingAction = SoundSchedulerAtom.PAUSE_SILENT; else if (soundAtom.schedulingAction == SoundSchedulerAtom.RESUME_AUDIBLE) soundAtom.schedulingAction = SoundSchedulerAtom.RESUME_SILENT; audioDevice3D.muteSample(sampleId); if (debugFlag) { debugPrint(": sound " + sampleId + "number of channels needed is " + numberChannels); debugPrint(": sound " + sampleId + " action is x_AUDIBLE but " + "not enough channels free (" + (totalChannels - totalChannelsUsed) + ") so, sound muted"); } } // sound has enough channels to play else if (status != SoundSchedulerAtom.SOUND_AUDIBLE) { // old status is not already unmuted/audible audioDevice3D.unmuteSample(sampleId); if (debugFlag) debugPrint(": sound " + sampleId + " action is x_AUDIBLE and channels free so, " + "sound unmuted"); } // now that the exact muting state is known (re-)get actual // number of channels used by this sound and add to total numberChannels = audioDevice3D.getNumberOfChannelsUsed(sampleId); soundAtom.numberChannels = numberChannels; // used in audio device totalChannelsUsed += numberChannels; } // otherwise, scheduling is for potentally audible sound // No sound in list should have action TURN_ or LEAVE_OFF } // of for loop over sounds in list } } void muteSilentSound(SoundSchedulerAtom soundAtom) { // Temp variables SoundRetained sound; SoundRetained mirSound; mirSound = (SoundRetained)soundAtom.sound; sound = mirSound.sgSound; int sampleId = soundAtom.sampleId; int status = soundAtom.status; if (status == SoundSchedulerAtom.SOUND_COMPLETE) { return; } if (sampleId == SoundRetained.NULL_SOUND) { return; } if (debugFlag) { debugPrint(": contents of current sound " + soundAtom.sampleId + " before switch on sAction" ); printAtomState(soundAtom); } if ( (soundAtom.schedulingAction == SoundSchedulerAtom.MAKE_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.RESTART_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.LEAVE_SILENT) || (soundAtom.schedulingAction == SoundSchedulerAtom.START_SILENT) ) { // Mute sounds that are not already silent if (status != SoundSchedulerAtom.SOUND_SILENT) { // old status is not already muted/silent audioDevice3D.muteSample(sampleId); if (debugFlag) debugPrint(": sound " + sampleId + " action is x_SILENT, sound muted"); } } // scheduling is for silent sound } /** * Determine amount of time before next playing sound will be * is complete. * * find the atom that has the least amount of time before is * finished playing and return this time * @return length of time in millisecond until the next active sound * will be complete. Returns -1 if no sounds are playing (or all are * complete). */ long shortestTimeToFinish() { long currentTime = J3dClock.currentTimeMillis(); long shortestTime = -1L; SoundSche
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -