📄 soundscheduler.java
字号:
// Issue 264 - catch Error System.err.println("Error occurred " + "during sound deactivation:"); e.printStackTrace(); } updateThread.active = false; } } // Check the ready state and return true if ready boolean checkState() { boolean runState = false; if (stallThread) { if (debugFlag) debugPrint(" checkState stallThread true"); runState = false; } if (ready) { if (debugFlag) debugPrint(" checkState ready to run"); runState = true; } else { // previous not ready, force reset call to see if everything // ready now or not reset(); if (ready) { if (debugFlag) debugPrint(" checkState Now ready to run"); runState = true; } else { if (debugFlag) { debugPrint(" checkState NOT ready to run"); } runState = false; } } return runState; } synchronized void reset() { // Return quickly if universe, view, physical env, or audio // device are null if (universe == null || view == null || view.physicalEnvironment == null || view.physicalEnvironment.audioDevice == null) { audioDevice = null; ready = false; return; } // Set AudioDevice audioDevice = view.physicalEnvironment.audioDevice; // Get viewPlatform; if it is null or not live, we can't render ViewPlatform vp = view.getViewPlatform(); if (vp == null || vp.retained == null) { // System.err.println(" vp is null"); viewPlatform = null; ready = false; return; } viewPlatform = (ViewPlatformRetained)vp.retained; if (!vp.isLive()) { ready = false; return; } // XXXX: Does not support multiple canvases per view, thus // multiple GraphicsContext3Ds // QUESTION: what does that mean for sound - // being applied to only ONE graphics context? // GET FIRST Canvas Canvas3D canvas = view.getFirstCanvas(); if (canvas != null) { graphicsCtx = canvas.getGraphicsContext3D(); } // now the render loop can be run successfully audioDevice3DL2 = null; audioDevice3D = null; if (audioDevice instanceof AudioDevice3DL2) { audioDevice3DL2 = (AudioDevice3DL2)audioDevice; } if (audioDevice instanceof AudioDevice3D) { audioDevice3D = (AudioDevice3D)audioDevice; if (debugFlag) debugPrint(".reset: audioDevice3D.setView"); audioDevice3D.setView(view); totalChannels = audioDevice.getTotalChannels(); if (debugFlag) debugPrint(" audioDevice3D.getTotalChannels returned " + totalChannels); } else { if (internalErrors) debugPrint(": AudioDevice implementation not supported"); totalChannels = 0; } if (totalChannels == 0) { ready = false; return; } ready = true; // since audio device is ready; set enable flag for continuous // calculating userHead-to-VirtualWorld transform view.setUserHeadToVworldEnable(true); return; } void receiveAWTEvent(AWTEvent evt) { int eventId = evt.getID(); if (debugFlag) debugPrint(".receiveAWTEvent " + eventId); if (ready && eventId == WindowEvent.WINDOW_ICONIFIED) { lastEventReceived = eventId; } else if (ready && (lastEventReceived == WindowEvent.WINDOW_ICONIFIED && eventId == WindowEvent.WINDOW_DEICONIFIED) ) { lastEventReceived = eventId; // used to notify } } /** * The main loop for the Sound Scheduler. */ void renderChanges() { int nSounds = 0; int totalChannelsUsed = 0; int nPrioritizedSound = 0; int numActiveSounds = 0; if (debugFlag) debugPrint(" renderChanges begun"); // XXXX: BUG?? should wait if audioDevice is NULL or nSounds = 0 // when a new sound is added or deleted from list, or // when the audioDevice is set into PhysicalEnvironment if (!checkState()) { if (debugFlag) debugPrint(".workToDo() checkState failed"); return; } /* synchronized (prioritizedSounds) { */ nPrioritizedSound = prioritizedSounds.size(); if (debugFlag) debugPrint(" nPrioritizedSound = " + nPrioritizedSound); if (nPrioritizedSound == 0) return; if (auralAttribsChanged) { // Find closest active aural attributes in scene graph int nIntersected = findActiveSoundscapes(); if (nIntersected > 0) { if (debugFlag) debugPrint(" "+ nIntersected + " active SoundScapes found"); // XXXX: (Performance) calling clone everytime, even // though closest AA has NOT changed, is expensive aaRetained = (AuralAttributesRetained) (findClosestAAttribs(nIntersected)).clone(); } else { if (debugFlag) debugPrint(" NO active SoundScapes found"); } } if (nPrioritizedSound > 0) { calcSchedulingAction(); muteSilentSounds(); // short term flag set within performActions->update() positionalSoundUpdated = false; // if listener parameters changed re-set View parameters if (testListenerFlag()) { if (debugFlag) debugPrint(" audioDevice3D.setView"); audioDevice3D.setView(view); } numActiveSounds = performActions(); if (positionalSoundUpdated) { // if performActions updated at least one positional sound // was processed so the listener/view changes were processed, // thus we can clear the SoundScheduler dirtyFlag, otherwise // leave the flag dirty until a positional sound is updated clearListenerFlag(); // clears listenerUpdated flag } } /* } */ } /** * Prioritize all sounds associated with SoundScheduler (view) * This only need be done once when scheduler is initialized since * the priority list is updated when: * a) PRIORITY_DIRTY_BIT in soundDirty field set; or * b) sound added or removed from live array list */ int prioritizeSounds() { int size; synchronized (prioritizedSounds) { if (!prioritizedSounds.isEmpty()) { prioritizedSounds.clear(); } // XXXX: sync soundStructure sound list UnorderList retainedSounds = universe.soundStructure.getSoundList(view); // QUESTION: what is in this sound list?? // mirror node or actual node??? nRetainedSounds = 0; nImmedSounds = 0; if (debugFlag) debugPrint(" prioritizeSound , num retained sounds" + retainedSounds.size()); for (int i=0; i<retainedSounds.size(); i++) { addPrioritizedSound((SoundRetained)retainedSounds.get(i)); nRetainedSounds++; } // XXXX: sync canvases Enumeration canvases = view.getAllCanvas3Ds(); while (canvases.hasMoreElements()) { Canvas3D canvas = (Canvas3D)canvases.nextElement(); GraphicsContext3D graphicsContext = canvas.getGraphicsContext3D(); Enumeration nonretainedSounds = graphicsContext.getAllSounds(); while (nonretainedSounds.hasMoreElements()) { if (debugFlag) debugPrint(" prioritizeSound , get non-retained sound"); Sound sound = (Sound)nonretainedSounds.nextElement(); if (sound == null) { if (debugFlag) debugPrint(" prioritizeSound , sound element is null"); // QUESTION: why should I have to do this? continue; } addPrioritizedSound((SoundRetained)sound.retained); nImmedSounds++; } } if (debugFlag) debugPrint(" prioritizeSound , num of processed retained sounds" + nRetainedSounds); debugPrint(" prioritizeSound , num of processed non-retained sounds" + nImmedSounds); size = prioritizedSounds.size(); } // sync return size; } // methods that call this should synchronize prioritizedSounds void addPrioritizedSound(SoundRetained mirSound) { SoundRetained sound = mirSound.sgSound; if (sound == null) { // this mirSound is a nonretained sound // pad the "child" sg sound pointer with itself mirSound.sgSound = mirSound; sound = mirSound; if (debugFlag) debugPrint(":addPritorizedSound() sound NULL"); } boolean addAtom = false; // see if this atom is in the list already // covers the case where the node was detached or unswitched but NOT // deleted (so sample already loaded // QUESTION: is above logic correct??? SoundSchedulerAtom atom = null; atom = findSoundAtom(mirSound, 1); // look thru list for 1st instance if (atom == null) { atom = new SoundSchedulerAtom(); atom.soundScheduler = this; // save scheduler atom is associated with addAtom = true; } // update fields in atom based on sound nodes state atom.sound = mirSound; // new mirror sound updateTransformedFields(mirSound); if ( !addAtom ) { return; } // if this atom being added then set the enable state atom.enable(sound.enable); if (prioritizedSounds.isEmpty()) { // List is currently empty, so just add it // insert into empty list of prioritizedSounds prioritizedSounds.add(atom); if (debugFlag) debugPrint(":addPritorizedSound() inset sound " + mirSound + " into empty priority list"); } else { // something's in the proirity list already // Since list is not empty insert sound into list. // // Order is highest to lowest priority values, and // for sounds with equal priority values, sound // inserted first get in list given higher priority. SoundRetained jSound; SoundSchedulerAtom jAtom; int j; int jsounds = (prioritizedSounds.size() - 1); float soundPriority = sound.priority; for (j=jsounds; j>=0; j--) { jAtom = (SoundSchedulerAtom)prioritizedSounds.get(j); jSound = jAtom.sound; if (debugFlag) debugPrint(": priority of sound " + jSound.sgSound + " element " + (j+1) + " of prioritized list"); if (soundPriority <= jSound.sgSound.priority) { if (j==jsounds) { // last element's priority is larger than // current sound's priority, so add this // sound to the end of the list prioritizedSounds.add(atom); if (debugFlag) debugPrint(": insert sound at list bottom"); break; } else { if (debugFlag) debugPrint( ": insert sound as list element " + (j+1)); prioritizedSounds.add(j+1, atom); break; } } } // for loop if (j < 0) { // insert at the top of the list if (debugFlag) debugPrint(": insert sound at top of priority list"); prioritizedSounds.add(0, atom); } } // else list not empty } /** * Process active Soundscapes (if there are any) and intersect these * soundscapes with the viewPlatform. * * Returns the number of soundscapes that intesect with * view volume. */ int findActiveSoundscapes() { int nSscapes = 0; int nSelectedSScapes = 0; SoundscapeRetained ss = null; SoundscapeRetained lss = null; boolean intersected = false; int nUnivSscapes = 0; UnorderList soundScapes = null; // Make a copy of references to the soundscapes in the universe // that are both switch on and have non-null (transformed) regions, // don't bother testing for intersection with view. if (universe == null) { if (debugFlag) debugPrint(".findActiveSoundscapes() univ=null"); return 0; } soundScapes = universe.soundStructure.getSoundscapeList(view); if (soundScapes == null) { if (debugFlag) debugPrint(".findActiveSoundscapes() soundScapes null"); return 0; } synchronized (soundScapes) { nUnivSscapes = soundScapes.size; if (nUnivSscapes == 0) { if (debugFlag) debugPrint( ".findActiveSoundscapes() soundScapes size=0"); return 0; } // increase arrays lengths by increments of 32 elements if (intersectedRegions.length < nSscapes) { intersectedRegions = new Bounds[nSscapes + 32]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -