动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息



本月文章推荐
.超越梦想 EJB 3.0规范全新体验.
.处理链处理WEB服务中的请求/响应.
.JAVA数组和JAVA集合类的对象操作.
.系统构建高性能J2EE应用的五种核.
.使用 EJB 3.0 Java Persistence .
.J2SE1.5版本的新特性一览.
.移动开发谁领风骚 J2ME开发.
.Java服务器Tomcat 5.5.15&n.
.[JAVA100例]039、生成PDF文件.
.集成 Struts、Tiles 和 JavaServ.
.Java网络编程之URI、URL研究(上.
.Java 实践: 用 XQuery 进行屏幕搜.
.Java学习的捷径.
.关于传值和值的引用的问题!.
.正则表达式常用功能—查询提取替.
.J2SE(TM) 5.0 语言特性.
.java日期格式化.
.Java进阶学习:jar打包详解.
.分享关于j2me xmlReader的轻量级.
.RSS 2.0 Specification.

学做网页Applet录音机

发表日期:2008-1-5 |



学做网页Applet录音机

网络多媒体是目前Web应用的一个发展方向。在网页上录音,并发给朋友,相信他们收到你的声音一定非常兴奋。如今这已经是一项很普通的多媒体应用技术,笔者使用Java语言开发出了能够嵌入Web页面上的Applet录音机(界面外观如下图所示)。假如你有编程的爱好,不妨试试。在此,我将这种技术介绍给各位编程爱好者。

多媒体基本概念及常识

开发多媒体音频软件,必须了解一些多媒体基本概念,诸如采样、量化、量化位、采样频率、单双声道、音频编解码、音频压缩格式等概念。采样是把时间上连续的模拟信号变成时间上离散的、有限个样值的信号。量化是在幅度上把连续值的模拟信号变为离散值的数字信号。在时间轴上已变为离散的样值脉冲,在幅度轴上仍会在动态范围内有连续值,可能出现任意幅值,即在幅度轴上仍是模拟信号的性质,因此必须用有限个电平等级来代表实际量值。量化位是每个采样点能够表示的数据范围,经常采用的有8、12和16位。采样频率是将模拟声音波形转换为数字时,每秒钟所抽取声波幅度样本的次数,采样频率的计算单位是Hz(赫兹)。根据采样理论,为了保证声音不失真,采样频率应为声音频率的两倍左右。记录声音时,假如每次生成一个声波数据,称为单声道;每次生成二个声波数据,成为立体声(双声道)。量化位和采样频率越高,音质就越好。

正常人耳听觉的声音频率范围大约在20Hz至20KHz之间,人的语音频率大概在300Hz至3.4KHz之间。对于语音来说,采用8KHz的采样频率已经足够了。所以我们采用8KHz采样频率、16位量化位、单声道来记录和播放语音,就可以满足网页上的语音需求了。

网页录音机的制作过程

了解了以上常识,下面来看看录音机的制作过程。

首先要碰到的是音频采集。音频采集有很多种,JDK 1.3中构建TargetDataLine类实例来实现声音数据采集。在此例中,我采用Visual J++的J/Direct调用Windows API函数来实现声音的采集。

声音俘获主要由AudioCapture、AudioDataEvent、AudioDataListener三个类组成。我们依次按照0.1秒时间采样数据块的大小(即1600字节)作为所送出到系统的录音数据缓冲区大小,这样也就相当于每隔0.1秒声卡提交给我们一次声音数据。另外,使用Windows API方式声音采集有一个好处,录音过程不需要建立单独的线程。这是因为有回调函数的巨大作用,这样节省了系统资源,提高了程序的稳定性。

//声音俘获类:

...

public class AudioCapture{

...

public AudioCapture(){

...

waveincaps=new WAVEINCAPS();

wavehdr=new WAVEHDR[bufferlen];

}

public void addAudioDataListener(AudioDataListener lter){

listeners.addElement(lter);

}

void applyBuffer(){

for(int i=0;i<bufferlen;i++){

wavehdr[i]=new WAVEHDR();

int

adr=dlllib.addrOfPinnedObject(dlllib.getPinnedHandle(data[i]));

wavehdr[i].lpData=adr;

...

}

}

int chkData(byte[] a){//将整型低16位高低位交叉并转为字节

...

}

public void close(){

if(!useful)return;

isclose=true;

waveInStop(deviceid[0]);

...

}

...

synchronized void notifyListener(int minValue,byte[] audioData){

AudioDataEvent evt=new AudioDataEvent(this,minValue,audioData);

For(Enumeration enu=listeners.elements();enu.hasMoreElements();)

((AudioDataListener)enu.nextElement()).onAudioDataArrived(evt);

}

...

public void setMuteValue(int muteValue){

this.muteValue=muteValue;

}

/**@dll.import("WINMM",auto)*/

...

public static native int waveInReset(int hwi);

private class c extends Callback{

AudioCapture record;

c(AudioCapture tt){

record=tt;

}

...

}

}

//缓冲数据提交事件类:

import java.util.EventObject;

public class AudioDataEvent extends EventObject{

...

}

//事件侦听接口

import java.util.EventListener;

public interface AudioDataListener extends EventListener{

public abstract void onAudioDataArrived(AudioDataEvent evt);

}

第二步,数据的编码压缩存储。由声卡采集的数据是一连串16位脉冲编码调制(PCM格式)的数据,数据量很大,假如不采取压缩处理,不利于文件的存储和传输。所以要进行数据的压缩编码,这就是我们会碰到的声音编码数据格式。压缩编码方法有很多种,有GSM、IAM4、AU格式编码等,这些压缩算法比较简单,可以在很多网站上获得压缩和解压缩的源代码。笔者对这几种压缩格式进行了测试,其主要参数及品质对比见上表。

压缩格式主要参数及品质对比

压缩格式 GSM IMA4 AU

压缩比 10:1 4:1 2:1

文件大小 很小 小 中

声音质量 一般 好 好

编解码速度 慢 快 很快

数据量(byte/s) 165 400 800

一般来说,人说话时并不是非常连续的,哪怕是你有意发连续的声音,其实有很多时间段是处在静音状态(没有声音或声音很小,量化数据值很小),只要记录它的一个状态就可以了。所以声音数据区的数据格式就是(数据头+数据体)的方式。对于静音数据,数据头为0,数据体为空。

在声音回放时,先读数据头,假如数据头不为0,则解压数据体播放;假如数据头为0,则暂停一定时间或者写入一定长度的静音数据即可。采用这种方式可以大大减小记录语音文件,并且不影响声音的还原回放。

//处理录音数据到达事件

public void onAudioDataArrived(AudioDataEvent evt){

...

int min=evt.getAudioMinValue();

fileWriter.write((min==0?0:1));

if(min!=0){

Convert.BytesToInts(evt.getAudioData(),audiodata);

fileWriter.write(Codec.encode(evt.getAudioData()));

}

...

}

第三步,声音采集编码保存结束后,就可以回放我们录制的声音。

接下来我们要在网页上来播放它。Java Applet支持AU格式声音的回放,使用非常简单。所以我们把录制并压缩的声音数据解码为AU格式,就可以很方便地进行声音回放了。在sun.audio包中提供的au流数据播放sun.audio.AudioPlayer.start(InputStream),实际上是虚拟机的au播放类每隔50毫秒依次调用InputStream的read(byte[],abyte0,int i,int j)方法,每次读取长度为400字节的AU格式数据用来播放。我们知道,输入流的read方法是阻塞方式的,而解压缩声音数据是要费时的,假如在其请求数据时再解压数据并写入缓冲区,则播放声音时听起来会断断续续的,那是不可行的。所以需要单独建立解压缩数据的线程,也就是说从虚拟机的au播放类读取数据的线程中独立出来,用缓冲区做为两个线程的管道连接,解压缩线程不停地写入缓冲区中,播放线程不断地从缓冲区中读取并播放。这样一来,对于播放声音的暂停、停止等功能就很轻易实现。所以我们需要重载read(byte[],abyte0,int I,int j)方法。

//音频缓冲区类

import java.io.*;

public class AudioBuffer extends InputStream{

int capacity=4096;

...

public AudioBuffer(AudioPlayer ap){

player=ap;

clearData();

}

public void close(){

isclose=true;

synchronized(putManager){

if(waitingPut>0)putManager.notify();

}

synchronized(getManager){

if(waitingGet>0)getManager.notify();

}

}

public void clearData(){

...

}

public void suspend(){ispause=true;}

public void resume(){ispause=false;}

public void write(int i){

synchronized(putManager){

while(emptyBytes<1){

waitingPut++;

try{

putManager.wait();

}catch(InterruptedException _ex){}

waitingPut--;

}

...

}

synchronized(getManager){

usedBytes++;

if(waitingGet>0)getManager.notify();

}

}

public void write(byte[] d){

write(d,0,d.length);

}

public void write(byte[] d,int i,int j){

...

synchronized(getManager){

usedBytes+=j;

if(waitingGet>0)getManager.notify();

}

}

public int read(){

...

}

public int read(byte[] d){

return read(d,0,d.length);

}

public int read(byte[] d,int i,int j){

if(isclose)return -1;

if(ispause){

d[i]=127;

return 1;

}

synchronized(getManager){

...

}

System.arraycopy(data,readPtr,d,i,k);

ReadPtr+=k;

readPtr%=capacity;

usedBytes-=j;

}

synchronized(putManager){

emptyBytes+=j;

if(waitingPut>0)putManager.notify();

}

try{

player.notifyListener(AudioPlayEvent.PLAY_DATA,d);

}catch(Exception e){}

return j;

}

}

