如何使用 java 播放 .wav 文件

Posted

技术标签:

【中文标题】如何使用 java 播放 .wav 文件【英文标题】:How to play .wav files with java 【发布时间】:2011-01-25 21:26:16 【问题描述】:

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

我已经用谷歌搜索过了,但大部分代码都不起作用。谁能给我一个简单的代码 sn-p 来播放 .wav 文件?

【问题讨论】:

【参考方案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();
    


【讨论】:

【参考方案2】:

使用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();
        
    

【讨论】:

为什么是extends Object @MazeOfEncryption 我真的不记得了 :)【参考方案3】:

您也可以通过这种方式使用 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();
            
        
    


【讨论】:

【参考方案4】:

将播放 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();
    

【讨论】:

【参考方案5】:

这是我在不使用 sun 的情况下能想到的最优雅的形式。*:

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

【讨论】:

我听不到使用此示例代码发出的任何音频。我有什么遗漏的吗? 应该是完整的,不过也是五岁了,丑陋的。我确信有更好的方法,使用漂亮的 Java 库。 要听到输出,您应该延迟应用程序终止一段播放时间。尝试将Thread.sleep(1000) 放在clip.start() 之后。【参考方案6】:

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

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);
    

【讨论】:

如果你想等到音频流被线路处理,你可以在句子开头添加“clip.drain()”。【参考方案7】:

最后我设法做到了以下,它工作正常

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();
    

【讨论】:

这个对我不起作用。我推荐一个非常简单的:http://alvinalexander.com/java/java-audio-example-java-au-play-sound 说真的,如果这是在 Java 中播放 wav 声音所需要的,那么我将停止使用 Java,幸运的是我怀疑这是正确的。 如果你在游戏循环中尝试这个,它会冻结游戏【参考方案8】:

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

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() 运行。 我发现的唯一可行但 UGLY 的方法是:

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

【讨论】:

【参考方案9】:

sn-p here 工作正常,用 windows 声音测试:

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

【讨论】:

如果您仍然有问题,请尝试更换声音设备。另请参阅此处推荐的工具***.com/questions/2175318/…

以上是关于如何使用 java 播放 .wav 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何同时录制使用 AVPlayer 和 wav 文件播放的歌曲?

如何在 Windows 上使用 gstreamer 播放 .wav 音频文件?

如何使用 QtMultimedia 播放 wav 文件?

如何使用 python 连接两个 wav 文件?

如何使用 Iphone sdk 中的音频队列播放 .wav 文件

如何在 Windows 中播放 .wav 文件?