Java 音乐播放器开发学习之——音频文件的播放

Java Sound API是javaSE平台提供底层的(low-level)处理声音接口,可以实现音频文件的播放。

其核心包括:

  • AudioSystem
  • AudioInputStream
  • AudioFormat
  • DataLine.Info
  • SourceDataLine
  • TargetDataLine等

AudioSystem的默认输入设备是麦克风,默认输出设备是扬声器:

  1. SourceDataLine:源数据流,指AudioSystem的输入流,把音频文件写入到AudioSystem中
  2. TargetDataLine:目标数据流,指AudioSystem的输出流
  3. 当播放文件时,把文件内容写入AudioSystem的SourceDataLine
  4. 当录音时,把AudioSystem的TargetDataLine中的内容读入内存

关于该API的基础知识,请各位自行查阅API,以下给出一个用来播放音频文件的Demo

 
  1. package com.ywq3;

  2.  
  3. import java.io.File;

  4. import java.io.IOException;

  5.  
  6. import javax.sound.sampled.AudioFormat;

  7. import javax.sound.sampled.AudioInputStream;

  8. import javax.sound.sampled.AudioSystem;

  9. import javax.sound.sampled.DataLine;

  10. import javax.sound.sampled.SourceDataLine;

  11.  
  12. public class Test {

  13. public static void main(String[] args) throws Exception, IOException {

  14. AudioInputStream audioInputStream;// 文件流

  15. AudioFormat audioFormat;// 文件格式

  16. SourceDataLine sourceDataLine;// 输出设备

  17. File file = new File("D:\\music.wav");

  18.  
  19.  
  20. // 取得文件输入流

  21. audioInputStream = AudioSystem.getAudioInputStream(file);

  22. audioFormat = audioInputStream.getFormat();

  23. // 转换文件编码

  24. if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {

  25. audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,

  26. audioFormat.getSampleRate(), 16, audioFormat.getChannels(),

  27. audioFormat.getChannels() * 2, audioFormat.getSampleRate(),

  28. false);

  29. audioInputStream = AudioSystem.getAudioInputStream(audioFormat,

  30. audioInputStream);

  31. }

  32.  
  33. // 打开输出设备

  34. DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,

  35. audioFormat, AudioSystem.NOT_SPECIFIED);

  36. sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);

  37. sourceDataLine.open(audioFormat); // 打开具有指定格式的行,这样可以使行获得所有所需的系统资源并变得可操作

  38. sourceDataLine.start(); // 允许某一数据行执行数据I/O

  39.  
  40. byte tempBuffer[] = new byte[320];

  41. try {

  42. int cnt;

  43. // 读取数据到缓存区

  44. // 从音频流读取指定的最大数量的数据字节,并将其放入给定的字节数组中。

  45. // return: 读入缓冲区的总字节数;如果因为已经到达流末尾而不再有更多数据,则返回-1

  46. while ((cnt = audioInputStream.read(tempBuffer, 0,

  47. tempBuffer.length)) != -1) {

  48. if (cnt > 0) {

  49. // 写入缓存数据

  50. sourceDataLine.write(tempBuffer, 0, cnt); // 通过此源数据行将音频数据写入混频器

  51. }

  52. }

  53. // Block等待临时数据被输出为空

  54. // 通过在清空数据行的内部缓冲区之前继续数据I/O,排空数据行中的列队数据

  55. sourceDataLine.drain();

  56. // 关闭行,指示可以释放的该行使用的所有系统资源。如果此操作成功,则将行标记为 closed,并给行的侦听器指派一个 CLOSE 事件。

  57. sourceDataLine.close();

  58. } catch (Exception e) {

  59. e.printStackTrace();

  60. System.exit(0);

  61. }

  62. }

  63. }


若程序正常运行,我们应该可以听到D盘下的一个叫做music.wav的音频文件被播放。

若程序报错:

Exception in thread "main" javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1189)
at com.ywq3.Test.main(Test.java:21)

异常信息是说,不支持的格式,即该音频文件不支持,得不到该文件的输入流。

原因分析:

      Javax sound API默认支持的格式通过AudioFileFormate源码可以看出,是支持wav文件的,如下所示:

开始我百思不得其解,后来发现wav格式的音频文件是有其固定格式的,若明明是wav文件,却报错说不支持该格式,则可能是该wav文件内部格式有错误。

关于wav内部格式请详见:http://blog.csdn.net/y96q1023/article/details/70307753

我先前使用的一个wav文件是直接通过io流合成的,所以一直报不支持的错误。后来使用了一个正确的wav文件,则可以播放。

下边给出一段如何使用javax sound合成wav音频文件的Demo,希望可以帮到各位小伙伴~

 
  1. import java.io.File;

  2. import java.io.IOException;

  3. import java.io.SequenceInputStream;

  4. import javax.sound.sampled.AudioFileFormat;

  5. import javax.sound.sampled.AudioInputStream;

  6. import javax.sound.sampled.AudioSystem;

  7.  
  8. public class WavAppender {

  9. public static void main(String[] args) {

  10. String wavFile1 = "D:\\wav1.wav";

  11. String wavFile2 = "D:\\wav2.wav";

  12.  
  13. try {

  14. AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(wavFile1));

  15. AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));

  16.  
  17. AudioInputStream appendedFiles =

  18. new AudioInputStream(

  19. new SequenceInputStream(clip1, clip2),

  20. clip1.getFormat(),

  21. clip1.getFrameLength() + clip2.getFrameLength());

  22.  
  23. AudioSystem.write(appendedFiles,

  24. AudioFileFormat.Type.WAVE,

  25. new File("D:\\wavAppended.wav"));

  26. } catch (Exception e) {

  27. e.printStackTrace();

  28. }

  29. }

  30. }


 

如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,可以进群366533258一起交流学习哦~

本群给大家提供一个学习交流的平台,内设菜鸟Java管理员一枚、精通算法的金牌讲师一枚、Android管理员一枚、蓝牙BlueTooth管理员一枚、Web前端管理一枚以及C#管理一枚。欢迎大家进来交流技术。

猜你喜欢

转载自blog.csdn.net/zp357252539/article/details/82776075