java實現音訊檔案的播放
實現思路
1、首先獲取音訊檔案的地址,然後通過IO流讀取音訊檔案,加緩衝區,實現Player類的物件。
2、Player類主要用於播放器的初始化,以及通過它來實現一些音視訊檔案的播放,這個類需要手動去網上下載,然後新增路徑到我們Eclipse的library中。
3、Player類有兩種方法比較常用,play()方法和close()方法,前者用於啟動音訊檔案,後者用於退出音訊檔案的播放,這兩個方法我們在使用的時候需要注意,在整個音訊播放的過程中,程式都會停留在play()方法中,類似於在讀進度條,close()方法可以使得其退出播放,程式往下繼續執行。
4、假設我們點選了開始按鈕,那麼程式就不會再去響應你的停止操作了,於是,我們可以通過多執行緒來實現這個啟動和停止功能,讓播放在一個執行緒裡自己去執行。
5、那麼迴圈呢?如何實現迴圈播放?答案是while迴圈,我們需要一個引數作為while的迴圈條件,類似於一個開關,只要為true,就一直迴圈播放。
6、我們在執行完一次播放後就不能再次對這個物件呼叫play()方法了,我們需要再次建立新的物件,那麼我們要想關閉新的物件就必須讓執行close()方法的物件是這個新的物件,我們每次新建相同名稱的物件,player.close()執行後關閉的往往只能是最後的那個物件。在啟動和停止中我們看不出問題,但是當我們試圖關閉在run方法裡迴圈中的音訊時,我們會發現停止不了!為什麼?我們把物件傳給執行緒類,close()方法依然可由此物件來執行,當他執行完play()方法後,我們new一個新的物件時,又開闢了一塊新的記憶體空間存放這個物件的資料,再用原先的物件close()就不能到達效果了,即無法關閉這個音訊。解決辦法:在每次new新物件後用set方法把物件傳回去,我們可以理解為讓close方法的呼叫者一直是這個新new的物件。
7、到這裡就不得不提一下static了,一般我們不斷用相同的物件名去new同類的物件時,它們是共享程式碼(JVM中),但是它們的物件資料都是獨立的,記憶體空間也是不同的;如果加了static,方法或者屬性就會屬於這個類,那麼它們就變成唯一的了,物件共用被static修飾的程式碼和屬性。
程式碼實現
1、介面:
/** * 背景音樂控制介面 */ public void showUI8(){ JFrame jf8 =new JFrame("音樂"); jf8.setSize(300, 150); jf8.setLocationRelativeTo(null); jf8.setDefaultCloseOperation(jf8.DISPOSE_ON_CLOSE); jf8.setLayout(null); jf8.setResizable(false); JLabel jl81 = new JLabel("選擇音樂"); jl81.setBounds(40,20,60,25); jf8.add(jl81); String[] str = {"許嵩 - 斷橋殘雪.mp3","許嵩 - 有何不可.mp3","薛之謙 - 紳士.mp3","薛之謙 - 意外.mp3"}; JComboBox<String> jcb81 = new JComboBox<String>(str); jcb81.setBounds(120, 20, 150, 25); jf8.add(jcb81); JButton jbu81=new JButton("播放"); jbu81.setBounds(20,60,70,30); jf8.add(jbu81); jbu81.addActionListener(listener); JButton jbu82=new JButton("迴圈"); jbu82.setBounds(110,60,70,30); jf8.add(jbu82); jbu82.addActionListener(listener); JButton jbu83=new JButton("停止"); jbu83.setBounds(200,60,70,30); jf8.add(jbu83); jbu83.addActionListener(listener); listener.setjcb81(jcb81); jf8.setVisible(true); }
2、監聽器方法:
private Player player;
private Player player1;
public boolean loopFlag=false;
public void actionPerformed(ActionEvent e) { if("音樂".equals(e.getActionCommand())) { System.out.println("音樂設定"); cli.showUI8(); } if("播放".equals(e.getActionCommand())) { if(player!=null) player.close(); loopFlag=false; String path = "E:\\workspace\\mayifan\\chetRoom\\com\\myf\\client1207\\music\\"+(String)jcb81.getSelectedItem(); try{ File file = new File(path); FileInputStream fis = new FileInputStream(file); BufferedInputStream buff = new BufferedInputStream(fis); player = new Player(buff); }catch(IOException e1){ e1.printStackTrace(); }catch(JavaLayerException e1){ e1.printStackTrace(); } System.out.println("開始播放:"+(String)jcb81.getSelectedItem()); MusicThread mt = new MusicThread(player, path ,listener); mt.start(); }if("迴圈".equals(e.getActionCommand())) { if(loopFlag==false) { System.out.println("開啟迴圈播放"); loopFlag = true; }else{ System.out.println("關閉迴圈播放"); loopFlag = true; } } if("停止".equals(e.getActionCommand())) { System.out.println("停止播放"); loopFlag=false; player.close(); player1.close(); } }
3、音訊執行緒:
public class MusicThread extends Thread{
private Player player;
private String path;
private Listener listener;
private Player player1;
public MusicThread(Player player , String path , Listener listener){
this.player=player;
this.path = path;
this.listener=listener;
}
@Override
public void run() {
int add=0;
try{
player.play();
}catch(JavaLayerException e){
e.printStackTrace();
}
player.close();
add++;
System.out.println(listener.loopFlag);
while(listener.loopFlag)
{
try{
File file1 = new File(path);
FileInputStream fis1 = new FileInputStream(file1);
BufferedInputStream buff1 = new BufferedInputStream(fis1);
player1 = new Player(buff1);
listener.setplayer1(player1);
}catch(IOException e1){
e1.printStackTrace();
}catch(JavaLayerException e1){
e1.printStackTrace();
}
try{
player1.play();
}catch(JavaLayerException e1){
e1.printStackTrace();
}
add++;
}
System.out.println("迴圈播放次數:"+add);
}
}
4、介面效果圖:
本文原文地址:https://blog.csdn.net/mayifan_blog/article/details/84981678