As3音樂播放器教程

作者: dymkkk

性質: 原創

閱讀次數: 12506

發表時間: 2010-02-02 09:14:21


山东20选5最新开奖结果 www.vyjto.com 2009年的最后一天了,送ws的朋友們一個播放器吧!貌似很有記念意義。按慣例先看一下最終效果:呵呵,界面是我自己在ps中畫的,感覺也不是很丑。


 

 

 

源文件下載

那么開始吧!大家先下載一下源文件。對著源文件的結構看教程。我將整個播放器做到一個元件中(Control_panel),再給它綁定一個類(sound_lib.Control_panel),所有的代碼就寫在這個類里面了。這樣做的好處是:日后要用到它時,直接把Control_panel元件拖到你要用的地方就Ok了!
接下來就是code了:要做音樂播放器,最重要的兩個類當然就是Sound和SoundChannel。
先試一下,怎樣讓一首mp3播放起來:

 

//建立一個Sound類
sound=new Sound()
//加載mp3文件
sound.load(new URLRequest(“你的mp3路徑”))
//播放
sound.play()

Ok了!
完整代碼:

 

package sound_lib{
	import flash.display.*
	import flash.media.Sound
	import flash.media.SoundChannel
	import flash.net.URLRequest
	public class Control_panel extends MovieClip{
		private var sound:Sound
		private const sound_url:String="sound_data/m01.mp3"
		public function Control_panel(){
			init()
		}
		private function init(){
			sound_init()
		}
		function sound_init(){
			sound=new Sound()
			sound.load(new URLRequest(sound_url))
			sound.play()
		}
	}
}

Ctrl+Enter一下。是不是聽到音樂了????沒聽到?看看sound_data目錄下是否放了mp3文件沒?如果一切正常的話,你現在應該在享受你的音樂了。
呵呵。不過別忘了大多數播放器是要用在web上的。有時候聲音播放的速度可能比下載的速度還要快,這種情況下聲音播放就會暫停等待數據下載,為了更好的處理這個環節,我們可以設置一個數據緩沖區,當聲音數據下載到一定數量時再進行播放,這樣的話即使下載速度偶爾變慢也不會影響正常播放。默認下Sound對象只創建1秒鐘的緩沖,也就是說要想立即播放也需要等待1秒鐘的緩沖,緩沖區的數據播放完后要想再次播放還要至少等1秒鐘緩沖時間。顯然如果網速較慢的話且緩沖為1秒時,在這種情況下音樂的播放將會給人很”卡”的感覺。所以我們必需手動設置一下緩沖:
設置緩沖需要用到SoundLoaderContext類:建立一個SoundLoaderContext對象,然后設置它的bufferTime屬性就行了。最后將SoundLoaderContext對象傳給sound對象的load()方法的參數就行了。

code
//建立一個SoundLoaderContext類,設置bufferTime為5秒
var buffer:SoundLoaderContext=new SoundLoaderContext(5000)
sound=new Sound()
sound.load(new URLRequest(sound_url),buffer)
sound.play()
:
聲音的暫停與回放
這樣,即使放到web上也不成問題了。不過現在只是能正常播放了,我們還得控制它才行嘛!最常見的控制就是暫停與回放了。聲音的暫停與回放不像視頻流那樣,可以直接pause和resume來操作??純碨oun類,大家可能會調用Sound對象的close( )方法可以停止播放,但是這樣也停止了聲音流,要想重新播放,必須再次調用load( )方法。這顯然不是我們想要的。這里我們終于要用到上面所提到的SoundChannel了,其實對音頻的絕大多數操作都是SoundChannel類來完成的。SoundChannel的stop()方法可以讓音樂暫停而不影響聲音流的中斷。于是我們可以用SoundChannel對象的stop()方法與Sound對象的play()方法來暫停與回流音頻流。但是,當再次調用play( )方法時,音樂會從頭開始播放而不是從暫停的地方開始,這個時候就要用到SoundChannel類的position屬性了:position屬性是用來記錄音樂播放頭的。我們可以在暫停時,記錄下position的值,然后再次調play()時,將它傳給play()方法的參數。這樣就達到了最終目:
code:
sound_channel.stop()
//記錄position屬性
position=sound_channel.position
sound_channel=sound.play(position)
完整代碼:
package sound_lib{
	import flash.display.*
	import flash.media.Sound
	import flash.media.SoundChannel
	import flash.media.SoundLoaderContext
	import flash.events.*
	import flash.net.URLRequest
	public class Control_panel extends MovieClip{
		private var sound:Sound
		private const sound_url:String="sound_data/m01.mp3"
		private var sound_channel:SoundChannel
		private var position:int
		private var is_play:Boolean
		public function Control_panel(){
			addEventListener(Event.ADDED_TO_STAGE,add_to_stage)
		}
		private function add_to_stage(_evt:Event):void{
			init()
		}
		private function init(){
			sound_init()
			control_init()
		}
		//==================sound part====================//
		function sound_init(){
			var buffer:SoundLoaderContext=new SoundLoaderContext(5000)
			sound=new Sound()
			sound.load(new URLRequest(sound_url),buffer)
			sound_channel=sound.play()
			is_play=true
			play_mc.visible=false
		}
		//===================control part=================//
		function control_init(){
			pause_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
			play_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
		}
		private function is_play_Handler(_evt:MouseEvent):void{
			if(is_play){
				is_play=false
				position=sound_channel.position
				sound_channel.stop()
				play_mc.visible=true
				pause_mc.visible=false
			}else{
				is_play=true
				sound_channel=sound.play(position)
				play_mc.visible=false
				pause_mc.visible=true
			}
		}
	}
}
Ctrl+Enter一下。Ok了吧?
跟蹤聲音的加載進度與播放進度
要得到聲音的加載進度是很簡單的,Sound類本身有bytesLoaded屬性與bytesTotal屬性。只要在progress事件中監測到這個屬性值就Ok了具體操作如下:
private function sound_loading_Handler(_evt:ProgressEvent):void{
	var loaded_per=Math.ceil(100*_evt.bytesLoaded/_evt.bytesTotal)/100
	scroll_bar.loading_bar.scaleX=loaded_per
}
// loaded_per就是加載進度的百分比了,簡單吧!
不過用戶肯定不滿足于只看到加載進度,他們更希望能看到聲音的播放進度并能控制播放進度。要得到播進度,必須知道兩個值:音樂的長度和當前的播放位置。這兩個屬性分別在兩不同的類里。長度屬性在sound類里,播放位置在SoundChannel類里,這兩個值相除就是播放進度百分比。呵呵,就這么簡單!不過好像高興得有點早了:sound類的length屬性是不確定的,直到聲音被下載完才確定,也就說它只表示已經被下載的那部分數據的長度,舉個例子說,如果一個10分鐘的音樂已下載了10%,那么length報告歌曲長度為1分鐘(length和position的單位都是毫秒)。不過從我上面的例子不難看出,只要長度除以加載進度百分比即可算出實際長度即sound_length/loaded_per。
嗯原理搞清楚了就來試試吧:
code:
	var loaded=sound.bytesLoaded
	var total=sound.bytesTotal
	sound_length=sound.length
	if(total>0){
		var loaded_per=loaded/total
		scroll_bar.loading_bar.scaleX=loaded_per
		sound_length=length/loaded_per
		position=sound_channel.position
		var played_per=position/sound_length
	}
好了。跟據以上思路再整理一下你的code:
package sound_lib{
	import flash.display.*
	import flash.media.Sound
	import flash.media.SoundChannel
	import flash.media.SoundLoaderContext
	import flash.events.*
	import flash.net.URLRequest
	public class Control_panel extends MovieClip{
		private var sound:Sound
		private const sound_url:String="sound_data/m01.mp3"
		private var sound_channel:SoundChannel
		private var position:int
		private var sound_length
		private var is_play:Boolean
		private var loadEnd:Boolean=false
		public function Control_panel(){
			addEventListener(Event.ADDED_TO_STAGE,add_to_stage)
		}
		private function add_to_stage(_evt:Event):void{
			init()
		}
		private function init(){
			sound_init()
			control_init()
		}
		//==================sound part====================//
		function sound_init(){
			var buffer:SoundLoaderContext=new SoundLoaderContext(5000)
			sound=new Sound()
			sound.load(new URLRequest(sound_url),buffer)
			sound_channel=sound.play()
			sound.addEventListener(ProgressEvent.PROGRESS,sound_loading_Handler)
			is_play=true
			play_mc.visible=false
		}
		//===================control part=================//
		function control_init(){
			pause_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
			play_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
			addEventListener(Event.ENTER_FRAME,progress_Handler)
		}
		private function is_play_Handler(_evt:MouseEvent):void{
			if(is_play){
				is_play=false
				position=sound_channel.position
				sound_channel.stop()
				play_mc.visible=true
				pause_mc.visible=false
			}else{
				is_play=true
				sound_channel=sound.play(position)
				play_mc.visible=false
				pause_mc.visible=true
			}
		}
		private function sound_loading_Handler(_evt:ProgressEvent):void{
			var loaded_per=Math.ceil(100*_evt.bytesLoaded/_evt.bytesTotal)/100
			if(loaded_per>=100) loadEnd=true
			scroll_bar.loading_bar.scaleX=loaded_per
		}
		private function progress_Handler(_evt:Event):void{
			var loaded=sound.bytesLoaded
			var total=sound.bytesTotal
			sound_length=sound.length
			if(total>0){
				var loaded_per=loaded/total
				if(loaded_per>=1) loadEnd=true
				scroll_bar.loading_bar.scaleX=loaded_per
				sound_length=sound_length/loaded_per
				position=sound_channel.position
				var played_per=position/sound_length
				scroll_bar.dragger.x=(scroll_bar.scroll_bg.width-scroll_bar.dragger.width)*played_per
			}
		}
	}
}
呼。。。我是不是講得太啰嗦了?繼續吧。
這才只能讓用戶看到播放進度而以。下面我們還要讓用戶能控制它。要控制它用到了我們常見的滾動條。由于滾動條是我們很常用的東東,所以我把它寫成了一個類。(Sound_lib/Scroll_bar.as),類很簡單,如果看不懂的話,可以參考控制音量的滾動條。其實這里用Scroll_bar.as不大合適,不過我還是想偷一下懶!
說到這里,怎么定位播放頭呢?想想“聲音的暫停與回放”是怎么做的,我們就可以得找出辦法了用sound.play(position)。Position的值就更容易得到了: sound_length* per。但是這里值得注意的是play()之前要把之前的sound_channel 停止,要不就出現多重聲音了。。。OK了。再跟據以上思路完善一下你的code吧!
package sound_lib{
	import flash.display.*
	import flash.media.Sound
	import flash.media.SoundChannel
	import flash.media.SoundLoaderContext
	import flash.events.*
	import flash.net.URLRequest
	public class Control_panel extends MovieClip{
		private var sound:Sound
		private const sound_url:String="sound_data/m01.mp3"
		private var sound_channel:SoundChannel
		private var position:int
		private var sound_length
		private var is_play:Boolean
		private var loadEnd:Boolean=false
		public function Control_panel(){
			addEventListener(Event.ADDED_TO_STAGE,add_to_stage)
		}
		private function add_to_stage(_evt:Event):void{
			init()
		}
		private function init(){
			sound_init()
			control_init()
		}
		//==================sound part====================//
		function sound_init(){
			var buffer:SoundLoaderContext=new SoundLoaderContext(5000)
			sound=new Sound()
			sound.load(new URLRequest(sound_url),buffer)
			sound_channel=sound.play()
			sound.addEventListener(ProgressEvent.PROGRESS,sound_loading_Handler)
			is_play=true
			play_mc.visible=false
		}
		//===================control part=================//
		function control_init(){
			pause_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
			play_mc._btn.addEventListener(MouseEvent.CLICK,is_play_Handler)
			addEventListener(Event.ENTER_FRAME,progress_Handler)
		}
		private function is_play_Handler(_evt:MouseEvent):void{
			if(is_play){
				is_play=false
				position=sound_channel.position
				sound_channel.stop()
				play_mc.visible=true
				pause_mc.visible=false
			}else{
				is_play=true
				sound_channel=sound.play(position)
				play_mc.visible=false
				pause_mc.visible=true
			}
		}
		private function sound_loading_Handler(_evt:ProgressEvent):void{
			var loaded_per=Math.ceil(100*_evt.bytesLoaded/_evt.bytesTotal)/100
			if(loaded_per>=100) loadEnd=true
			scroll_bar.loading_bar.scaleX=loaded_per
		}
		private function progress_Handler(_evt:Event):void{
			var loaded=sound.bytesLoaded
			var total=sound.bytesTotal
			sound_length=sound.length
			if(total>0){
				var loaded_per=loaded/total
				if(loaded_per>=1) loadEnd=true
				scroll_bar.loading_bar.scaleX=loaded_per
				sound_length=sound_length/loaded_per
				position=sound_channel.position
				var played_per=position/sound_length
				scroll_bar.dragger.x=(scroll_bar.scroll_bg.width-scroll_bar.dragger.width)*played_per
			}
		}
	}
}
Ctrl+Enter一下!再拖動一下滑塊,別拖到音量骨塊上去哦。呵呵。。。
 
