HappyLifeLife.com
HappyLifeLife.com
HappyLifeLife.com 登录 HappyLifeLife.com 注册 HappyLifeLife.com
爱新闻 爱生活
爱分享 爱学习
爱读书 爱探索
爱音乐 爱宇宙
爱电影 爱地球
爱阅读 爱世界
爱运动 爱科技
资料宝库

Java 音频接口
HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com
完成录制音频文件的过程。我们使用类似于 IAudioPlayer 接口,称为 IAudioRecorder 的接口。
IAudioRecorder 接口非常象播放音频中演示的 IAudioPlayer,但它用于录制而不是回放。
与 IAudioPlayer 一样,IAudioRecorder 接口仅包含很通用的方法(例如,startRecording、stopRecording 和 save),
因此简化了使用并封装了特定于 Java Sound 的功能。
虽然关于播放音频的一章与关于录制的本章之间有许多相似之处,但在实现方面却有许多很重要的不同之处。
首先,没有简单的对象能象 Clip 简单地播放音频那样来录制声音。
结果,我们不得不直接同 I/O 流、线路、字节数组和音频数据转换等打交道。
在 AudioPlayer 示例中,我们学习了如何从给定的声音文件中检索音频格式。
然而在 AudioRecorder(IAudioRecorder 的基本实现)中,我们控制用于录制实际音频的设置。
由于一旦录制了音频就难以更改音频格式,所以这需要更多地关注音频设置。
下面介绍 AudioRecorder 接口。AudioRecorder 接口与 AudioPlayer 之间有一点不同,
不同之处在于这个类需要考虑音频格式。对于 AudioPlayer,根据从读入的音频数据中检索的格式,
从 AudioSystem 类检索线路。
然而,在音频录制时,AudioRecorder 将控制录制音频所用的格式。
下面是 AudioRecorder 接口代码:
public interface IAudioRecorder
{
public void startRecording();
public void stopRecording();
public void reset();
public void setAudioFormat();
public AudioFormat getAudioFormat();
CD-quality settings */
public void setDefaultAudioFormat();
public boolean
saveToFile(File file, AudioFileFormat.Type fileType);
}

标准音频设置

对于缺省 AudioFormat,我们将使用 CD 音频设置和 WAV 文件格式以使示例简单。
下面是缺省音频格式的规范:
编码:带正负号的 PCM
采样率:44.1 kHz(CD 音质)
采样大小:16 位或两个 8 位字节(CD 音质)
声道数:两个或立体声(CD 音质)
帧大小:32 位或 4 字节(16 位采样大小 * 2 声道 = 每字节 32 位/8 位每字节 = 4 字节)
帧速率:44.1 kHz(采样率)
大尾数法:否
接下来,我们将为 IAudioRecorder 接口中的缺省音频格式声明 public static final 变量。下面是格式:
*/
public static final AudioFormat DEFAULT_AUDIO_FORMAT = new AudioFormat
(
AudioFormat.Encoding.PCM_SIGNED,
44100f,
2,
2,
4,
44100f,
false
);
除了我们必须实例化一个 AudioFormat 对象,而不是从 AudioInputStream 检索它之外,
检索输入 Line 的过程与检索 Clip 的过程相同。要检索一个输入 Line,请完成下列步骤:
实例化 AudioFormat 对象。
实例化 DataLine.Info 对象,该对象引用适当的 AudioFormat 并指定请求的 Line 类型。
从 AudioSystem 请求 Line。
与 AudioPlayer 示例相同,我们将请求一个 TargetDataLine 实例来接收音频输入而不是直接实例化 TargetDataLine。
在有了 TargetDataLine 实例之后,需要打开它以完成初始化。
与回放示例相同,AudioSystem 类返回一个缺少内容的容器。
另外,AudioRecorder 被设计成除非被覆盖,否则使用 DEFAULT_AUDIO_FORMAT。
下面是代码:
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format, line.getBufferSize());

TargetDataLine 中的读方法

一旦提供了音频,我们就需要使用 TargetDataLine 接口中的 read 方法读取并储存音频数据。
让我们查看 read 方法以了解如何捕获音频输入:
public int read(byte[] b, int offset, int length)
byte[] b:音频数据输入被写入这个 byte[]。
状态 int 是由 read 方法返回的,因此必须传入 byte[] 以使它只具有单个返回类型。
int offset:指定数组内的偏移量以开始写音频。
当在缓冲区中已有数据并且您想将新数据添加到已有数据的结尾时,可以使用偏移量。
对于我们简单的音频录制器用途,偏移量将始终为零。
这将新捕获的音频数据放在缓冲区的开始处。
int length:指定从音频输入读取的字节数。在从输入读取 length 个字节以前,该方法会一直阻塞。
因此,read 方法应该在其自己的线程中执行;否则,将冻结该接口。
假设 AudioRecorder 被正确线程化(但我不会详细讨论线程化,因为它超出本教程的范围)。
检查示例源代码(可以在参考资料中获取)以了解更多信息。

准备检索的字节数组

首先,我们需要计算传入 read 方法中的 byte 数组的大小。这是通过下列计算完成的:
int frameSizeInBytes = format.getFrameSize();
int bufferLengthInFrames = line.getBufferSize() / 8;
int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
byte[] data = new byte[bufferLengthInBytes];
接下来,我们实例化一个输出流以将 byte 数组写入。
用这种方法,如果我们进行后续读取,则可以写入到输出流而不需要为数据管理编写更多代码。
ByteArrayOutputStream out = new ByteArrayOutputStream();

读取音频数据并对其进行高速缓存

现在,我们已经准备好读入音频。可以通过调用 TargetDataLine 中的 read 方法读取音频数据。
read 方法在 while 循环中,因此我们可以连续地录制而不用创建一个非常大的 byte[]。
从 TargetDataLine 中读取的数据将被写到 ByteArrayOutputStream 进行存储。
如果 read 方法返回 -1(表示错误),则我们还需要执行检查以中断循环。
下面是代码:
int numBytesRead; //Cache the number of bytes we have read
while (recording)
{
if((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1)
{
break;
}
out.write(data, 0, numBytesRead);
}

将 ByteArrayOutputStream 转换成 AudioInputStream

接下来,我们将把 ByteArrayOutputStream 转换成 AudioInputStream。这样做有两个原因:
将音频保存到一个文件
将音频缓冲区保存到文件之前回放它
下面是用于转换的代码:
byte[] audioBytes = out.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
audioInputStream =
new AudioInputStream(bais, format, audioBytes.length/frameSizeInBytes);

将音频缓冲区保存到文件

既然我们已经有了 AudioInputStream,则我们可以调用 AudioSystem 中的 write 方法以将缓冲区保存到文件。
在保存该文件之前,我们需要指定 AudioFileFormat。AudioFileFormat 包含下列信息:
AudioFormat
AudioFileFormat.Type
AudioFileFormat.Type 是 AudioFileFormat 的一个内部类,它定义下列文件类型的全局常量:
AIFC
AIFF
AU
SND
WAV
我们需要提供输出文件和文件类型常量。
我们将假设调用方法将为我们指定 AudioFileFormat.Type 类.
下面是 save 方法的代码:
public boolean saveToFile(File file, AudioFileFormat.Type fileType)
throws Exception
{
audioInputStream.reset();
return (AudioSystem.write(audioInputStream, fileType, file) == -1);
}

支持的文件类型

AudioFileFormat.Type 常量对应的文件类型不是保证受支持的。
您可以通过使用 isFileTypeSupported(AudioFileFormat.Type type) 方法询问 AudioSystem 类来确定受支持的文件类型。
回放音频缓冲区
HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com HappyLifeLife.com
首篇 上一篇 总共539篇,当前第147 下一篇 末篇
天天快乐生活[HappyLifeLife.com]
欢迎来访 快乐空间 热点新闻 我的分享 读书频道 七彩生活 精彩世界 快乐搜索 
ICP备15040518 | ©1999-2018 HappyLiveLife.com 版权所有 | 服务 | 爱新闻 | 爱分享 | 在线搜索 | 招贤纳士
欢迎来访 快乐空间 热点新闻 我的分享 读书频道 七彩生活 精彩世界 快乐搜索 
ICP备15040518 | ©1999-2018 HappyLiveLife.com 版权所有 | 服务 | 爱新闻 | 爱分享 | 在线搜索 | 招贤纳士