/src/away3d/audio/Sound3D.as
ActionScript | 206 lines | 101 code | 23 blank | 82 comment | 3 complexity | 6c195599e6a584a73be63a84d8ae1ddb MD5 | raw file
1package away3d.audio 2{ 3 import away3d.audio.drivers.*; 4 import away3d.containers.ObjectContainer3D; 5 import away3d.events.Object3DEvent; 6 7 import flash.events.Event; 8 import flash.geom.*; 9 import flash.media.*; 10 11 /** 12 * Dispatched when end of sound stream is reached (bubbled from the internal sound object). 13 */ 14 [Event(name="soundComplete", type="flash.events.Event")] 15 16 /** 17 * <p>A sound source/emitter object that can be positioned in 3D space, and from which all audio 18 * playback will be transformed to simulate orientation.</p> 19 * 20 * <p>The Sound3D object works much in the same fashion as primitives, lights and cameras, in that 21 * it can be added to a scene and positioned therein. It is the main object, in the 3D sound API, 22 * which the programmer will interact with.</p> 23 * 24 * <p>Actual sound transformation is performed by a driver object, which is defined at the time of 25 * creation by the driver ini variable, the default being a simple pan/volume driver.</p> 26 * 27 * @see SimplePanVolumeDriver 28 */ 29 public class Sound3D extends ObjectContainer3D 30 { 31 private var _refv:Vector3D; 32 private var _driver:ISound3DDriver; 33 private var _reference:ObjectContainer3D; 34 private var _sound:Sound; 35 36 private var _paused:Boolean; 37 private var _playing:Boolean; 38 39 /** 40 * Create a Sound3D object, representing the sound source used for playback of a flash Sound object. 41 * 42 * @param sound The flash Sound object that is played back from this Sound3D object's position. 43 * For realistic results, this should be a <em>mono</em> (single-channel, non-stereo) sound stream. 44 * @param reference The reference, or "listener" object, typically a camera. 45 * @param driver Sound3D driver to use when applying simulation effects. Defaults to SimplePanVolumeDriver. 46 * @param init [optional] An initialisation object for specifying default instance properties. 47 */ 48 public function Sound3D(sound:Sound, reference:ObjectContainer3D, driver:ISound3DDriver = null, volume:Number = 1, scale:Number = 1000) 49 { 50 51 _sound = sound; 52 _reference = reference; 53 _driver = driver || new SimplePanVolumeDriver(); 54 _driver.sourceSound = _sound; 55 _driver.volume = volume; 56 _driver.scale = scale; 57 _driver.addEventListener(Event.SOUND_COMPLETE, onSoundComplete); 58 59 addEventListener(Object3DEvent.SCENE_CHANGED, onSceneChanged); 60 addEventListener(Object3DEvent.SCENETRANSFORM_CHANGED, onSceneTransformChanged); 61 _reference.addEventListener(Object3DEvent.SCENETRANSFORM_CHANGED, onSceneTransformChanged); 62 } 63 64 /** 65 * Defines the overall (master) volume of the 3D sound, after any 66 * positional adjustments to volume have been applied. This value can 67 * equally well be cotrolled by modifying the volume property on the 68 * driver used by this Sound3D instance. 69 * 70 * @see ISound3DDriver.volume 71 */ 72 public function get volume():Number 73 { 74 return _driver.volume; 75 } 76 77 public function set volume(val:Number):void 78 { 79 _driver.volume = val; 80 } 81 82 /** 83 * Defines a scale value used by the driver when adjusting sound 84 * intensity to simulate distance. The default number of 1000 means 85 * that sound volume will near the hearing threshold as the distance 86 * between listener and sound source approaches 1000 Away3D units. 87 * 88 * @see ISound3DDriver.scale 89 */ 90 public function get scaleDistance():Number 91 { 92 return _driver.scale; 93 } 94 95 public function set scaleDistance(val:Number):void 96 { 97 _driver.scale = val; 98 } 99 100 /** 101 * Returns a boolean indicating whether or not the sound is currently 102 * playing. 103 */ 104 public function get playing():Boolean 105 { 106 return _playing; 107 } 108 109 /** 110 * Returns a boolean indicating whether or not playback is currently 111 * paused. 112 */ 113 public function get paused():Boolean 114 { 115 return _paused; 116 } 117 118 /** 119 * Start (or resume, if paused) playback. 120 */ 121 public function play():void 122 { 123 _playing = true; 124 _paused = false; 125 _driver.play(); 126 } 127 128 /** 129 * Pause playback. Resume using play(). 130 */ 131 public function pause():void 132 { 133 _playing = false; 134 _paused = true; 135 _driver.pause(); 136 } 137 138 /** 139 * Stop and rewind sound file. Replay (from the beginning) using play(). 140 * To temporarily pause playback, allowing you to resume from the same point, 141 * use pause() instead. 142 * 143 * @see pause() 144 */ 145 public function stop():void 146 { 147 _playing = false; 148 _paused = false; 149 _driver.stop(); 150 } 151 152 /** 153 * Alternate between pausing and resuming playback of this sound. If called 154 * while sound is paused (or stopped), this will resume playback. When 155 * called during playback, it will pause it. 156 */ 157 public function togglePlayPause():void 158 { 159 if (_playing) 160 this.pause(); 161 else 162 this.play(); 163 } 164 165 /** 166 * @internal 167 * When scene changes, mute if object was removed from scene. 168 */ 169 private function onSceneChanged(ev:Object3DEvent):void 170 { 171 trace('scene changed'); 172 // mute driver if there is no scene available, i.e. when the 173 // sound3d object has been removed from the scene 174 _driver.mute = (_scene == null); 175 176 // Force update 177 update(); 178 179 // Re-update reference vector to force changes to take effect 180 _driver.updateReferenceVector(_refv); 181 } 182 183 /** 184 * @internal 185 * When scene transform changes, calculate the relative vector between the listener/reference object 186 * and the position of this sound source, and update the driver to use 187 * this as the reference vector. 188 */ 189 private function update():void 190 { 191 // Transform sound position into local space of the reference object ("listener"). 192 _refv = _reference.inverseSceneTransform.transformVector(sceneTransform.position); 193 _driver.updateReferenceVector(_refv); 194 } 195 196 private function onSceneTransformChanged(ev:Object3DEvent):void 197 { 198 update(); 199 } 200 201 private function onSoundComplete(ev:Event):void 202 { 203 dispatchEvent(ev.clone()); 204 } 205 } 206}