音量的控制
要改調節音量需用到SoundChannel對象的soundTransform屬性,它是SoundTransform的類實例。操用步驟:1.建立一個soundTransform對象。2.設置soundTransform對象的volume值(0-1)3.將soundTransform對象賦給SoundChannel的soundTransform屬性屬性。為了方便我將其寫成函數
function set_volume(temp:SoundChannel,temp_value:Number){
	var sound_trf:SoundTransform=new SoundTransform()
	sound_trf.volume=temp_value
	temp.soundTransform=sound_trf
}
再看一下控制音量的滑塊。也寫成了一個類(sound_lib/Vol_scroll_bar.as)
package sound_lib{
	import flash.display.*
	import flash.events.*
	import flash.geom.*
	public class Vol_scroll_bar extends MovieClip{
		public static const SCROLL:String="scroll"
		public var per
		public function Vol_scroll_bar(){
			this.addEventListener(Event.ADDED_TO_STAGE,add_to_stage)
		}
		private function add_to_stage(_evt:Event):void{
			init()
		}
		private function init(){
			dragger._btn.addEventListener(MouseEvent.MOUSE_DOWN,press_Handler)
			dragger._btn.addEventListener(MouseEvent.MOUSE_UP,release_Handler)
		}
		private function press_Handler(_evt:MouseEvent):void{
			dragger.startDrag(false,new Rectangle(scroll_bg.x,scroll_bg.y,scroll_bg.width-dragger.width,0))
			scroll_bg.addEventListener(Event.ENTER_FRAME,move_Handler)
			stage.addEventListener(MouseEvent.MOUSE_UP,release_Handler)
		}
		private function release_Handler(_evt:MouseEvent):void{
			dragger.stopDrag()
			scroll_bg.removeEventListener(Event.ENTER_FRAME,move_Handler)
			stage.removeEventListener(MouseEvent.MOUSE_UP,release_Handler)
		}
		private function move_Handler(_evt:Event):void{
			per=Math.ceil(100*dragger.x/(scroll_bg.width-dragger.width))/100
			this.dispatchEvent(new Event(SCROLL))
		}
	}
}
該類就公開了一個屬性per(百分比)那么怎么實時獲取per呢?
看到this.dispatchEvent(new Event(SCROLL))這句沒?在拖動滑塊的同時給該類加入了一個事件,所以我們只需在父類中貞聽這個事件就可以了:
private function Vol_scroll_init(){
			vol_scroll_bar.addEventListener(Vol_scroll_bar.SCROLL,get_per_Handler)
		}
		private function get_per_Handler(_evt):void{
			trace(vol_scroll_bar.per)
		}
