📄 soundretained.java
字号:
schedulingRegion = (Bounds) region.clone(); if (staticTransform != null) { schedulingRegion.transform(staticTransform.transform); } // QUESTION: Clone into transformedRegion IS required. Why? transformedRegion = (Bounds) schedulingRegion.clone(); if (debugFlag) debugPrint("setSchedulingBounds for a non-null region"); } else { schedulingRegion = null; // QUESTION: Is transformedRegion of node (not mirror node) // even looked at??? transformedRegion = null; if (debugFlag) debugPrint("setSchedulingBounds for a NULL region"); } // XXXX: test that this works - could not new Bounds() since // Bounds is an abstract class and can't be instantiated dispatchAttribChange(BOUNDS_DIRTY_BIT, region); if (source != null && source.isLive()) { notifySceneGraphChanged(false); } } /** * Get the Sound's scheduling region. * @return this Sound's scheduling region information */ Bounds getSchedulingBounds() { Bounds b = null; if (this.schedulingRegion != null) { b = (Bounds) schedulingRegion.clone(); if (staticTransform != null) { Transform3D invTransform = staticTransform.getInvTransform(); b.transform(invTransform); } } return b; } /** * Set the Sound's scheduling region to the specified Leaf node. */ void setSchedulingBoundingLeaf(BoundingLeaf region) { int i; int numSnds = numMirrorSounds; if (numMirrorSounds == 0) numSnds = 1; if ((boundingLeaf != null) && (source != null && source.isLive())) { // Remove the mirror lights as users of the original bounding leaf for (i = 0; i < numSnds; i++) { boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorSounds[i]); } } if (region != null) { boundingLeaf = (BoundingLeafRetained)region.retained; // Add all mirror sounds as user of this bounding leaf if (source != null && source.isLive()) { for (i = 0; i < numSnds; i++) { boundingLeaf.mirrorBoundingLeaf.addUser(mirrorSounds[i]); } } } else { boundingLeaf = null; } // XXXX: since BoundingLeaf constructor only takes Bounds // test if region passed into dispatchAttribChange correctly. dispatchAttribChange(BOUNDING_LEAF_DIRTY_BIT, region); if (source != null && source.isLive()) { notifySceneGraphChanged(false); } } /** * Get the Sound's scheduling region */ BoundingLeaf getSchedulingBoundingLeaf() { if (boundingLeaf != null) { return((BoundingLeaf)boundingLeaf.source); } else { return null; } } // The update Object function. synchronized void updateMirrorObject(Object[] objs) { Transform3D trans = null; int component = ((Integer)objs[1]).intValue(); if (component == -1) { // update everything // object 2 contains the mirror object that needs to be // updated initMirrorObject(((SoundRetained)objs[2])); } // call the parent's mirror object update routine super.updateMirrorObject(objs); } void updateBoundingLeaf(long refTime) { // This is necessary, if for example, the region // changes from sphere to box. if (boundingLeaf != null && boundingLeaf.switchState.currentSwitchOn) { transformedRegion = boundingLeaf.transformedRegion; } else { // evaluate schedulingRegion if not null if (schedulingRegion != null) { transformedRegion = schedulingRegion.copy(transformedRegion); transformedRegion.transform(schedulingRegion, getLastLocalToVworld()); } else { transformedRegion = null; } } } /** * Set sound's proirity value. * @param priority value used to order sound's importance for playback. */ void setPriority(float rank) { if (rank == this.priority) // changing priority is expensive in the sound scheduler(s) // so only dispatch a message if 'new' priority value is really // different return; this.priority = rank; dispatchAttribChange(PRIORITY_DIRTY_BIT, (new Float(rank))); if (source != null && source.isLive()) { notifySceneGraphChanged(false); } } /** * Retrieves sound's priority value. * @return sound priority value */ float getPriority() { return (this.priority); } /** * Retrieves sound's duration in milliseconds * @return sound's duration, returns DURATION_UNKNOWN if duration could * not be queried from the audio device */ long getDuration() { return (duration); } /** * Set scale factor * @param scaleFactor applied to sound playback rate */ void setRateScaleFactor(float scaleFactor) { this.rate = scaleFactor; dispatchAttribChange(RATE_DIRTY_BIT, (new Float(scaleFactor))); if (source != null && source.isLive()) { notifySceneGraphChanged(false); } } /** * Retrieves sound's rate scale factor * @return sound rate scale factor */ float getRateScaleFactor() { return (this.rate); } void changeAtomList(SoundSchedulerAtom atom, int loadStatus) { if (atom == null) return; if (loadStatus == SoundRetained.LOAD_COMPLETE) { // atom is successfully loaded, so add this atom to array of atoms // associated with this sound, if not already in list for (int i=0; i<atomCount; i++) { if (atom == loadedAtoms[i]) return; } // add atom to list atomCount++; int currentArrayLength = loadedAtoms.length; if (atomCount > currentArrayLength) { // expand array - replace with a larger array loadedAtoms = new SoundSchedulerAtom[2*currentArrayLength]; } loadedAtoms[atomCount-1] = atom; // store reference to new atom // all atoms sample durations SHOULD be the same so store it in node this.duration = atom.sampleLength; // XXXX: refine later? in ms } else { // atom is NOT loaded or has been unloaded; remove from list if (atomCount == 0) return; // remove atom from array of playing atoms if it is in list boolean atomFound = false; int i; for (i=0; i<atomCount; i++) { if (atom == loadedAtoms[i]) { atomFound = true; continue; } } if (!atomFound) return; // otherwise remove atom from list by close up list for (int j=i; j<atomCount; j++) { loadedAtoms[j] = loadedAtoms[j+1]; } atomCount--; if (atomCount == 0) this.duration = Sound.DURATION_UNKNOWN; // clear sound duration } } /** * Retrieves sound's ready state for ALL active views. * For this node, the list of sound scheduler atoms associated with * each view is maintained. The 'loaded' (=is ready) state is * true only if the following are true for all views/sound schedulers: * * <ul> * 1) the Sound node has a non-null sound data and this data has * sucessfully been loaded/opened/copied/attached;<br> * 2) the Sound node is live;<br> * 3) there is at least one active View in the Universe; and<br> * 4) an instance of an AudioDevice is attached to the current * PhysicalEnvironment. * </ul> * * @return true if potentially playable (audibly or silently); false otherwise */ boolean isReady() { // all the atoms in the atom list must be are ready for this // method to return true // if any non-null atoms are found NOT ready, return false. boolean atomFoundReady = true; for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; else if (atom.loadStatus == SoundRetained.LOAD_COMPLETE) { atomFoundReady = true; continue; } else return false; } if (atomFoundReady) // at least on atom found ready return true; else // not even one atom is associated with node so none are loaded return false; } /** * Retrieves sound's ready state for a particular view. * For this node, the list of sound scheduler atoms associated with * each view is maintained. The 'loaded' (=is ready) state is * true only if the following are true for the given view: * * <ul> * 1) the Sound node has a non-null sound data and this data has * sucessfully been loaded/opened/copied/attached;<br> * 2) the Sound node is live;<br> * 3) the given View is active in the Universe; and<br> * 4) an instance of an AudioDevice is attached to the current * PhysicalEnvironment. * </ul> * * @param viewRef view to test sound readiness for * @return true if potentially playable (audibly or silently); false otherwise */ boolean isReady(View viewRef) { // if an atom in the atom list that is associated with the // given view is found and has been loaded than return true, // otherwise return false. if (viewRef == null) return false; for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.soundScheduler.view == viewRef) if (atom.loadStatus != SoundRetained.LOAD_COMPLETE) return false; else return true; else // atom is not associated with given referenced view continue; } return false; // sound scheduler atom for given view not found } // ******************************* // Play Status - isPlaying states // ******************************* /** * Retrieves sound's playing status * true if potentially audible (enabled and active) on ANY audio device * false otherwise * @return sound playing flag */ boolean isPlaying() { for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE) return true; else continue; // look for at lease one atom that is playing } // not even one atom is associated with this node so none are playing return false; } /** * Retrieves sound's playing status for a particular view * true if potentially audible (enabled and active) on audio device * associated with the given view * false otherwise * @param viewRef view to test sound playing state for * @return sound playing flag */ boolean isPlaying(View viewRef) { if (viewRef == null) return false; for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.soundScheduler.view == viewRef) { if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE) return true; else return false; } else // atom is not associated with given referenced view continue; } return false; // atom associated with this view not found in list } /** * Retrieves sound's playing silently status * true if enabled but not active (on any device) * false otherwise * @return sound playing flag */ boolean isPlayingSilently() { for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.status == SoundSchedulerAtom.SOUND_SILENT) return true; else return false; } return false; // atom not found in list or not playing audibilly } /** * Retrieves sound's playing silently status for a particular view * true if potentially audible (enabled and active) on audio device * associated with the given view * false otherwise * @param viewRef view to test sound playing silently state for * @return sound playing flag */ boolean isPlayingSilently(View viewRef) { if (viewRef == null) return false; for (int i=0; i<atomCount; i++) { SoundSchedulerAtom atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.soundScheduler.view == viewRef) { if (atom.status == SoundSchedulerAtom.SOUND_SILENT) return true; else return false; } else // atom is not associated with given referenced view continue; } return false; // atom associated with this view not found in list } /** * Retrieves number of channels allocated for this sound on the primary * view's audio device. * @return number of channels used by sound across all devices */ int getNumberOfChannelsUsed() { // retrieves the number of channels used by the atom that is: // loaded, and // playing either audibily or silently // on the device associated with the primary view. View primaryView = this.universe.getCurrentView(); if (primaryView == null) return 0; // find atom associated with primary view (VirtualUniverse currentView) // then return the number of channels associated with that atom SoundSchedulerAtom atom; for (int i=0; i<atomCount; i++) { atom = loadedAtoms[i]; if (atom == null || atom.soundScheduler == null) continue; if (atom.soundScheduler.view == primaryView) { return atom.numberChannels; } } return 0; // atom associated with primary view not found } /** * Retrieves number of channels allocated for this sound on the audio
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -