PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/externals/soundmanager/src/SoundManager2_SMSound_AS3.as

https://github.com/grandison/budo16
ActionScript | 282 lines | 224 code | 22 blank | 36 comment | 25 complexity | 5d0b0297532556533cd744fb734627d9 MD5 | raw file
  1. /*
  2. SoundManager 2: Javascript Sound for the Web
  3. ----------------------------------------------
  4. http://schillmania.com/projects/soundmanager2/
  5. Copyright (c) 2007, Scott Schiller. All rights reserved.
  6. Code licensed under the BSD License:
  7. http://www.schillmania.com/projects/soundmanager2/license.txt
  8. Flash 9 / ActionScript 3 version
  9. */
  10. package {
  11. import flash.external.*;
  12. import flash.events.*;
  13. import flash.display.Sprite;
  14. import flash.display.StageDisplayState;
  15. import flash.display.StageScaleMode;
  16. import flash.display.StageAlign;
  17. import flash.geom.Rectangle;
  18. import flash.media.Sound;
  19. import flash.media.SoundChannel;
  20. import flash.media.SoundLoaderContext;
  21. import flash.media.SoundTransform;
  22. import flash.media.SoundMixer;
  23. import flash.media.Video;
  24. import flash.net.URLRequest;
  25. import flash.utils.ByteArray;
  26. import flash.net.NetConnection;
  27. import flash.net.NetStream;
  28. public class SoundManager2_SMSound_AS3 extends Sound {
  29. public var sm: SoundManager2_AS3 = null;
  30. // externalInterface references (for Javascript callbacks)
  31. public var baseJSController: String = "soundManager";
  32. public var baseJSObject: String = baseJSController + ".sounds";
  33. public var soundChannel: SoundChannel = new SoundChannel();
  34. public var urlRequest: URLRequest;
  35. public var soundLoaderContext: SoundLoaderContext;
  36. public var waveformData: ByteArray = new ByteArray();
  37. public var waveformDataArray: Array = [];
  38. public var eqData: ByteArray = new ByteArray();
  39. public var eqDataArray: Array = [];
  40. public var usePeakData: Boolean = false;
  41. public var useWaveformData: Boolean = false;
  42. public var useEQData: Boolean = false;
  43. public var sID: String;
  44. public var sURL: String;
  45. public var justBeforeFinishOffset: int;
  46. public var didJustBeforeFinish: Boolean;
  47. public var didFinish: Boolean;
  48. public var loaded: Boolean;
  49. public var paused: Boolean;
  50. public var duration: Number;
  51. public var handledDataError: Boolean = false;
  52. public var ignoreDataError: Boolean = false;
  53. public var lastValues: Object = {
  54. bytes: 0,
  55. position: 0,
  56. volume: 100,
  57. pan: 0,
  58. nLoops: 1,
  59. leftPeak: 0,
  60. rightPeak: 0,
  61. waveformDataArray: null,
  62. eqDataArray: null,
  63. isBuffering: null
  64. };
  65. public var didLoad: Boolean = false;
  66. public var sound: Sound = new Sound();
  67. public var cc: Object;
  68. public var nc: NetConnection;
  69. public var ns: NetStream;
  70. public var st: SoundTransform;
  71. public var useNetstream: Boolean;
  72. public var useVideo: Boolean = false;
  73. public var bufferTime: Number = -1;
  74. public var lastNetStatus: String = null;
  75. public var oVideo: Video = null;
  76. public var videoWidth: Number = 0;
  77. public var videoHeight: Number = 0;
  78. public function SoundManager2_SMSound_AS3(oSoundManager: SoundManager2_AS3, sIDArg: String = null, sURLArg: String = null, usePeakData: Boolean = false, useWaveformData: Boolean = false, useEQData: Boolean = false, useNetstreamArg: Boolean = false, useVideoArg: Boolean = false, netStreamBufferTime: Number = -1) {
  79. this.sm = oSoundManager;
  80. this.sID = sIDArg;
  81. this.sURL = sURLArg;
  82. this.usePeakData = usePeakData;
  83. this.useWaveformData = useWaveformData;
  84. this.useEQData = useEQData;
  85. this.urlRequest = new URLRequest(sURLArg);
  86. this.justBeforeFinishOffset = 0;
  87. this.didJustBeforeFinish = false;
  88. this.didFinish = false; // non-MP3 formats only
  89. this.loaded = false;
  90. this.soundChannel = null;
  91. this.lastNetStatus = null;
  92. this.useNetstream = useNetstreamArg;
  93. if (this.useNetstream) {
  94. try {
  95. this.cc = new Object();
  96. this.nc = new NetConnection();
  97. // TODO: security/IO error handling
  98. // this.nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doSecurityError);
  99. // this.nc.addEventListener(IOErrorEvent.IO_ERROR, doIOError);
  100. this.nc.connect(null);
  101. this.ns = new NetStream(this.nc);
  102. this.ns.checkPolicyFile = true;
  103. // bufferTime reference: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/NetStream.html#bufferTime
  104. if (netStreamBufferTime != -1) {
  105. this.ns.bufferTime = netStreamBufferTime; // set to 0.1 or higher. 0 is reported to cause playback issues with static files.
  106. }
  107. this.st = new SoundTransform();
  108. this.cc.onMetaData = this.metaDataHandler;
  109. this.ns.client = this.cc;
  110. this.ns.receiveAudio(true);
  111. if (useVideoArg) {
  112. this.useVideo = true;
  113. this.oVideo = new Video();
  114. this.ns.receiveVideo(true);
  115. this.sm.stage.addEventListener(Event.RESIZE, this.resizeHandler);
  116. this.oVideo.smoothing = true; // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Video.html#smoothing
  117. this.oVideo.visible = false; // hide until metadata received
  118. this.sm.addChild(this.oVideo);
  119. this.oVideo.attachNetStream(this.ns);
  120. writeDebug('setting video w/h to stage: ' + this.sm.stage.stageWidth + 'x' + this.sm.stage.stageHeight);
  121. this.oVideo.width = this.sm.stage.stageWidth;
  122. this.oVideo.height = this.sm.stage.stageHeight;
  123. }
  124. } catch(e: Error) {
  125. writeDebug('netStream error: ' + e.toString());
  126. }
  127. }
  128. }
  129. public function resizeHandler(e: Event) : void {
  130. // scale video to stage dimensions
  131. // probably less performant than using native flash scaling, but that doesn't quite seem to work. I'm probably missing something simple.
  132. this.oVideo.width = this.sm.stage.stageWidth;
  133. this.oVideo.height = this.sm.stage.stageHeight;
  134. }
  135. public function writeDebug(s: String, bTimestamp: Boolean = false) : Boolean {
  136. return this.sm.writeDebug(s, bTimestamp); // defined in main SM object
  137. }
  138. public function doNetStatus(e: NetStatusEvent) : void {
  139. writeDebug('netStatusEvent: ' + e.info.code);
  140. }
  141. public function metaDataHandler(infoObject: Object) : void {
  142. /*
  143. var data:String = new String();
  144. for (var prop:* in infoObject) {
  145. data += prop+': '+infoObject[prop]+' ';
  146. }
  147. ExternalInterface.call('soundManager._writeDebug','Metadata: '+data);
  148. */
  149. if (this.oVideo) {
  150. // set dimensions accordingly
  151. if (!infoObject.width && !infoObject.height) {
  152. writeDebug('No width/height specified');
  153. infoObject.width = 0;
  154. infoObject.height = 0;
  155. }
  156. writeDebug('video dimensions: ' + infoObject.width + 'x' + infoObject.height + ' (w/h)');
  157. this.videoWidth = infoObject.width;
  158. this.videoHeight = infoObject.height;
  159. // implement a subset of metadata to pass over EI bridge
  160. // some formats have extra stuff, eg. "aacaot", "avcprofile"
  161. // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html
  162. var oMeta: Object = new Object();
  163. var item: Object = null;
  164. for (item in infoObject) {
  165. // exclude seekpoints for now, presumed not useful and overly large.
  166. if (item != 'seekpoints') {
  167. oMeta[item] = infoObject[item];
  168. }
  169. }
  170. ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onmetadata", oMeta);
  171. writeDebug('showing video for ' + this.sID);
  172. this.oVideo.visible = true; // show ze video!
  173. }
  174. if (!this.loaded) {
  175. ExternalInterface.call(baseJSObject + "['" + this.sID + "']._whileloading", this.bytesLoaded, this.bytesTotal, infoObject.duration);
  176. }
  177. this.duration = infoObject.duration * 1000;
  178. // null this out for the duration of this object's existence.
  179. // it may be called multiple times.
  180. this.cc.onMetaData = function (infoObject: Object) : void {}
  181. }
  182. public function getWaveformData() : void {
  183. // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()
  184. SoundMixer.computeSpectrum(this.waveformData, false, 0); // sample wave data at 44.1 KHz
  185. this.waveformDataArray = [];
  186. for (var i: int = 0, j: int = this.waveformData.length / 4; i < j; i++) { // get all 512 values (256 per channel)
  187. this.waveformDataArray.push(int(this.waveformData.readFloat() * 1000) / 1000);
  188. }
  189. }
  190. public function getEQData() : void {
  191. // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()
  192. SoundMixer.computeSpectrum(this.eqData, true, 0); // sample EQ data at 44.1 KHz
  193. this.eqDataArray = [];
  194. for (var i: int = 0, j: int = this.eqData.length / 4; i < j; i++) { // get all 512 values (256 per channel)
  195. this.eqDataArray.push(int(this.eqData.readFloat() * 1000) / 1000);
  196. }
  197. }
  198. public function start(nMsecOffset: int, nLoops: int) : void {
  199. this.sm.currentObject = this; // reference for video, full-screen
  200. if (this.useNetstream) {
  201. writeDebug('start: seeking to ' + nMsecOffset);
  202. this.cc.onMetaData = this.metaDataHandler;
  203. this.ns.seek(nMsecOffset);
  204. if (!this.didLoad) {
  205. this.ns.play(this.sURL);
  206. this.didLoad = true;
  207. } else {
  208. this.ns.resume(); // get the sound going again
  209. }
  210. // this.ns.addEventListener(Event.SOUND_COMPLETE, _onfinish);
  211. this.applyTransform();
  212. } else {
  213. this.soundChannel = this.play(nMsecOffset, nLoops);
  214. this.addEventListener(Event.SOUND_COMPLETE, _onfinish);
  215. this.applyTransform();
  216. }
  217. }
  218. private function _onfinish() : void {
  219. this.removeEventListener(Event.SOUND_COMPLETE, _onfinish);
  220. }
  221. public function loadSound(sURL: String, bStream: Boolean) : void {
  222. if (this.useNetstream) {
  223. if (this.didLoad != true) {
  224. ExternalInterface.call('loadSound(): loading ' + this.sURL);
  225. this.ns.play(this.sURL);
  226. this.didLoad = true;
  227. }
  228. // this.addEventListener(Event.SOUND_COMPLETE, _onfinish);
  229. this.applyTransform();
  230. } else {
  231. try {
  232. this.didLoad = true;
  233. this.urlRequest = new URLRequest(sURL);
  234. this.soundLoaderContext = new SoundLoaderContext(1000, true); // check for policy (crossdomain.xml) file on remote domains - http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundLoaderContext.html
  235. this.load(this.urlRequest, this.soundLoaderContext);
  236. } catch(e: Error) {
  237. writeDebug('error during loadSound(): ' + e.toString());
  238. }
  239. }
  240. }
  241. public function setVolume(nVolume: Number) : void {
  242. this.lastValues.volume = nVolume / 100;
  243. this.applyTransform();
  244. }
  245. public function setPan(nPan: Number) : void {
  246. this.lastValues.pan = nPan / 100;
  247. this.applyTransform();
  248. }
  249. public function applyTransform() : void {
  250. var st: SoundTransform = new SoundTransform(this.lastValues.volume, this.lastValues.pan);
  251. if (this.useNetstream) {
  252. this.ns.soundTransform = st;
  253. } else if (this.soundChannel) {
  254. this.soundChannel.soundTransform = st; // new SoundTransform(this.lastValues.volume, this.lastValues.pan);
  255. }
  256. }
  257. }
  258. }