前言:
进行音频处理,肯定需要从指定的位置播放,本章将介绍如何通过设置帧的方式,指定播放的位置。
目标:
知道什么帧,如何设置帧,代码【1】处
正文:
要明白本章从指定位置进行播放声音的代码,就要先知道什么是帧,先看下图:
我们知道电脑中的声音文件例如wav其实就是保存的连续的采样数据,每一个采样数据就是上图中的圆圈。简单点说,当我们播放wav时,就是从最左侧开始播放这些采样的点(实际中采样的点非常的多,这里只是便于理解)。
那么什么是帧呢?帧就是按照某个固定规则,讲这些连续不断地采样点进行了划分,这样就可以通过帧定位到点了。举个例子就明白了:图中如果不考虑帧,我想从采样点3开始播放,你可以定位到采样点3就行,你也可以直接通过指定到第2帧,然后就自动会从采样点3开始播放了。
既然通过采样点也可以操作,为什么还要帧呢?我们说过实际采样时,采样数据非常多,这时候用采样点做最小单位没有太大的意义,所以人们就设置了一个更大一点的,相对于我们来说更有意义的单位,帧。这就好比我们说二进制是一般都用字节表示,而没有说第几位的。但是本质上最终操作的还是里面的采样点。
我这里的描述只是为了方便理解,专业只是大家可自行百度。
下面上代码,代码中通过设置帧位置,来指定从什么位置开始播放声音,注意【1】处
package my;
import javax.sound.sampled.*;
import java.io.File;
import java.util.Scanner;
public class Player{
private static int consoleInput=-1;
private static final int EXIT = 0;
public static void main(String[] args) throws Exception {
/**
* 这个线程主要用来接收控制台输入退出命令【输入0】,跳出while循环,结束程序。。
*/
new Thread(()->{
Scanner scanner = new Scanner(System.in);
while (true){
if(scanner.nextInt()==0){
consoleInput = 0;
break;
}
}
}).start();
Player player = new Player();
Clip clip = player.loadSound();
player.playSound(clip);
}
public Clip loadSound() throws Exception {
String filePath = "C:\\Users\\cook\\Desktop\\javasounddemo-150249\\JavaSoundDemo\\audio\\1-welcome.wav";
File file = new File(filePath);
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format = stream.getFormat();
//1-welcome.wav共152736帧,每个帧占存储2个字节的采样数据,所以一共需要内存152736*2 = 305472个字节空间
// stream.getFrameLength()获取我们音频中总共有多少帧,所有的采样数据都分配在这些帧里面
// format.getFrameSize()获取每个帧的存储空间(几个字节)
DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat(), ((int) stream.getFrameLength() * format.getFrameSize()));
Clip clip = (Clip) AudioSystem.getLine(info);
clip.addLineListener((event)->{
System.out.println(event.getType().toString());
});
clip.open(stream);
return clip;
}
public void playSound(Clip clip ){
//【1】设置从第几帧开始播放,然后播放时就会从帧中读取当前位置的采样数据,开始播放了。本例中的1-welcome.wav共152736帧,设置从100000播放
clip.setFramePosition(100000);
clip.start();
while (true) {
try {
if(consoleInput == EXIT){
break;
}
System.out.println(clip.getMicrosecondPosition());
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();break;}
}
clip.stop();
clip.close();
}
}
上面代码中【1】处,设置了音频直接从第100000帧开始播放,大家可以注释掉此句代码,来听一下播放的效果。
另外除了通过帧来指定播放位置外,我们还可以直接通过时间来指定,代码如下,可以替换到上面代码【1】处测试
// 从指定的时间段开始播放,单位是为妙
clip.setMicrosecondPosition(4679092);
clip.start();
要想知道当前音频播放了多长时间了,通过如下代码即可
clip.getMicrosecondPosition();
到此,本章结束。学完这一章Clip接口中的几个方法就已经涉及到了。