0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何用Java播放声音

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-09 10:56 次阅读

在本篇文章中,我们将学习如何用Java播放音乐,Java 声音 API 的设计是为了流畅和连续地播放声音,甚至是很长的声音。我们将使用 Java 提供的 ClipSourceDataLine 声音API播放一个音频文件。

播放声音的Java APIs

一般来说,javax.sound 包中的Java Sound APIs提供了两种播放音频的方法。在这两种方法之间,在如何指定声音文件数据方面有区别。Java Sound APIs可以以流式、缓冲方式和内存、非缓冲方式处理音频传输。Java的两个最著名的声音API是 ClipSourceDataLine

Clip API

Clip API是Java的一个非缓冲或内存声音API。Clip类是javax.sound.sampled包的一部分,它在读取和播放短的声音文件时有用。在播放之前,整个音频文件被加载到内存中,用户可以完全控制播放。除了循环播放声音外,它还允许用户在一个随机的位置开始播放。

让我们首先创建一个示例类,SoundPlayerWithClip,它实现了LineListener接口,以便接收播放的线事件(OPENCLOSESTARTSTOP)。我们将从LineListener实现update()方法来检查播放状态。

public class SoundPlayerUsingClip implements LineListener {

    boolean isPlaybackCompleted;
    
    @Override
    public void update(LineEvent event) {
        if (LineEvent.Type.START == event.getType()) {
            System.out.println("Playback started.");
        } else if (LineEvent.Type.STOP == event.getType()) {
            isPlaybackCompleted = true;
            System.out.println("Playback completed.");
        }
    }
}

其次,让我们从我们项目的资源文件夹中读取音频文件。我们的资源文件夹包含三个不同格式的音频文件--即WAV、MP3和MPEG。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(audioFilePath);

第三,从文件流中,我们将创建一个AudioInputStream

AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);

现在,我们将创建一个DataLine.Info对象。

AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);

让我们从这个DataLine.Info创建一个Clip对象,并打开流,然后调用start来开始播放音频。

Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
audioClip.open(audioStream);
audioClip.start();

最后,我们需要关闭任何开放的资源。

audioClip.close();
audioStream.close();

一旦代码运行,音频文件就会播放。

由于音频被预装在内存中,我们有许多其他有用的API,我们可以从中受益。

我们可以使用Clip.loop方法来连续循环播放音频片段。

例如,我们可以把它设置为播放五次音频。

audioClip.loop(4);

或者,我们可以设置它无限期地播放音频(或直到中断)。

audioClip.loop(Clip.LOOP_CONTINUUSLY);

Clip.setMicrosecondPosition设置媒体位置。当剪辑下次开始播放时,它将从这个位置开始。例如,要从第30秒开始,我们可以这样设置。

audioClip.setMicrosecondPosition(30_000_000);

SourceDataLine API

SourceDataLine API是java的一个缓冲或流式声音API。SourceDataLine类是javax.sound.sampled包的一部分,它可以播放无法预装到内存中的长声音文件。

当我们希望优化大的音频文件的内存时,或者在流传实时音频数据时,使用SourceDataLine更有效。如果我们事先不知道声音有多长,何时结束,它也很有用。

让我们首先创建一个示例类,从我们项目的资源文件夹中读取音频文件。我们的资源文件夹包含三个不同格式的音频文件--即WAV、MP3和MPEG。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(audioFilePath);

第二,从文件输入流中,我们将创建一个AudioInputStream

AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);

现在,我们将创建一个DataLine.Info对象。

AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);

让我们从这个DataLine.Info创建一个SourceDataLine对象,打开流,并调用start来开始播放音频。

SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(info);
sourceDataLine.open(audioFormat);
sourceDataLine.start();

现在,在SourceDataLine的情况下,的音频数据是分块加载的,我们需要提供缓冲区的大小。

private static final int BUFFER_SIZE = 4096;

现在,让我们从AudioInputStream读取音频数据,并将其发送到SourceDataLine的播放缓冲区,直到它到达流的末端。

byte[] bufferBytes = new byte[BUFFER_SIZE];
int readBytes = -1;
while ((readBytes = audioStream.read(bufferBytes)) != -1) {
    sourceDataLine.write(bufferBytes, 0, readBytes);
}

最后,让我们关闭任何开放的资源。

sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();

一旦代码运行,音频文件就会播放。在这里,我们不需要实现任何LineListener接口。

ClipSourceDataLine之间的比较

让我们来讨论一下两者的优点和缺点。

ClipSourceDataLine
支持从音频的任何位置播放。参见setMicrosecondPosition(long)setFramePosition(int).不能从声音中的任意位置开始播放。
支持在循环中播放(全部或部分的声音)。 参见setLoopPoints(int, int)loop(int).不能播放(循环)全部或部分声音。
可以在播放前知道声音的持续时间。参见getFrameLength()getMicrosecondLength().在播放前不能知道声音的持续时间。
可以在当前位置停止播放,稍后继续播放。请看stop()start()不能在中间停止和恢复播放。
不适合播放大的音频文件,也没有效率,因为它是在内存中的。适合播放长的声音文件或实时的声音流。
Clip的start()方法确实在播放声音,但它不会阻塞当前线程(它立即返回),所以它需要实现LineListener接口来了解播放状态。与Clip不同,我们不需要实现LineListener接口来知道什么时候播放完成。
不可能控制什么声音数据被写入音频线的播放缓冲区。可以控制哪些声音数据要被写入音频线的播放缓冲区。

Java API对MP3格式的支持

目前,ClipSourceDataLine都可以播放AIFC、AIFF、AU、SND和WAV格式的音频文件。

我们可以使用AudioSystem检查支持的音频格式。

Type[] list = AudioSystem.getAudioFileTypes();
    StringBuilder supportedFormat = new StringBuilder("Supported formats:");
    for (Type type : list) {
        supportedFormat.append(", " + type.toString());
    }
    System.out.println(supportedFormat.toString());

然而,我们不能用Java Sound APIs ClipSourceDataLine 播放流行的音频格式MP3/MPEG。`我们需要寻找一些能播放MP3格式的第三方库。

如果我们向 ClipSourceDataLine API提供MP3格式的文件,我们会得到UnsupportedAudioFileException

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
        at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1189)

总结

在这篇文章中,我们学习了如何用Java播放声音。我们还了解了两个不同的Java声音API - ClipSourceDataLine。我们了解了 ClipSourceDataLine API之间的区别。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 音频
    +关注

    关注

    29

    文章

    2873

    浏览量

    81529
  • 缓冲
    +关注

    关注

    0

    文章

    52

    浏览量

    17821
  • 内存
    +关注

    关注

    8

    文章

    3024

    浏览量

    74035
  • JAVA
    +关注

    关注

    19

    文章

    2967

    浏览量

    104741
  • API
    API
    +关注

    关注

    2

    文章

    1499

    浏览量

    61991
收藏 人收藏

    评论

    相关推荐

    ESP32-C5怎么播放声音

    我看了ESP32-C5的介绍,没发现它有I2C和I2S,那怎么播放声音?看到来ADF和它无关。
    发表于 06-28 08:29

    Tas5825pevm无法通过usb播放声音怎么办

    无法通过usb播放声音 ppc显示需要ID地址为0x98 但evm板ID为0x97 我该怎么修?
    发表于 10-09 07:11

    wince系统playsound单独播放声音正常,进去地图里面播放就有杂音的原因?

    地图也是用playsound播放声音,同样的音频文件,只是进去地图播放有杂音。在地图播放声音过程中cpu和内存实用率都没有超过50%。音频芯片tlv320aic3106。
    发表于 10-29 06:05

    TPA3110无法播放声音的原因?怎么解决?

    立刻重新制作了一块新的板子,最后还是无法播放声音。 在接下来的查找错误原因中,我们发现以下几种有价值的情况: 1,首先,如果先在输入端输入音频信号,再接通电源,板子可以短暂的播放一会音乐。但如果暂停或
    发表于 11-05 07:39

    C#中如何播放声音

    C#中没有声音类。播放声音请参阅API!比如:  [DllImport("Winmm.dll")]  
    发表于 02-20 10:22

    WinForm中如何播放声音与Flash动画

    WinForm中如何播放声音与Flash动画前面几天有一位MM在william hill官网 中问我,怎么在VC#设计中如何播放声音和Flash动画。当时我正急着找工作,没有机会去想想怎么做,只能遗憾对那个MM说,我帮不了你
    发表于 03-04 17:00

    VC播放声音函数PlaySound和sndPlaySound的用法

    VC播放声音函数PlaySound和sndPlaySound的用法一、PlaySound函数的声明为:BOOL PlaySound(LPCSTR pszSound,HMODULE hmod
    发表于 10-02 01:51

    播放声音

    自己编程的播放声音文件的程序,分享相互学习。
    发表于 01-11 18:55

    LabVIEW播放声音文件选择设备ID无效?

    电脑有两个声卡,使用LabVIEW播放声音文件的VI,无论设备ID设置0或1,都通过默认的声卡输出声音。即无法实现选择输出设备。而如果读取波形文件控制播放时,则可以按照设备ID的选择,通过不同的声卡播出。但是
    发表于 09-13 15:01

    播放声音直接从PSoC和发送同时有声音失真

    我的英语道歉,不讲起我用“谷歌翻译”。试图做一个乐器,必须传送到计算机,这种风格的“吉他英雄”的游戏,我的问题是,当我尝试播放声音直接从PSoC和发送同时有声音失真,思考这quice使用“操作系统
    发表于 01-17 12:53

    请问用edma方式播放声音如何让循环播放声音停下来?

    想问两个问题:1、AUDIO LINE OUT 例程中,用edma方式播放声音,如何让循环播放声音停下来。做交互时很困扰,声音一旦播放就停
    发表于 09-06 08:29

    求助大神自己设计咪头声音很大,录音播放声音很小

    自己在做一个基于ISD4004语音芯片的一个语音录放装置,不知道是哪里除了问题,在放音是总是很大杂音而录音的播放声音很小,请教一下各位大神们我的威廉希尔官方网站 有什么问题吗?
    发表于 07-16 08:30

    如何强制使用默认声卡播放声音

    如何强制使用默认声卡播放声音
    发表于 03-03 06:49

    java小应用,java小应用程序下载

    Java小应用: 2.1 所有小应用程序的根源 2.2 小试身手 2.3 图形操作 2.4 URL类 2.5 载入现有图像文件 2.6 动画效果 2.7  播放声音 2.8 小 
    发表于 04-28 14:20 0次下载

    JAVA教程之声音播放程序

    JAVA教程之声音播放程序,很好的JAVA的资料,快来学习吧
    发表于 04-11 17:14 5次下载