本系列是多媒体技术课程的实验的整理。
实验一:声音录制
基本要求:使用windows api或Java media Framework(JMF)或javax.media.sound实现类似于windows录音机一类的小工具
bonus: 实现压缩录音
硬件: 麦克风
软件: 无/JMF/JDK
实验指导只给出实现的一种方法,仅供参考。
在实现时用到了JMF,需要先去下载JMF的相关jar包。最终实现的效果是录制声音,并保存为本地的一个.wav文件。关键代码如下所示。
package 声音录制;
import java.io.IOException;
import java.util.Vector;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.DataSink;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoProcessorException;
import javax.media.Processor;
import javax.media.control.StreamWriterControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
public class CaptureAudio {
public CaptureAudio(){
}
public static void run() {
CaptureDeviceInfo di = null;
Processor p = null;
StateHelper sh = null;//实现处理器(processor)的状态控制管理
Vector deviceList = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR, 44100, 16, 2));
if (deviceList.size() > 0){//得到此设备的CaptureDeviceInfo实例。
di = (CaptureDeviceInfo)deviceList.firstElement();
}
else{
// 找不到满足(linear, 44100Hz, 16 bit,stereo audio.)音频设备,退出。
System.out.println("找不到音频设备");
System.exit(-1);
}
try {//获得MediaLocator,并由此创建一个Processor。
p = Manager.createProcessor(di.getLocator());
sh = new StateHelper(p);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
} catch (NoProcessorException e) {
e.printStackTrace();
System.exit(-1);
}
if (!sh.configure(10000)){
System.out.println("configure wrong!");
System.exit(-1);
}
//定义待存储该媒体的内容类型(content type)。
p.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.WAVE));
// realize the processor.
if (!sh.realize(10000)){
System.out.println("realize wrong!");
System.exit(-1);
}
DataSource source = p.getDataOutput();
//定义存储该媒体的文件。
MediaLocator dest = new MediaLocator(new java.lang.String(
"file:///F:/Recorder/sound.wav"));
//创建一个数据池
DataSink filewriter = null;
try {
filewriter = Manager.createDataSink(source, dest);
filewriter.open();
} catch (NoDataSinkException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
} catch (SecurityException e) {
e.printStackTrace();
System.exit(-1);
}
StreamWriterControl swc = (StreamWriterControl)p.getControl("javax.media.control.StreamWriterControl");
if (swc != null)
swc.setStreamSizeLimit(5000000);//录音最大文件大小
try {
filewriter.start();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
sh.playToEndOfMedia(10000);//录音时间设置为10秒
sh.close();
filewriter.close();
}
}
package 声音录制;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Recorder extends JFrame{
private static final int WIDE = 350;
private static final int HEIGHT = 230;
public Recorder(){
this.setSize(WIDE, HEIGHT);
RecorderPanel panel = new RecorderPanel();
this.add(panel);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(100, 100);
this.setTitle("多媒体实验1——声音录制");
}
public static void main(String[] args) {
Recorder frame = new Recorder();
}
}
package 声音录制;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.IOException;
import java.util.Vector;
import javax.media.*;
import javax.media.control.StreamWriterControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
public class RecorderPanel extends JPanel{
JButton startbutton = new JButton("start");
JButton stopbutton = new JButton("close");
JLabel label = new JLabel("10秒钟声音录制,点击“start”开始",JLabel.CENTER);
JLabel label2 = new JLabel("录音文件将保存到F盘下的Recorder文件夹中",JLabel.CENTER);
public RecorderPanel(){
this.setLayout(new BorderLayout());
JPanel buttonpanel = new JPanel();
JPanel labelpanel = new JPanel();
buttonpanel.add(startbutton);
buttonpanel.add(stopbutton);
this.add(buttonpanel, BorderLayout.NORTH);
labelpanel.setLayout(new BorderLayout());
labelpanel.add(label,BorderLayout.CENTER);
labelpanel.add(label2,BorderLayout.SOUTH);
this.add(labelpanel);
startbutton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//label.setText("正在录音");
CaptureAudio player = new CaptureAudio();
player.run();
label.setText("声音录制成功");
label2.setText("可在F盘下的Recorder文件夹中查看");
}
});
stopbutton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
}
package 声音录制;
import javax.media.*;
public class StateHelper implements javax.media.ControllerListener {
Player player = null;
boolean configured = false;
boolean realized = false;
boolean prefetched = false;
boolean eom = false;//End of media.
boolean failed = false;
boolean closed = false;
public StateHelper(Player p) {
player = p;
p.addControllerListener(this);
}
public boolean configure(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
if (player instanceof Processor)
((Processor)player).configure();
else
return false;
while (!configured && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return configured;
}
/**
* 判断player是否已经实现
*/
public boolean realize(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
player.realize();
while (!realized && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return realized;
}
public boolean prefetch(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
player.prefetch();
while (!prefetched && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return prefetched && !failed;
}
public boolean playToEndOfMedia(int timeOutMillis) {
long startTime = System.currentTimeMillis();
eom = false;
synchronized (this) {
player.start();
while (!eom && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return eom && !failed;
}
public void close() {
synchronized (this) {
player.close();
while (!closed) {
try {
wait(100);
} catch (InterruptedException ie) {
}
}
}
player.removeControllerListener(this);
}
public synchronized void controllerUpdate(ControllerEvent ce) {
if (ce instanceof RealizeCompleteEvent) {
realized = true;
} else if (ce instanceof ConfigureCompleteEvent) {
configured = true;
} else if (ce instanceof PrefetchCompleteEvent) {
prefetched = true;
} else if (ce instanceof EndOfMediaEvent) {
eom = true;
} else if (ce instanceof ControllerErrorEvent) {
failed = true;
} else if (ce instanceof ControllerClosedEvent) {
closed = true;
} else {
return;
}
notifyAll();
}
}
最终实现实现效果如下所示