2012-04-17 75 views
1

我想在我的Java应用程序中播放mp3。用户有能力点击按钮并改变声音。以延迟结束的Java线程

声音和切换工作...但是当用户试图切换声音时,新的歌曲开始在旧的播放器上播放约一秒钟,然后在旧的播放器停止播放。我正在尝试使用线程来处理一切。

我的MP3类:

import java.applet.*; 
import javazoom.jl.player.Player; 
import java.io.*; 
import java.io.FileInputStream; 
import java.net.*; 

public class mp3 extends Thread implements Runnable{ 

    private Player sound; 
    private InputStream path; 
    public mp3(String file_name) { 
     path = mp3.class.getClassLoader().getResourceAsStream(file_name); 
    } 
    public void run(){ 
     try { 
      Player sound=new Player(path); 
      sound.play(); 
     } catch(Exception e) {System.out.println(e);} 
    } 
} 

这就是我试图在我的主游戏运行代码。 MP3对象被称为歌曲。

当应用程序初始化,下面的代码运行:

song = new mp3("default.mp3"); 
song.start(); 

有人试图去改变它,下面的代码运行:

song.stop(); 
song = new mp3(t+".mp3"); 
song.start(); 

其中T是文件名的参数。

我很确定这个问题依赖于MP3对象的运行功能。我对线程完全陌生,所以我希望得到一些帮助。

同样,从“停止”被调用的时间和实际停止播放的时间延迟约为1秒。所以也许在那里等一下?

谢谢!

编辑:我使用的代码基于离这里现在:

http://introcs.cs.princeton.edu/java/faq/mp3/MP3.java.html

我创建了一个播放和定义关闭功能如下:

public void close() { if (player != null) player.close(); } 

    // play the MP3 file to the sound card 
    public void play() { 
     try { 
      FileInputStream fis  = new FileInputStream(filename); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      player = new Player(bis); 
     } catch (Exception e) { 
      System.out.println("Problem playing file " + filename); 
      System.out.println(e); 
     } 

     // run in new thread to play in background 
     new Thread() { 
      public void run() { 
       try { player.play(); } 
       catch (Exception e) { System.out.println(e); } 
      } 
     }.start(); 

我的问题是关闭功能...播放器对象始终为空,并且关闭功能不会执行..即使播放函数初始化它。为什么它是空的?

+1

'Thread.stop()'是不推荐使用的方法,不应使用。 – Gray 2012-04-17 05:09:25

+0

['Clip'](http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/Clip.html)或['BigClip'](http: //stackoverflow.com/a/9470886/418556)。 – 2012-04-17 08:33:46

+0

可以扩展Thread或实现Runnable。没有必要这样做。关闭线程很可能不是立即停止声音的正确方法。 Javazoom的播放器应该提供一些方法。如果没有,那么这是他们的对象的缺陷。另外,Player的每个实例可能都应该在自己的线程中,而不是试图重用。 – 2012-04-18 04:41:53

回答

1

编辑:

在你的编辑,如果将多个线程访问player领域,那么它应该作出volatile。没有看到如何定义player,否则很难猜测问题。


我认为你需要确保该Player已经完成了先前的MP3在你开始下之前。展望javadocs for Player我看到:

`player.isComplete()` 

引述:

返回true,如果所有可用的MPEG音频帧已被解码,否则为false

如果要停止之前的当新声音开始时,您应该在旧播放器上使用close()

关闭此播放器。任何音频当前正在播放的是立即停止

声音对我说,你需要关闭当前运行Player对象(如果有的话),并开始一个新的Player对象打新的声音。如果你这样做是在多线程,那么你就需要做一些事情,如:

  1. 锁定某些final Object lock对象
  2. 如果你想目前的声音来完成,检查当前Player对象(如果有的话)已完成与sleep
  3. close()当前Player对象和循环创建一个新的Player如果你想杀死电流声
  4. 呼叫play()下一个MP3,
  5. 解锁锁定对象。

据我所知,play()方法不会等待要播放的声音,但在加载声音到音频缓冲区后立即返回。我不确定如果音频文件很大,会发生什么情况。

+0

感谢您的回应。我试图创建一个函数,当我需要改变声音时调用sound.close。但是,更改声音文件后,似乎可以防止再次使用该声音。我得到一个空指针异常。 close()某种析构函数? – 2012-04-17 05:32:30

+0

它可能是@Katherine。是的,看着这个文档你可能需要创建一个新的'Player'对象。我已经改变了我的答案,以弥补这一点。 – Gray 2012-04-17 13:36:25