//音频播放器类

public class AudioPlayer implements Runnable{

...

AudioBuffer buffer=new AudioBuffer(this);

sun.audio.AudioPlayer.start(buffer);

...

byte[] auData=new byte[400];

//存放解压后的au数据

int compressLength=165;

//GSM格式为165;IMA格式为400;AU格式为800

byte[] compressData=new byte[compressLength];

//存储从文件流中读取的压缩格式数据

...

public void run(){

...

fileInputStream.read(compressData);//从音频文件读取压缩格式数据,此输入流要处理静音

Codec.decode(abyte0,auData); //解压缩数据到auData

Buffer.write(auData,0,400);//写入到缓冲区

...

}

...

}

最后,将上述各个模块拼接起来,并把GUI做好就可以使用了。假如在GUI上加入声音显示效果,你的录音机就更酷了。

总结

这里介绍的声音处理的主要技术,可以组合或衍生使用。例如,可以在网页上方便地实现声音回放;可以加入调节播放起点(跳跃播放)功能,而不使用其它播放器;还可以做语音留言系统。假如数据通过流格式以组播方式实时传出,另一端接收下来然后播放出来,又可非常简单地实现实时语音系统,即语音聊天。另外,有了自己的语音库,还可以实现简单的语音合成技术,让计算机读出文本内容(请访问播放程序演示地址:http://home.njenet.net.cn/hawa/player.htm)。
上一篇:一个applet-servlet通讯的例子 人气:450
下一篇:学习如何使 Java 应用程序启动更快以及占用更少的内存 人气:858
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-7-19 Roclog v3.1.4 SP1
2008-7-19 马克斯CMS(Maxcms) v1.1 Build 0
2008-7-19 乐学LBBS无限级目录图片直读系统
2008-7-19 PHP在线考试系统PPExam v1.2.5
2008-7-19 APJE私服发布系统 v2.0
2008-7-19 寻觅图书管理系统 v1.12
2008-7-19 寻觅学校管理系统
2008-7-19 义乌网站目录baidu新闻订阅 v1.0
2008-7-19 牛仔IIS日志蜘蛛爬行记录分析器
2008-7-19 UltraEdit 简体中文增强版 14.10
2008-7-19 CentOS 5.2 i386 LiveCD
2008-7-19 Snapture多功能相机 v1.4
2008-7-19 iAcces中文输入法 v1.0Build016
2008-7-19 Cookbook烹饪秘籍 v2.5
2008-7-19 苹果专用DVD转换工具 v1.1.59汉化
2008-7-19 Modem修复软件ZiPhone修改版04.0
2008-7-19 AgileMessenger即时通讯工具美化
2008-7-19 Sketches画图软件 v0.7b6破解版


  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