📄 soundscheduler.java
字号:
if (intersectedSoundscapes.length < nSscapes) { intersectedSoundscapes = new SoundscapeRetained[nSscapes + 32]; } // nSscapes is incremented for every Soundscape found if (debugFlag) debugPrint(".findActiveSoundscapes() nUnivSscapes="+ nUnivSscapes); nSelectedSScapes = 0; for (int k=0; k<nUnivSscapes; k++) { lss = (SoundscapeRetained)soundScapes.get(k); // Find soundscapes that intersect the view platform region if (lss.transformedRegion == null ) { continue; } if ((region instanceof BoundingSphere && lss.transformedRegion instanceof BoundingSphere) || (region instanceof BoundingBox && lss.transformedRegion instanceof BoundingBox) || (region instanceof BoundingPolytope && lss.transformedRegion instanceof BoundingPolytope) ) { lss.transformedRegion.getWithLock(region); if (debugFlag) debugPrint(" get tranformed region " + region ); } else { region = (Bounds)lss.transformedRegion.clone(); if (debugFlag) debugPrint(" clone tranformed region " + region ); } if (region!=null && viewPlatform.schedSphere.intersect(region)){ intersectedRegions[nSelectedSScapes] = (Bounds)region.clone(); // test View Platform intersection(lss)) intersectedSoundscapes[nSelectedSScapes] = lss; if (debugFlag) debugPrint(" store sscape " + lss + " and region " + region + " into array"); nSelectedSScapes++; if (debugFlag) debugPrint(": region of intersection for "+ "soundscape "+k+" found at "+J3dClock.currentTimeMillis()); } else { if (debugFlag) debugPrint( ": region of intersection for soundscape "+ k + " not found at "+ J3dClock.currentTimeMillis()); } } } return(nSelectedSScapes); } AuralAttributesRetained findClosestAAttribs(int nSelectedSScapes) { AuralAttributes aa = null; SoundscapeRetained ss = null; boolean intersected = false; // Get auralAttributes from closest (non-null) soundscape ss = null; if (nSelectedSScapes == 1) ss = intersectedSoundscapes[0]; else if (nSelectedSScapes > 1) { Bounds closestRegions; closestRegions = viewPlatform.schedSphere.closestIntersection( intersectedRegions); for (int j=0; j < intersectedRegions.length; j++) { if (debugFlag) debugPrint(" element " + j + " in intersectedSoundsscapes is " + intersectedRegions[j]); if (intersectedRegions[j] == closestRegions) { ss = intersectedSoundscapes[j]; if (debugFlag) debugPrint(" element " + j + " is closest"); break; } } } if (ss != null) { if (debugFlag) debugPrint(" closest SoundScape found is " + ss); aa = ss.getAuralAttributes(); if (aa != null) { if (debugFlag) debugPrint(": AuralAttribute for " + "soundscape is NOT null"); } else { if (debugFlag) debugPrint(": AuralAttribute for " + "soundscape " + ss + " is NULL"); } } else { if (debugFlag) debugPrint(": AuralAttribute is null " + "since soundscape is NULL"); } if (debugFlag) debugPrint( " auralAttrib for closest SoundScape found is " + aa); return ((AuralAttributesRetained)aa.retained); } /** * Send current aural attributes to audio device * * Note that a AA's dirtyFlag is clear only after parameters are sent to * audio device. */ void updateAuralAttribs(AuralAttributesRetained attribs) { if (auralAttribsChanged) { if (attribs != null) { synchronized (attribs) {/* // XXXX: remove use of aaDirty from AuralAttrib node if ((attribs != lastAA) || attribs.aaDirty)*/ if (debugFlag) { debugPrint(" set real updateAuralAttribs because"); } // Send current aural attributes to audio device // Assumes that aural attribute parameter is NOT null. audioDevice3D.setRolloff(attribs.rolloff); if (debugFlag) debugPrint(" rolloff " + attribs.rolloff); // Distance filter parameters int arraySize = attribs.getDistanceFilterLength(); if ((attribs.filterType == AuralAttributesRetained.NO_FILTERING) || arraySize == 0 ) { audioDevice3D.setDistanceFilter( attribs.NO_FILTERING, null, null); if (debugFlag) debugPrint(" no filtering"); } else { Point2f[] attenuation = new Point2f[arraySize]; for (int i=0; i< arraySize; i++) attenuation[i] = new Point2f(); attribs.getDistanceFilter(attenuation); double[] distance = new double[arraySize]; float[] cutoff = new float[arraySize]; for (int i=0; i< arraySize; i++) { distance[i] = attenuation[i].x; cutoff[i] = attenuation[i].y; } audioDevice3D.setDistanceFilter(attribs.filterType, distance, cutoff); if (debugFlag) { debugPrint(" filtering parameters: " + " distance, cutoff arrays"); for (int jj=0; jj<arraySize; jj++) debugPrint( " " + distance[jj]+", "+cutoff[jj]); } } audioDevice3D.setFrequencyScaleFactor( attribs.frequencyScaleFactor); if (debugFlag) debugPrint(" freq.scale " + attribs.frequencyScaleFactor); audioDevice3D.setVelocityScaleFactor( attribs.velocityScaleFactor); if (debugFlag) debugPrint(" velocity scale " + attribs.velocityScaleFactor); audioDevice3D.setReflectionCoefficient( attribs.reflectionCoefficient); if (audioDevice3DL2 != null) { audioDevice3DL2.setReverbCoefficient( attribs.reverbCoefficient); audioDevice3DL2.setDecayFilter(attribs.decayFilter); audioDevice3DL2.setDiffusion(attribs.diffusion); audioDevice3DL2.setDensity(attribs.density); if (debugFlag) { debugPrint(" reflect coeff " + attribs.reflectionCoefficient); debugPrint(" reverb coeff " + attribs.reverbCoefficient); debugPrint(" decay filter " + attribs.decayFilter); debugPrint(" diffusion " + attribs.diffusion); debugPrint(" density " + attribs.density); } } // Precidence for determining Reverb Delay // 1) If ReverbBounds set, bounds used to calculate delay. // Default ReverbBounds is null meaning it's not defined. // 2) If ReverbBounds is null, ReverbDelay used // (implitic default value is defined as 40ms) // If Bounds null, use Reverb Delay // else calculate Reverb Delay from Bounds Bounds reverbVolume = attribs.reverbBounds; if (reverbVolume == null) { audioDevice3D.setReverbDelay(attribs.reverbDelay); if (debugFlag) debugPrint( " reverbDelay " + attribs.reverbDelay); } else { float reverbDelay; if (reverbVolume instanceof BoundingSphere) { // worst (slowest) case is if sound in center of // bounding sphere reverbDelay = (float) ((2.0*((BoundingSphere)reverbVolume).radius)/ AuralAttributesRetained.SPEED_OF_SOUND); } else { // create a bounding sphere the surrounds the bounding // object then calcalate the worst case as above BoundingSphere tempSphere = new BoundingSphere(reverbVolume); reverbDelay = (float) ((2.0 * tempSphere.radius)/ AuralAttributesRetained.SPEED_OF_SOUND); } audioDevice3D.setReverbDelay(reverbDelay); if (debugFlag) debugPrint(" reverbDelay " + reverbDelay); } // Audio device makes calculations for reverb decay // using API's precidence where positive reverb order // is used to clamp reverb decay time. // Because of that the values are just passed along. audioDevice3D.setReverbOrder(attribs.reverbOrder); if (audioDevice3DL2 != null) audioDevice3DL2.setDecayTime(attribs.decayTime); } // sync attribs resetAA = true; } // attribs not null else if (lastAA != null) { // Even when there are no active auralAttributes, still check // if a set of auralAttributes was passed to the AudioDevice, // thus is now inactive and must be cleared out (set to // default values). // Gain scale factor of 1.0 implicit by default - this value // passed to AudioDevice3D as part of InitialScaleFactor value. if (debugFlag) debugPrint(": set updateDefaultAAs"); audioDevice3D.setRolloff(1.0f); audioDevice3D.setReflectionCoefficient(0.0f); audioDevice3D.setReverbDelay(40.0f); audioDevice3D.setReverbOrder(0); // Distance filter parameters audioDevice3D.setDistanceFilter( AuralAttributesRetained.NO_FILTERING, null, null); audioDevice3D.setFrequencyScaleFactor(1.0f); audioDevice3D.setVelocityScaleFactor(0.0f); if (audioDevice3DL2 != null) { audioDevice3DL2.setReverbCoefficient(0.0f); audioDevice3DL2.setReflectionDelay(20.0f); audioDevice3DL2.setDecayTime(1000.0f); audioDevice3DL2.setDecayFilter(5000.0f); audioDevice3DL2.setDiffusion(1.0f); audioDevice3DL2.setDensity(1.0f); } // Any change in AuralAttrib should force an update of all // active sounds as passed to AudioDevice3D. resetAA = true; } else { if (debugFlag) debugPrint(" updateAuralAttribs: none set or cleared"); }/* attribs.aaDirty = false;*/ lastAA = attribs; auralAttribsChanged = false; } } void processSoundAtom(SoundSchedulerAtom soundAtom) { SoundRetained mirSound = soundAtom.sound; SoundRetained sound = mirSound.sgSound; // Sounds that have finished playing are not put into list if ((soundAtom.status == SoundSchedulerAtom.SOUND_COMPLETE) && (soundAtom.enabled != SoundSchedulerAtom.PENDING_ON )) { // XXXX:/QUESTION test for immediate mode (?) // Unless the sound has been re-started, there's no need // to process sound the finished playing the last time thru // the run() loop return; // don't need to process unless re-started } // Sound must be loaded if it hasn't been successfully loaded already if (soundAtom.loadStatus != SoundRetained.LOAD_COMPLETE) { // should be OK for soundData to be NULL - this will unclear if (debugFlag) debugPrint(": LOAD_PENDING - try attaching"); attachSoundData(soundAtom, sound.soundData, false); } // if the loadStatus is STILL NOT COMPLETE, wait to schedule if (soundAtom.loadStatus != SoundRetained.LOAD_COMPLETE) { if (debugFlag) debugPrint(": not LOAD_COMPLETE yet, so bail"); // if sound is still not loaded, or loaded with null return; // don't process this sound now } if (resetAA) { // explicitly force update of gain for sound soundAtom.setAttribsDirtyFlag(SoundRetained.INITIAL_GAIN_DIRTY_BIT); } // Determine if sound is "active" // Immediate mode sounds are always active. // Sounds (both background and positional) are active only when their // scheduling region intersects the viewPlatform. boolean intersected = false; if (!updateThread.active) { region = null; intersected = false; // force sound to be made inactive if (debugFlag) debugPrint(": updateThread NOT active"); } else if (sound.getInImmCtx()) { region = null; intersected = true; if (debugFlag) debugPrint(": sound.getInImmCtx TRUE"); } else { if ( sound.schedulingRegion != null && mirSound.transformedRegion != null ) { // QUESTION: shouldn't mirror sound transformedRegion be // set to null when sound node's region set null? if ((region instanceof BoundingSphere && mirSound.transformedRegion instanceof BoundingSphere) || (region instanceof BoundingBox && mirSound.transformedRegion instanceof BoundingBox) || (region instanceof BoundingPolytope && mirSound.transformedRegion instanceof BoundingPolytope)){ mirSound.transformedRegion.getWithLock(region); } else { region = (Bounds)mirSound.transformedRegion.clone(); } } else { region = null; } if (region != null) { if (debugFlag) debugPrint(": region is " + region ); intersected = viewPlatform.schedSphere.intersect(region); if (debugFlag) debugPrint(" intersection with viewPlatform is " + intersected ); } else { intersected = false; if (debugFlag) debugPrint(": region is null, " + "so region does NOT intersect viewPlatform"); } } // Get scheduling action based on sound state (flags, status) // Sound must be unmuted or pending unmuting and // either immediate mode node, or if retained // then intersecting active region and switch state must be on. if (debugFlag) { debugPrint(": intersected = " + intersected); debugPrint(": switchState = " + mirSound.switchState); if (mirSound.switchState != null) debugPrint(": switchOn = " + mirSound.switchState.currentSwitchOn); debugPrint(": soundAtom.muted = " + soundAtom.muted); } if ( (sound.getInImmCtx() || (intersected && mirSound.switchState != null && mirSound.switchState.currentSwitchOn) ) && (soundAtom.muted == soundAtom.UNMUTED || soundAtom.muted == soundAtom.PENDING_UNMUTE) ) { if (debugFlag) debugPrint(": calcActiveSchedAction"); soundAtom.schedulingAction = soundAtom.calcActiveSchedAction(); } else { if (debugFlag) debugPrint(": calcInactiveSchedAction"); soundAtom.schedulingAction = soundAtom.calcInactiveSchedAction(); } if (debugFlag) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -