java sound api_Java Sound API

Java Sound API是javaSE平台提供底层的(low-level)处理声音接口。

例外,java也提供了简单的实用的高层媒体接口(higher-level) - JMF(Java Media Framework)。

Java Sound API 将需要处理的数字音频分为:simpled-audio和midi,

分别提供Package来处理它们:

javax.sound.simpled

javax.sound.midi

同时SOUND API还提供了第三方的扩展接口:

javax.sound.simpled.spi

javax.sound.midi.spi

*注:spi : service provider interface

Sampled Audio

采样音频(simpled-audio)不仅包含从模拟信号采样来的数字音频,还包括电脑合成的。

称作digital-audio更为合适。

为了能够让设备播放采样声音,程序需要处理 audio input, output device, audio data buffers。

还有混音处理(mix multiple streams of audio into one stream)。

SOUND API 可以使用3种方式传输声音数据:stream, buffered fashion, in-memory unbuffered fashion。

第三种方式适合数据量不大,能够一次载入的所有数据的情形。这样,声音的响应较快,循环和随机定位也会很简单。

使用SOUND API播放声音至少需要3样东西:

lformatted audio data,

la mixer,

la line.

Mixer

调音台

technically the Mixer itself is also a kind of Line

Line

音频数据管道。

Clip extends Line

将需要播放的音频数据装载进来。

preloads audio data from a sound file into clips

A Clip is a data line into which audio data can be loaded prior to playback. Because the data is

pre-loaded rather than streamed, the clip‘s duration is known before playback, and you can choose any

starting position in the media. Clips can be looped, meaning that upon playback, all the data between two

specified loop points will repeat a specified number of times, or indefinitely.

SourceDataLine extends Line

accept real-time stream of audio data

feed audio to the Mixer

A SourceDataLine receives audio data for playback. It provides methods for writing data to the

source data line‘s buffer for playback, and for determining how much data the line is prepared to receive

without blocking.

TargetDataLine

A TargetDataLine receives audio data from a mixer. Commonly, the mixer has captured audio data

from a port such as a microphone; it might process or mix this captured audio before placing the data in

the target data line‘s buffer. The TargetDataLine interface provides methods for reading the data

from the target data line‘s buffer and for determining how much data is currently available for reading.

Port extends Line

simple Line

Line接口的继承关系图

361273_1.png

AudioSystem

AudioSystem提供音频资源的访问服务。

通过AudioSystem,可以知道什么样的资源可以被识别。

可从AudioSystem获得的资源:

lMixers, AudioSystem类可以提供一张已经安装的Mixer列表

lLines

lFormat conversions

lFiles and streams

Mixer的获得

Mixer.Info

AudioSystem.getMixerInfo():Mixer.Info

可以获得一张Mixer信息列表。

每个Mixer.Info包含如下关键信息:

lName

lVersion

lVendor

lDescription

我机器上的Mixer列表,WinXP,JDK_1.4.2

[INFO 0]

INFO.NAME:Java Sound Audio Engine

INFO.VERSION:1.0

INFO.VERDOR:Sun Microsystems

INFO.DESCRIPTION:Software mixer and synthesizer

[INFO 1]

INFO.NAME:Microsoft ?ù??????÷

INFO.VERSION:Unknown Version

INFO.VERDOR:Unknown Vendor

INFO.DESCRIPTION:No details available

[INFO 2]

INFO.NAME:Realtek AC97 Audio

INFO.VERSION:Unknown Version

INFO.VERDOR:Unknown Vendor

INFO.DESCRIPTION:No details available

[INFO 3]

INFO.NAME:Realtek AC97 Audio

INFO.VERSION:5.10

INFO.VERDOR:Unknown Vendor

INFO.DESCRIPTION:Unknown Description

获取Mixer

AudioSystem.getMixer( MixerInfo ):Mixer

如果只从Mixer.Info提供的信息无法确定需要的Mixer,

不妨创建出所有的Mixer,使用时检查它们的能力,使用合适那个。

例如,你可能需要一个Mixer,能够将混音好的数据同时写入一定数目的目标数据管道(TargetDataLine).

使用Mixer.getMaxLines(Line.Info info):int来了解Mixer的输出能力。info就是指定的TargetDataLine

获得指定类型Line

2种方法获得Line

l直接由AudioSystem获得,AudioSystem.getLine( Line.Info ):Line

l由Mixer获得

从AudioSystem直接获得Line

static Line AudioSystem.getLine( Line.Info )

不同于Mixer.Info,Line.Info不是文本信息,而是Line的类信息。

Line.Info是抽象类,所以使用它的子类DataLine.Info,Port.Info。

下面是通过Line.Info获得Line的示例:

TargetDataLine line;

DataLine.Info info = new DataLine.Info(TargetDataLine.class,

format); // format is an AudioFormat object

if (!AudioSystem.isLineSupported(info)) {

// Handle the error.

}

// Obtain and open the line.

try {

line = (TargetDataLine) AudioSystem.getLine(info);

line.open(format);

} catch (LineUnavailableException ex) {

// Handle the error.

//...

}

Port.Info定义一系列静态的Port.Info对象,MICROPHONE,SPEAKER,etc.

从Mixer获得Line

getSourceDataLine()

getTargetDataLine()

getLine()

AudioSystem对象模型

361273_2.png

AudioPermission

音频资源访问许可。

利用JAVA-SOUND-API播放声音

可以使用2种Line来播放声音,Clip,SourceDataLine。

Clip一次载入需要播放的声音资源,而SourceDataLine以流的方式传输声音数据。

使用Clip

当使用getLine()获得Clip后,还要保证其他的程序在你播放前不能获取它,调用open()方法独占它:

void open( AudioInputStream stream );

void open( AudioFormat, byte[] data, int offset, int bufferSize );

Clip默认从音频的开头开始播放,除非使用setFramePosition(),setMicroSecondPosition()设定其他位置。

Clip.start()播放,Clip.stop()暂停。

getLevel(),获得声音高度。

isActive(),Clip是否正在播放。

使用SourceDataLine

open(AudioFormat),打开source dataLine,但不指定数据,使用默认的buffer size。

open(AudioFormat, bufferSize),指定buffer size.

合理设置buffer size,保证开始载入的延时能够被接受,又尽量减少IO访问。

open()之后,调用start()容许SourceDataLine一有数据就开始播放,使用write()不停的输入数据。

void write( byte[] b, int offset, int length );

SourceDataLine开始播放后,向Mixer传输数据,当Mixer开始向target传输数据时,SourceDataLine产生一个START事件。

这是SourceDataLine被认为是活动的(active)。

isRunning()表明Line是否start()了。

isActive()表明Line是否开始播放。

write()方法向buffer size中写入数据,如果buffer已满,还剩下一些数据,该方法会阻塞;否则,是不阻塞的。

可以使用DataLine.available()知道buffer size还能写入多少数据。

事实上,可以另开线程去使用write(),而不用考虑阻塞的问题。

drain()方法在所有数据播放完后返回。

所有在写完数据后,调用drain(),到它返回时再是否Line。

line.write(b, offset, numBytesToWrite);

//this is the final invocation of write

line.drain();

line.stop();

line.close();

line = null;

flush()清空buffer中的剩余数据,Line在stop时才能调用。

有如下情形,Line会产生STOP事件:

l调用drain()

l调用stop()

l调用flush()

l输出完旧的数据,而新的数据未到时。

STOP事件意味着isActive()返回false.

start()调用之后,isRunning()都会返回true,知道stop()被调用。它不是依据STOP事件产生返回值的。

而isActive()是依据START和STOP事件的。

监视Line的状态

使用LineListener响应Line的事件。

void Line.addLineListener( LineListener );

当调用open(),close(),start(),stop()会产生OPEN,CLOSE,START,STOP事件。

多个Line同步播放

有些Mixer提供方便的同步功能,对一组Lines使用open(),close(),start(),stop(),保证它们的同步。

可以使用如下方法,检查Mixer是否支持同步功能:

boolean isSynchronizationSupported( Line[] lines, boolean maintainSync )

第二个参数表明同步精度,是采样同步,还是只是start(),stop()保持同步,并不维护播放过程同步。

AudioFormat

音频采样的格式,不是音频文件的格式。

l编码技术,一般都是PCM( pulse code modulation )

l声道数目(1,单声道;2,双声道;等等)

l采样频率sample rate

l样本的位数number of bits per sample

l帧速率Frame rate

lFrame Size in bytes

lByte Order( big-endian or little-endian )

AudioFileFormat:

音频文件格式。

The file type( WAV,AIFF,etc )

The file length in bytes

The length, in frames, of the audio data contained in the file

An AudioFormat that specifies data format of the audio data in the file

AudioInputStream extends InputStream

无须考虑文件的格式,就能操作Samples。

读取音频文件

AudioSystem提供2中方法读取音频文件:

l根据音频文件中音频数据的格式信息

l使用一个指定了音频数据格式的流

使用如下方法获得音频文件中音频数据的格式信息:

static AudioFileFormat getAudioFileFormat(File);

static AudioFileFormat getAudioFileFormat(InputStream);

static AudioFileFormat getAudioFileFormat(URL);

利用如下方法获得第二种方法提到的音频数据流:

static AudioInputStream getAudioInputStream(File)

static AudioInputStream getAudioInputStream(InputStream)

static AudioInputStream getAudioInputStream(URL)

读取音频文件数据的步骤:

1)获得AudioInputStream对象

2)创建一个字节数组,存放一次读入的数据块

3)不断地从audio流中读入数据,播放或处理数据。

示例代码如下:

int totalFramesRead = 0;

File fileIn = new File(somePathName);

// somePathName is a pre-existing string whose value was

// based on a user selection.

try {

AudioInputStream audioInputStream =

AudioSystem.getAudioInputStream(fileIn);

int bytesPerFrame =

audioInputStream.getFormat().getFrameSize();

// Set an arbitrary buffer size of 1024 frames.

int numBytes = 1024 * bytesPerFrame;

byte[] audioBytes = new byte[numBytes];

try {

int numBytesRead = 0;

int numFramesRead = 0;

// Try to read numBytes bytes from the file.

while ((numBytesRead =

audioInputStream.read(audioBytes)) != -1) {

// Calculate the number of frames actually read.

numFramesRead = numBytesRead / bytesPerFrame;

totalFramesRead += numFramesRead;

// Here, do something useful

// with the audio data that‘s

// now in the audioBytes array...

}

} catch (Exception ex) {

// Handle the error...

}

} catch (Exception e) {

// Handle the error...

}

写音频文件

通过下列方法知道AudioSystem支持哪些音频文件格式写入:

static boolean isFileTypeSupported( AudioFileFormat.Type,AudioInputStream );

static AudioFileFormat.Type[] getAudioFileTypes();

static AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream);

利用AudioSystem.write()方法向文件写入指定格式的音频数据:

static int write( AudioInputStream, AudioFileFormat.Type, File );

文件或数据格式转换

“Java Sound Programmer Guide” – chapter 7

Audio File Format Convertion

Audio Data Format Convertion

PCM

PCM脉冲编码调制是Pulse Code Modulation的缩写。

PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。

PCM是数字音频中最佳的保真水准,近似看成“无损”编码。

PCM编码的优点是音质好,缺点是数据量大。

JAVA SOUND API对于其它编码格式,在播放前都会转换成PCM格式。

DAC:digital-to-analog converter,数模转换器

Decibel:分贝。pl.decibels

PAN:声象,该通道信号在左右音箱之间的立体声位置。

GAIN:增益

REVERB:数字混响。

Acoustics:声学

资源

《Java Sound programmer guide》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java实现的小程序_Java实现 微信小程序 + 消息推送

实现效果:下面要显示五个字段接下来,参照官方文档,一步步实现:一、官方给出请求示例、返回示例二、根据上面编写实体类(1)请求参数Datapublic class SendTemplateReq {/*** 接收者(用户)的 openid*/private String touser;/*** 所…

vb excel 整行删除_Excel中常用的批量处理都不掌握,那就真的Out了

针对一些有规律,能批量处理的数据,必须采用批量处理的方法,否则对于工作效率就会有很大的影响。今天我们来学习的内容是Excel中的6个批量处理技巧。一、Excel批量技巧:批量求和。目的:按照“季度”和“产品”两个维度计…

exe编辑器_【小功能】Unreal Editor中调用exe

后续文章更新移步→微信公众号“虚幻社区”(mantra-xhsq),您的支持是我创作的动力。在程序界混,哪能碰上不改需求的策划 --Mantra最近遇到了一个奇葩的需求,在Unreal Editor的Toolbar中添加一个快捷键,可以…

html select选择事件_按键精灵的Html系列命令实战讲解

金猪脚本(原飞猪脚本)以按键精灵教学为主,涉及UiBot,Python,Lua等脚本编程语言,教学包括全自动办公脚本,游戏辅助脚本,引流脚本,网页脚本,安卓脚本,IOS脚本,注册脚本,点赞脚本,阅读脚本以及网赚脚本等各个领域。想学习按键精灵的朋友可以添加金猪脚本粉丝交流群:554…

java 验证码_java学习之web基础(6):使用Response的输出流在页面输出验证码

package 输出并且我们可以写一个简单的网页&#xff0c;来实现点击更新验证码<!DOCTYPE html>

java socket编程实现聊天程序_java Socket编程 聊天程序 服务器端和客户端

[java]代码库package com.gufengxiachen.sthreadchatapp;/*** author GUXIA*/import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;imp…

电商前台模板中文html5_跨境电商平台上产品如何上传?虾皮新版批量上传工具使用指南分享...

大家好&#xff0c;这里是天师跨境&#xff0c;今天来为电商新人们解答一下关于如何在跨境电商平台上上传产品的疑惑&#xff0c;顺便介绍一下虾皮跨境平台的新版批量上传工具是如何使用的。在跨境电商平台上开店的新手们在入驻成功后&#xff0c;一般最先面临的问题就是上传产…

移动端 关闭浏览器事件_前端开发中什么是移动端点透事件?

点透事件&#xff1a;是指两个元素其中一个元素具有默认的点击事件&#xff0c;当我们让不具有点击事件的元素隐藏起来&#xff0c;会触发另一个元素的点击事件&#xff0c;这种行为被称之为点透事件。如下图所示&#xff1a;当我们给div元素添加touchstart事件让div元素隐藏起…

清除浏览器缓存之后为什么还是显示旧的html页面_Web缓存控制策略详解

管理Web缓存的最常用和最有效的方法之一是通过Cache-Control HTTP标头&#xff0c;由于此标头适用于Web页面的缓存&#xff0c;这意味着我们页面上的所有内容都可以具有非常精细化的缓存策略。通过各种自定义策略&#xff0c;我们控制的策略就可以变得非常复杂和强大。Cache-Co…

java jtextfield 事件_JAVA JTextField事件处理

初学JAVA&#xff0c;笔记&#xff1a;package windows;import javax.swing.*;import java.awt.*;import java.awt.event.*;class WindowFlow extends JFrame implements ActionListener{private static final long serialVersionUID 1L;JTextField text1,text2;WindowFlow(St…

js封装函数_JavaScript基础-如何封装函数来改变元素的位置

点击右上方红色按钮关注“小郑搞码事”&#xff0c;每天都能学到知识&#xff0c;搞懂一个问题&#xff01;大家好&#xff01;我是/小郑搞码事/的小郑今天给大家分享JavaScript的基础知识-改变元素的位置。没错&#xff0c;用JS实现过动画的同学都应该了解一点&#xff0c;简单…

java程序设计与实践教程 王薇 doc_Java程序设计与实践教程 王薇主编 答案

Java程序设计与实践教程 王薇 主编 董迎红 副主编 课后习题 答案第1章 JAVA简介一、判断题1.√ 2.√ 3. 4. 5. 6.√ 7.√ 8.√ 9. 10.二、填空题1.Application Applet 2. 类(字节码文件、目标文件) .class3.对象 4. 主 5. J2SE J2EE J2ME三、选择题1.B 2. D 3.B 4.B 5. A四、简…

maya藤蔓插件_Maya特效制作之植物生长动画制作教程(二)之多条藤蔓动画制作...

四、制作多条蔓藤植物下面我们要让很多植物在这个“崖壁”上生长出来&#xff0c;也就是要重复很多次前面的工作&#xff0c;当然可以这样一步一步地做&#xff0c;在“崖壁”面片上手动画很多的线&#xff0c;但下面尝试一种新的方法来制作&#xff0c;让粒子在“崖壁”面片Pl…

mysql数据库导入导出_MySQL数据库导入导出详解

MySQL数据库的导入&#xff0c;有两种方法&#xff1a;1) 先导出数据库SQL脚本&#xff0c;再导入&#xff1b;2) 直接拷贝数据库目录和文件。在不同操作系统或MySQL版本情况1. 概述MySQL数据库的导入&#xff0c;有两种方法&#xff1a;1) 先导出数据库SQL脚本&#xff0c;再导…

代码统计工具有哪几种_跟我学“Linux”小程序Web版开发(四):引入统计及Crash收集...

在完成了产品的基础开发以后&#xff0c;接下来需要进行一些周边的工作&#xff0c;这些周边工具将会帮助下一步优化产品。在完成了产品的基础开发以后&#xff0c;接下来需要进行一些周边的工作&#xff0c;这些周边工具将会帮助下一步优化产品。为什么要加应用统计和 Crash 收…

错误:不能继续进行下一步操作 openfire 设置._如何为MacBook或Mac电脑恢复出厂设置...

mac电脑经过长时间的使用后会变得卡顿&#xff0c;或者因为部分操作方式改变以至于给我们在使用过程中造成障碍&#xff0c;此时我们可以进行恢复出厂设置&#xff0c;以此来解决部分问题。那么该如何为MacBook或Mac电脑恢复出厂设置呢&#xff1f;下面跟随小编来一起学习一下吧…

mac显示网速_Mac网络流量监控工具——NetWorker pro

NetWorker pro for Mac是Mac系统上一款轻量级的网速实时监测软件&#xff0c;可以让用户在菜单栏上显示当前的网络上传下载速度&#xff0c;可以在速度和流量两种模式之间切换&#xff0c;也可以选择不同的网络模式来进行监测。此外&#xff0c;networker mac还提供有关当前活动…

matlab gui学习手记_MATLAB论坛不可错过的30例GUI源代码

​过去的两年中&#xff0c;我经常会在微信公众号和知乎上分享&#xff0c;平时如何通过MATLAB制作GUI&#xff0c;来让自己的工作和生活更加便捷与高效。在分享的同时&#xff0c;有不少朋友会给我留言提问关于MATLAB GUI的问题。而其中的许多问题&#xff0c;其实都是能够在M…

线性回归csv数据集_用mxnet的gluon线性回归训练只有两个特征的数据集

前言自从上次试着用最基础的线性回归训练一个有80个特征的数据集&#xff0c;梯度爆炸之后&#xff0c;今天拿一个简单到不能再简单的数据集试试能不能成功收敛。途中我们又会遇到什么问题&#xff1f;数据集来自吴恩达机器学习课程第二周的课后练习。原本是txt文件&#xff0c…

java中include标签的用法_原 ng-include用法分析以及多标签页面的简单实现方式

在平时的项目开发中&#xff0c;应该会经常遇到上图所示的需求&#xff0c;就是在一个页面中有多个标签&#xff0c;被选中的标签颜色会高亮显示&#xff0c;切换不同标签显示相应的不同内容。如果内容代码过多则写在同一个html文件就会显得特别乱&#xff0c;所以这里我们最好…