Ctrl+Enter一下!拖動滑塊(別拖錯了哦)查看trace出來的值。這到里你應該明天怎么做了吧:再結合上面給出的調節音量的函數。
 
private function Vol_scroll_init(){
			vol_scroll_bar.addEventListener(Vol_scroll_bar.SCROLL,get_per_Handler)
		}
		private function get_per_Handler(_evt):void{
			set_volume(sound_channel,Number(vol_scroll_bar.per))
			trace(vol_scroll_bar.per)
		}
		function set_volume(temp:SoundChannel,temp_value:Number){
			var sound_trf:SoundTransform=new SoundTransform()
			sound_trf.volume=temp_value
			temp.soundTransform=sound_trf
		}
至此音量的控制搞定
 
讀取聲音文件的ID3數據
MP3 文件大多包含一些如songname, artist, album, genre, year等元數據,不過這些并不是都有。通過Sound對象的id3屬性可獲得這些數據。這個屬性其實是ID3Info的類實例,它包含下列屬性:artist(歌手名)、songName(歌曲名).........等?;袢∥募腎D3數據很簡單:通過監聽Sound對象的ID3事件就行了
sound.addEventListener(Event.ID3,ID3_Handler)
private function ID3_Handler(_evt:Event):void{
			trace(sound.id3.songName)
		}
將以上代碼加到之前的代碼Ctrl+Enter一下!很不幸,你很可能看到的是亂碼。編碼問題,不想多說了,用這個函數轉一下就行了
private function EncodeUtf8(str : String):String {
   			var oriByteArr : ByteArray = new ByteArray();
   			oriByteArr.writeUTFBytes (str);
  			var tempByteArr : ByteArray = new ByteArray();
   			for (var i = 0; i<oriByteArr.length; i++) {
    			if (oriByteArr[i] == 194) {
     				tempByteArr.writeByte(oriByteArr[i+1]);
     				i++;
    			} else if (oriByteArr[i] == 195) {
     				tempByteArr.writeByte(oriByteArr[i+1] + 64);
     				i++;
    			} else {
    				 tempByteArr.writeByte(oriByteArr[i]);
    			}
   			}
   			tempByteArr.position = 0;
   			return tempByteArr.readMultiByte(tempByteArr.bytesAvailable,"chinese");
  		}
讀取音樂聲譜
自己看源吧。

關于我們

萬博思圖(北京)信息技術有限公司,專業的flash,flex開發團隊,5年經驗。公司致力于互聯網上的業務的開展,對于互動網站行銷,互聯網應用程序開發有成熟的解決方案。我們關注互聯網市場動態,關注新技術,更注重在新的領域不斷探索發現。
萬博思圖業務內容主要包括企業品牌Flash網站開發,企業形象宣傳Flash設計,動畫,多媒體演示,Flex企業級應用程序開發,擁有眾多成功案例,歡迎來電咨詢。
COPYRIGHT BY WEBSTUDIO INTERACTIVE DESIGN Co.,Ltd. ALL RIGHTS RESERVED.
公司地址: 北京市朝陽區光華路15號院泰達時代中心4號樓704 郵編: 100026 EMAIL: [email protected]
電話: 010-59070059   (新號:010-59897050 010-59897060)  手機: 13693660520 傳真: 010-59070059-801
京公網安備:110108006741      京ICP備:05013074號-1
王先生