【问题标题】:Embed vs Dynamically Loading sounds嵌入与动态加载声音
【发布时间】:2011-09-08 12:10:48
【问题描述】:

只是想知道是否有人可以帮助我。我是 actionscript 的新手,正在构建一个应用程序,在单击按钮时播放一些声音。

它有 5 个标签,用户可以选择每个标签播放大约 10 种声音。

我最初是在运行时加载声音,所以每当用户单击按钮播放该声音时,我会执行以下操作:

var sound:Sound = new Sound(new URLRequest("assets/hello.mp3"));
sound.play();

我不确定,但我认为这不是很好,因为如果用户按下按钮太多次,我会一遍又一遍地加载那个声音。

然后我考虑在每个视图中嵌入声音(每个选项卡都有一个视图),因此每当加载视图时都会嵌入声音。我认为这是一个更好的选择,但仍然有点不确定嵌入是如何工作的。

[Embed('assets/hello.mp3')] private var hello_mp3:Class;

我想它只是在编译 swf 时嵌入 mp3 文件(使其更大),但一旦应用程序启动或再次初始化该视图,它们将不再加载。

我的问题是:这是正确的做法吗?有没有更好的方法可以做到这一点?是否为我的问题嵌入了正确的解决方案?

提前致谢

【问题讨论】:

    标签: actionscript-3 actionscript


    【解决方案1】:

    第一个解决方案效果很好,它不会使您的 SWf 变大,并且一旦加载了一次声音,它将被 Flash Player 缓存,因此不会一次又一次地加载声音。

    这是一种更高效的方法,不会加载未播放的声音。

    请记住,第一次按下按钮时,由于声音正在加载,您可能会遇到轻微的延迟。

    为了避免这种情况,您可以将一些声音加载为外部资产,这意味着在您的 SWF 加载后,您可以调用一个函数来加载部分或全部声音,具体取决于应用程序的需要。您的 SWF 不会臃肿,而且按钮点击会更灵敏。

    【讨论】:

      【解决方案2】:

      听起来你需要一个 SoundManager 类或类似的东西来缓存你需要的声音,这样你就可以随时播放它们,而且它们只会被加载一次。像这样的类,你只需要一个类的实例,是单例的好候选。有很多方法可以实现单例设计。在actionscript中,我最喜欢的方式是这样的:

      //in SoundManager.as
      public static var instance:SoundManager = new SoundManager();
      

      简单,而且有效。由于计划是您只需要一个 SoundManager,因此您现在可以在代码中的其他任何位置获取该实例,如下所示:

      var soundManager:SoundManager = SoundManager.instance;
      
      //or, more likely you can just use it in-line like this
      SoundManager.instance.myMethod();
      

      所以现在你已经有了你的 SoundManager。让我们将其设置为保留声音缓存,以便它们只加载一次:

      // in SoundManager.as
      
      private var _soundCache:Array = [];
      
      public function getSound(soundName:String):Sound {
      
          var testSound:Sound = _soundCache[soundName] as Sound;
      
          if(!testSound) {    //if the sound isn't loaded yet, testSound will be null
      
              //the sound isn't there, so lets load it
              var newSound:Sound = new Sound(new URLRequest(soundName));
              _soundCache[soundName] = newSound;
              return newSound;
      
          }
      
          //if we made it this far it means the sound was in the cache, so we return it
          return testSound;
      
      }
      

      然后,您只需加载一次声音!当您想获得声音时,很简单:

      var mySound:Sound = SoundManager.instance.getSound("mySound.mp3");
      

      如果您在使用此代码时遇到问题,请告诉我,但希望这足以让您走上正轨。

      【讨论】:

        【解决方案3】:

        在我看来,您应该在开始时加载所有声音,并将每个声音的引用存储在您可以随时访问的位置。一个简单的例子是将每个声音存储在一个数组中。我为此示例创建了一个类似但更强大的应用程序:

        sounds.xml

        <?xml version="1.0" encoding="utf-8" ?>
        <sounds>
            <sound name="sound1" url="sound/sound1.mp3" />
            <sound name="sound2" url="sound/sound2.mp3" />
            <sound name="sound3" url="sound/sound3.mp3" />
            <sound name="sound4" url="sound/sound4.mp3" />
            <sound name="sound5" url="sound/sound5.mp3" />
        </sounds>
        

        Main.as(文档类):

        package 
        {
            import flash.display.Sprite;
            import flash.events.Event;
            import flash.media.SoundChannel;
            import flash.net.URLLoader;
            import flash.net.URLRequest;
        
            public class Main extends Sprite 
            {
                private var _soundLibrary:SoundLibrary;
        
                public function Main():void 
                {
                    if (stage) init() else addEventListener(Event.ADDED_TO_STAGE, init);
        
                }// end function
        
                private function init(e:Event = null):void 
                {
                    removeEventListener(Event.ADDED_TO_STAGE, init);
        
                    var urlLoader:URLLoader = new URLLoader(new URLRequest("xml/sounds.xml"));
                    urlLoader.addEventListener(Event.COMPLETE, onUrlLoaderComplete);
        
                }// end function
        
                private function onUrlLoaderComplete(e:Event):void
                {
                    _soundLibrary = new SoundLibrary(XML(URLLoader(e.target).data));
                    _soundLibrary.addEventListener(Event.COMPLETE, onSoundLibraryComplete);
        
                }// end function
        
                private function onSoundLibraryComplete(e:Event):void
                {
                    var soundChannel:SoundChannel = _soundLibrary.getSound("sound3").play();
        
                }// end function
        
            }// end class
        
        }// end package
        
        
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.media.Sound;
        import flash.net.URLRequest;
        
        internal class SoundLibrary extends EventDispatcher
        {
            private var _xml:XML;
            private var _length:int;
            private var _counter:int;
            private var _soundLibraryItems:Vector.<SoundLibraryItem>;
        
            public function SoundLibrary(xml:XML):void
            {
                _xml = xml;
                _length = _xml.children().length();
                _soundLibraryItems = new Vector.<SoundLibraryItem>();
        
                loadSounds();
        
            }// end function
        
            public function getSound(name:String):Sound
            {
                var sound:Sound;
        
                for (var i:int = 0; i < _soundLibraryItems.length; i++)
                {
                    if (_soundLibraryItems[i].name == name)
                    sound = _soundLibraryItems[i].sound;
        
                }// end for
        
                if (!sound) throw new ArgumentError("No sound object matches specified name");
        
                return sound;
        
            }// end function
        
            private function loadSounds():void
            {
                for (var i:int = 0; i < _length; i++)
                {
                    var sound:Sound = new Sound(new URLRequest(_xml.children()[i].@url));
                    sound.addEventListener(Event.COMPLETE, onSoundComplete);    
        
                }// end for
        
            }// end function
        
            private function onSoundComplete(e:Event):void
            {
                _soundLibraryItems.push(new SoundLibraryItem(_xml.children()[_counter].@name, Sound(e.target)));
        
                if (++_counter == _length) dispatchEvent(new Event(Event.COMPLETE));
        
            }// end function
        
        }// end class
        
        internal class SoundLibraryItem
        {
            private var _name:String; 
            private var _sound:Sound;
        
            public function get name():String { return _name }
            public function get sound():Sound { return _sound }
        
            public function SoundLibraryItem(name:String, sound:Sound)
            {
                _name = name; _sound = sound;
        
            }// end function
        
        }// class
        

        [更新]

        总结

        首先加载sounds.xml,然后在完成时将其解析为SoundLibrary 的新实例。

        SoundLibrary 处理从 xml 加载声音,然后将每个加载的 Sound 对象解析为 SoundLibraryItem 的新实例。

        SoundLibraryItem 只存储Sound 对象的名称以及Sound 对象本身。创建所有 SoundLibraryItem 对象后,SoundLibrary 对象将分派具有 Event.COMPLETE 类型的 Event 对象。

        当事件被调度时,SoundLibrary 对象上的事件侦听器调用onSoundLibraryComplete() 事件处理程序。

        最后,SoundLibrary 对象的getSound() 方法用于通过name 参数获取先前加载的Sound 对象之一。然后使用SoundChannel 对象调用Sound 对象的play() 方法。

        【讨论】:

          【解决方案4】:

          在我看来

          嵌入东西绝不是一种方法

          优点:

          1. 您在同一个文件中有任何内容 = 1 次加载 ( 好吧,这不是真正的专业人士......)

          缺点:

          1. 加载整个文件需要更长的时间 应用程序(用户不喜欢 等等)

          2. 如果你想改变声音,你必须重新编译所有东西

          3. 可扩展性优势

          4. 我相信人们可以帮助我解决更多缺点 ;)

          希望对你有帮助

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-28
            • 1970-01-01
            • 2019-04-07
            • 1970-01-01
            • 1970-01-01
            • 2011-12-02
            相关资源
            最近更新 更多