如何用java播放.wav文件

问题描述 投票:0回答:11

我正在尝试用 Java 播放 *.wav 文件。我希望它执行以下操作:
按下按钮时,会发出短促的蜂鸣声。

我用谷歌搜索了它,但大部分代码都不起作用。有人能给我一个简单的代码片段来播放 .wav 文件吗?

java audio wav
11个回答
46
投票

最后我成功地做到了以下几点并且效果很好

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class MakeSound {

    private final int BUFFER_SIZE = 128000;
    private File soundFile;
    private AudioInputStream audioStream;
    private AudioFormat audioFormat;
    private SourceDataLine sourceLine;

    /**
     * @param filename the name of the file that is going to be played
     */
    public void playSound(String filename){

        String strFilename = filename;

        try {
            soundFile = new File(strFilename);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            audioStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e){
            e.printStackTrace();
            System.exit(1);
        }

        audioFormat = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try {
            sourceLine = (SourceDataLine) AudioSystem.getLine(info);
            sourceLine.open(audioFormat);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        sourceLine.start();

        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) {
            try {
                nBytesRead = audioStream.read(abData, 0, abData.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (nBytesRead >= 0) {
                @SuppressWarnings("unused")
                int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
            }
        }

        sourceLine.drain();
        sourceLine.close();
    }
}

41
投票

这是我在不使用阳光的情况下可以想到的最优雅的形式。*:

import java.io.*;
import javax.sound.sampled.*;

try {
    File yourFile;
    AudioInputStream stream;
    AudioFormat format;
    DataLine.Info info;
    Clip clip;

    stream = AudioSystem.getAudioInputStream(yourFile);
    format = stream.getFormat();
    info = new DataLine.Info(Clip.class, format);
    clip = (Clip) AudioSystem.getLine(info);
    clip.open(stream);
    clip.start();
}
catch (Exception e) {
    //whatevers
}

19
投票

最短形式(无需安装随机库)?

public static void play(String filename)
{
    try
    {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File(filename)));
        clip.start();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}

唯一的问题是没有好的方法可以让这个方法在 *.wav 完成后阻塞关闭并处理数据。

clip.drain()
表示它被阻塞,但事实并非如此。该剪辑未在之后
start()
运行。 我发现唯一可行但丑陋的方法是:

// ...
clip.start();
while (!clip.isRunning())
    Thread.sleep(10);
while (clip.isRunning())
    Thread.sleep(10);
clip.close();

17
投票

您可以使用事件侦听器在播放后关闭剪辑

import java.io.File;
import javax.sound.sampled.*;

public void play(File file) 
{
    try
    {
        final Clip clip = (Clip)AudioSystem.getLine(new Line.Info(Clip.class));

        clip.addLineListener(new LineListener()
        {
            @Override
            public void update(LineEvent event)
            {
                if (event.getType() == LineEvent.Type.STOP)
                    clip.close();
            }
        });

        clip.open(AudioSystem.getAudioInputStream(file));
        clip.start();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}

4
投票

这里的代码片段工作正常,用 Windows 声音进行了测试:

public static void main(String[] args) { AePlayWave aw = new AePlayWave( "C:\\WINDOWS\\Media\\tada.wav" ); aw.start(); }
    

2
投票
将播放 WAV 文件的类,阻塞直到声音播放完毕:

class Sound implements Playable { private final Path wavPath; private final CyclicBarrier barrier = new CyclicBarrier(2); Sound(final Path wavPath) { this.wavPath = wavPath; } @Override public void play() throws LineUnavailableException, IOException, UnsupportedAudioFileException { try (final AudioInputStream audioIn = AudioSystem.getAudioInputStream(wavPath.toFile()); final Clip clip = AudioSystem.getClip()) { listenForEndOf(clip); clip.open(audioIn); clip.start(); waitForSoundEnd(); } } private void listenForEndOf(final Clip clip) { clip.addLineListener(event -> { if (event.getType() == LineEvent.Type.STOP) waitOnBarrier(); }); } private void waitOnBarrier() { try { barrier.await(); } catch (final InterruptedException ignored) { } catch (final BrokenBarrierException e) { throw new RuntimeException(e); } } private void waitForSoundEnd() { waitOnBarrier(); } }
    

1
投票
另一种使用

AudioInputStream

 的方法:

import java.io.File; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.Line; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.swing.JDialog; import javax.swing.JFileChooser; public class CoreJavaSound extends Object implements LineListener { File soundFile; JDialog playingDialog; Clip clip; public static void main(String[] args) throws Exception { CoreJavaSound s = new CoreJavaSound(); } public CoreJavaSound() throws Exception { JFileChooser chooser = new JFileChooser(); chooser.showOpenDialog(null); soundFile = chooser.getSelectedFile(); System.out.println("Playing " + soundFile.getName()); Line.Info linfo = new Line.Info(Clip.class); Line line = AudioSystem.getLine(linfo); clip = (Clip) line; clip.addLineListener(this); AudioInputStream ais = AudioSystem.getAudioInputStream(soundFile); clip.open(ais); clip.start(); } public void update(LineEvent le) { LineEvent.Type type = le.getType(); if (type == LineEvent.Type.OPEN) { System.out.println("OPEN"); } else if (type == LineEvent.Type.CLOSE) { System.out.println("CLOSE"); System.exit(0); } else if (type == LineEvent.Type.START) { System.out.println("START"); playingDialog.setVisible(true); } else if (type == LineEvent.Type.STOP) { System.out.println("STOP"); playingDialog.setVisible(false); clip.close(); } } }
    

1
投票
没有java反射的解决方案

DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat)



Java 反射会降低性能。 运行:

java playsound absoluteFilePathTo/file.wav



import javax.sound.sampled.*; import java.io.*; public class playsound { public static void main (String args[]) throws Exception { playSound (args[0]); } public static void playSound () throws Exception { AudioInputStream audioStream = AudioSystem.getAudioInputStream(new File (filename)); int BUFFER_SIZE = 128000; AudioFormat audioFormat = null; SourceDataLine sourceLine = null; audioFormat = audioStream.getFormat(); sourceLine = AudioSystem.getSourceDataLine(audioFormat); sourceLine.open(audioFormat); sourceLine.start(); int nBytesRead = 0; byte[] abData = new byte[BUFFER_SIZE]; while (nBytesRead != -1) { try { nBytesRead = audioStream.read(abData, 0, abData.length); } catch (IOException e) { e.printStackTrace(); } if (nBytesRead >= 0) { int nBytesWritten = sourceLine.write(abData, 0, nBytesRead); } } sourceLine.drain(); sourceLine.close(); } }
    

0
投票
您也可以这样使用 AudioStream:

import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import sun.audio.AudioPlayer; import sun.audio.AudioStream; public class AudioWizz extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; //you like your cereal and the program likes their "serial" static AudioWizz a; static JButton playBuddon; static JFrame frame; public static void main(String arguments[]){ frame= new JFrame("AudioWizz"); frame.setSize(300,300); frame.setVisible(true); a= new AudioWizz(); playBuddon= new JButton("PUSH ME"); playBuddon.setBounds(10,10,80,30); playBuddon.addActionListener(a); frame.add(playBuddon); frame.add(a); } public void actionPerformed(ActionEvent e){ //an eventListener if (e.getSource() == playBuddon) { try { InputStream in = new FileInputStream("*.wav"); AudioStream sound = new AudioStream(in); AudioPlayer.player.start(sound); } catch(FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } } }
    

0
投票
我采用了@greenLizard 的代码并使其更加健壮。

    我关闭了
  1. AudioInputStream
  2. 我用了
  3. BufferedInputStream
    AudioSystem
     
    getAudioInputStream
     偶尔会抛出 
    IOException
    ,因为 
    getAutoInputSytream
     方法无法备份输入流并重新开始。
希望没有更多的例外情况。

这是修改后的代码。

ErrorDisplayDialog 在 Java Swing 应用程序中将异常显示为 JDialog

。  只需替换为
e.printStackTrace();
即可。

private void playWavFile(String fileName) { InputStream inputStream = getClass().getResourceAsStream(fileName); BufferedInputStream bufferedInputStream = new BufferedInputStream( inputStream); AudioInputStream audioStream = null; AudioFormat audioFormat = null; try { audioStream = AudioSystem.getAudioInputStream(bufferedInputStream); audioFormat = audioStream.getFormat(); } catch (UnsupportedAudioFileException e) { new ErrorDisplayDialog(view.getFrame(), "UnsupportedAudioFileException", e); return; } catch (IOException e) { new ErrorDisplayDialog(view.getFrame(), "IOException", e); return; } DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); SourceDataLine sourceLine; try { sourceLine = (SourceDataLine) AudioSystem.getLine(info); sourceLine.open(audioFormat); } catch (LineUnavailableException e) { new ErrorDisplayDialog(view.getFrame(), "LineUnavailableException", e); return; } sourceLine.start(); int nBytesRead = 0; byte[] abData = new byte[128000]; while (nBytesRead != -1) { try { nBytesRead = audioStream.read(abData, 0, abData.length); } catch (IOException e) { new ErrorDisplayDialog(view.getFrame(), "IOException", e); return; } if (nBytesRead >= 0) { sourceLine.write(abData, 0, nBytesRead); } } sourceLine.drain(); sourceLine.close(); try { audioStream.close(); } catch (IOException e) { new ErrorDisplayDialog(view.getFrame(), "IOException", e); } }
    

0
投票
我对迷你我写的简短形式做了一些改进。为了避免将来出现问题,所有打开的输入流都应该关闭。

private void play(String filename) { try(AudioInputStream ais = AudioSystem.getAudioInputStream(new File(filename))) { Clip clip = AudioSystem.getClip(); clip.open(ais); clip.start(); } catch (Exception exc) { exc.printStackTrace(System.out); } }
    
© www.soinside.com 2019 - 2024. All rights reserved.