从另一个线程中定义的类返回变量

时间:2017-12-08 21:03:26

标签: java multithreading audio

我正在编写一个音频可视化工具。要将要显示的数据同步到音乐本身,我需要通过调用clip.getMicrosecondPosition() / player.getPosition()来获取剪辑的/播放器在音频文件中的当前位置。这对于剪辑工作正常。问题是我需要在另一个线程中定义播放器对象,因为调用player.play()会暂停当前线程中的所有执行,直到文件播放到结束。 Player是来自MP3SPI库(javazoom.jl.player.Player)的类。

代码:

public class AudioTools implements Runnable {

public File file;
public boolean isMP3 = false;
public Player player;
public Clip clip;

public AudioTools(File file) {
    this.file = file;
    determineFilyType();
}   

private void determineFileType() {
    if (file.getAbsolutePath().endsWith(".mp3")) {
        this.isMP3 = true;
    } else if (file.getAbsolutePath().endsWith(".wav")) {
        this.isMP3 = false;
    } else {
        System.err.println("Invalid File Type!");
        System.exit(0);
    }

}

public void play() {
    if (isMP3) {
        Thread t = new Thread(this);
        t.start(); // play MP3 using Player class
    } else {
        playWav(file); // play WAV using Clip class
    }

}

protected void playMP3(File file){
    try {
        player = new Player(new FileInputStream(file));
        player.play();
    } catch (Exception e) {
        System.out.println("Invalid MP3 File!");
        e.printStackTrace();
        System.exit(0);
    }

}

@Override
public void run() {
    playMP3(file);
}

private void playWav(File file) {
    try {
        AudioInputStream ais = AudioSystem.getAudioInputStream(file);
        DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
        clip = (Clip) AudioSystem.getLine(dataInfo);
        clip.open(ais);
        clip.start();
    } catch (Exception e) {
        e.printStackTrace();
        System.err.println("Invalid .wav file!");
        System.exit(0);
    }
}

}

主要课程:

public static void main(String[] args) {

File file = new File(/*PATH_TO_FILE_HERE*/);
AudioTools at = new AudioTools(file);
at.play();
// at.clip.getMicrosecondPosition() works here if loaded file is .wav.
// at.player.getPosition() returns null if loaded file is .mp3.
}

从主课程开始,我希望能够获得玩家当前的位置。目前,尝试此操作将返回null。

任何有用的评论表示赞赏。我之前曾问过类似的问题,这次编辑使问题更清晰,更短。

编辑:应该包含运行示例的所有代码necissary。

2 个答案:

答案 0 :(得分:1)

我不确定我是否完成了解你的问题,但我会尝试向你解释一些事情。

假设您有一个班级Clip,其中300毫秒到1000毫秒的随机时间(仅举例)播放剪辑的一秒并设置变量currentLength这是您想要获得的来自其他主题。

public class Clip implements Runnable {

    private int clipLength;

    private volatile int currentLength;

    public Clip(int clipLength) {
        this.clipLength = clipLength;
    }

    public void run() {

        while (currentLength <= clipLength) {
            try {
                currentLength += 1;
                Thread.sleep(ThreadLocalRandom.current().nextInt(300, 1000 + 1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public int getCurrentLength() {
        return currentLength;
    }

    public void setCurrentLength(int currentLength) {
        this.currentLength = currentLength;
    }

}

还可以说你有一个类Player,它的作用是获取剪辑对象,并在一段时间后请求它的当前长度。

public class Player implements Runnable {

    private Clip clip;

    public Player(Clip clip) {
        this.clip = clip;
    }

    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println(clip.getCurrentLength());
            Thread.sleep(2000);
            System.out.println(clip.getCurrentLength());
            Thread.sleep(1000);
            System.out.println(clip.getCurrentLength());
            Thread.sleep(3000);
            System.out.println(clip.getCurrentLength());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

此外,我们有一个Main类包含程序的开头,我们创建一个Clip对象并将其传递给to runnable类。

public class Main {
    public static void main(String[] args) {
        Clip clip = new Clip(60);
        Thread thread = new Thread(clip);
        thread.start();
        Thread threadPlayer = new Thread(new Player(clip));
        threadPlayer.start();

    }

}

我认为这是您要求的内容,但在将其实施到您的计划之前,您应该阅读atomic access and volatile keyword并了解Java memory model.

答案 1 :(得分:0)

使用不同的方法解决,这甚至不是问题的一部分。我已经有一个解密的音频数据数组,我可以将其变成Clip可以播放的AudioInputStream。