?? captureplaybackserver.java
字號:
package tcpSoundCommunication;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;
//import javax.swing.event.*;
import javax.swing.border.*;
import java.util.Vector;
//import java.util.Enumeration;
import java.io.*;
import javax.sound.sampled.*;
import java.awt.font.*;
import java.text.*;
//import java.net.ServerSocket;
/**
* audio can be saved either as a WAVE, AU or AIFF. Or load an audio file
* for streaming playback.
*/
public class CapturePlaybackServer extends JPanel implements ActionListener, MyControlContext {
final int bufSize = 16384; //2048 x 8 8個雙字節長 22048=10多?
MultiServerListener multiServerListener = new MultiServerListener();
FormatControls formatControls = new FormatControls();
Capture capture = new Capture();
Playback playback = new Playback();
//存放聲音的對象——audioInputStream
AudioInputStream audioInputStream;
SamplingGraph samplingGraph;
JButton playB, captB, pausB, loadB,connB;
JButton auB, aiffB, waveB;
JTextField textField;
String fileName = "untitled";
String errStr;
double duration, seconds;
File file;
//
Vector lines = new Vector();
public CapturePlaybackServer() {
/**
* 關于幾個容器(P1,P1右面部分P2)——panel的布局,外觀
*/
setLayout(new BorderLayout());
EmptyBorder eb = new EmptyBorder(5, 5, 5, 5);
SoftBevelBorder sbb = new SoftBevelBorder(SoftBevelBorder.LOWERED);
setBorder(new EmptyBorder(5, 5, 5, 5));
JPanel p1 = new JPanel();
//P1——formatControls左面格式參數設置
p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
// p1.add(formatControls);
//P2——:
JPanel p2 = new JPanel();
p2.setBorder(sbb);
p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
//buttonsPanel上方 MultiServerListener
JPanel buttonsPanel = new JPanel();
buttonsPanel.setBorder(new EmptyBorder(10, 0, 5, 0));
connB = addButton("斷開所有連接", buttonsPanel, true);
playB = addButton("Play", buttonsPanel, false);
captB = addButton("Record", buttonsPanel, true);
pausB = addButton("Pause", buttonsPanel, false);
loadB = addButton("Load...", buttonsPanel, true);
p2.add(buttonsPanel);
//samplingPanel畫板
JPanel samplingPanel = new JPanel(new BorderLayout());
eb = new EmptyBorder(10, 20, 20, 20);
samplingPanel.setBorder(new CompoundBorder(eb, sbb));
samplingPanel.add(samplingGraph = new SamplingGraph());
p2.add(samplingPanel);
//savePanel下方
JPanel savePanel = new JPanel();
savePanel.setLayout(new BoxLayout(savePanel, BoxLayout.Y_AXIS));
JPanel saveTFpanel = new JPanel();
saveTFpanel.add(new JLabel("File to save: "));
saveTFpanel.add(textField = new JTextField(fileName));
textField.setPreferredSize(new Dimension(140, 25));
savePanel.add(saveTFpanel);
JPanel saveBpanel = new JPanel();
auB = addButton("Save AU", saveBpanel, false);
aiffB = addButton("Save AIFF", saveBpanel, false);
waveB = addButton("Save WAVE", saveBpanel, false);
savePanel.add(saveBpanel);
p2.add(savePanel);
p1.add(p2);
add(p1);
}
public void open() {
try {
multiServerListener.getServer();
}
catch (Exception ex1) {
}
}
//fuwuqi
public void close() {
if (playback.thread != null) {
//doClick()模擬一個按鈕的click動作!時間為0;
playB.doClick(0);
}
if (capture.thread != null) {
captB.doClick(0);
}
}
private JButton addButton(String name, JPanel p, boolean state) {
JButton b = new JButton(name);
b.addActionListener(this);
b.setEnabled(state);
p.add(b);
return b;
}
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
//保存到文件
if (obj.equals(auB)) {
saveToFile(textField.getText().trim(), AudioFileFormat.Type.AU);
}
else if (obj.equals(aiffB)) {
saveToFile(textField.getText().trim(), AudioFileFormat.Type.AIFF);
}
else if (obj.equals(waveB)) {
saveToFile(textField.getText().trim(), AudioFileFormat.Type.WAVE);
}
else if (obj.equals(playB)) {
if (playB.getText().startsWith("Play")) {
playback.start();
samplingGraph.start();
captB.setEnabled(false);
pausB.setEnabled(true);
playB.setText("Stop");
}
else {
playback.stop();
samplingGraph.stop();
captB.setEnabled(true);
pausB.setEnabled(false);
playB.setText("Play");
}
}
else if (obj.equals(connB)) {
if (connB.getText().startsWith("斷開所有連接")) {
multiServerListener.clearServer();
//設置人機界面
loadB.setEnabled(false);
playB.setEnabled(false);
pausB.setEnabled(false);
auB.setEnabled(false);
aiffB.setEnabled(false);
waveB.setEnabled(false);
captB.setEnabled(false);
// connB.setText("服務端暫時斷開監聽");
}
else {
connB.setText("???");
// connB.doClick(0);
//fuwuqi---lianjie
try {
multiServerListener.getServer();
}
catch (Exception ex1) {
}
}
}
else if (obj.equals(captB)) {
//kehu---lianjie
if (captB.getText().startsWith("Record")) {
file = null;
//開始一個線程 "Capture"
capture.start();
fileName = "untitled";
//開始一個線程 "SamplingGraph"
// samplingGraph.start(); //call run()
//設置人機界面
loadB.setEnabled(false);
playB.setEnabled(false);
pausB.setEnabled(true);
auB.setEnabled(false);
aiffB.setEnabled(false);
waveB.setEnabled(false);
captB.setText("Stop");
}
else {
//kehu---duankai
lines.removeAllElements();
capture.stop();
samplingGraph.stop();
loadB.setEnabled(true);
playB.setEnabled(true);
pausB.setEnabled(false);
auB.setEnabled(true);
aiffB.setEnabled(true);
waveB.setEnabled(true);
captB.setText("Record");
}
}
else if (obj.equals(pausB)) {
if (pausB.getText().startsWith("Pause")) {
if (capture.thread != null) {
//cease I/O activity ;停止捕獲
capture.line.stop();
}
else {
if (playback.thread != null) {
//cease I/O activity;停止重放
playback.line.stop();
}
}
pausB.setText("Resume");
}
else {
if (capture.thread != null) {
//engage in data I/O
capture.line.start();
}
else {
if (playback.thread != null) {
//engage in data I/O
playback.line.start();
}
}
pausB.setText("Pause");
}
}
else if (obj.equals(loadB)) {
try {
File file = new File(System.getProperty("user.dir"));
JFileChooser fc = new JFileChooser(file);
fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String name = f.getName();
if (name.endsWith(".au") || name.endsWith(".wav") ||
name.endsWith(".aiff") || name.endsWith(".aif")) {
return true;
}
return false;
}
public String getDescription() {
return ".au, .wav, .aif";
}
});
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
//true,表示要更新audioInputStream對象的format;fc就是文件選擇器JFileChooser;
createAudioInputStream(fc.getSelectedFile(), true);
}
}
catch (SecurityException ex) {
// JavaSound.showInfoDialog();
ex.printStackTrace();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
//讀取文件中的聲音到audioInputStream中, createAudioInputStream(file, false);
public void createAudioInputStream(File file, boolean updateComponents) {
if (file != null && file.isFile()) {
try {
this.file = file;
errStr = null;
//操作
audioInputStream = AudioSystem.getAudioInputStream(file);
playB.setEnabled(true);
fileName = file.getName();
long milliseconds = (long) ( (audioInputStream.getFrameLength() * 1000) /
audioInputStream.getFormat().getFrameRate());
duration = milliseconds / 1000.0;
auB.setEnabled(true);
aiffB.setEnabled(true);
waveB.setEnabled(true);
//更新formatControls.setFormat為當前audioInputStream的格式;samplingGraph.createWaveForm
if (updateComponents) {
formatControls.setFormat(audioInputStream.getFormat());
samplingGraph.createWaveForm(null);
}
}
catch (Exception ex) {
reportStatus(ex.toString());
}
}
else {
reportStatus("Audio file required.");
}
}
public void saveToFile(String name, AudioFileFormat.Type fileType) {
if (audioInputStream == null) {
reportStatus("No loaded audio to save");
return;
}
else if (file != null) {
createAudioInputStream(file, false);
}
// 重置audioInputStream對象!reset to the beginnning of the captured data
try {
audioInputStream.reset();
}
catch (Exception e) {
reportStatus("Unable to reset stream " + e);
return;
}
File file = new File(fileName = name);
try {
if (AudioSystem.write(audioInputStream, fileType, file) == -1) {
throw new IOException("Problems writing to file");
}
}
catch (Exception ex) {
reportStatus(ex.toString());
}
samplingGraph.repaint();
}
private void reportStatus(String msg) {
if ( (errStr = msg) != null) {
System.out.println(errStr);
samplingGraph.repaint();
}
}
//fuwuqi
/**
* 內隱類Playback。寫出數據到OutputChannel中,以重放
* createAudioInputStream(file, false);
*/
public class Playback
implements Runnable {
SourceDataLine line;
Thread thread;
public void start() {
errStr = null;
thread = new Thread(this);
thread.setName("Playback");
thread.start();
}
public void stop() {
thread = null;
}
private void shutDown(String message) {
if ( (errStr = message) != null) {
System.err.println(errStr);
samplingGraph.repaint();
}
if (thread != null) {
thread = null;
samplingGraph.stop();
captB.setEnabled(true);
pausB.setEnabled(false);
playB.setText("Play");
}
}
//實現播放線程
public void run() {
// 如果audioInputStream由文件載入,我們將重載播放的文件reload the file if loaded by file
if (file != null) {
createAudioInputStream(file, false); //false表示不用更新audioInputStream的格式
}
// audioInputStream不能為空,make sure we have something to play
if (audioInputStream == null) {
shutDown("No loaded audio to play back");
return;
}
// 復位流媒體,reset to the beginnning of the stream
try {
audioInputStream.reset();
}
catch (Exception e) {
shutDown("Unable to reset the stream\n" + e);
return;
}
//得到期望的格式信息!get an AudioInputStream of the desired format for playback
AudioFormat format = formatControls.getFormat();
// !??!將輸入的流對象audioInputStream,格式化后得到一個標準的流對象playbackInputStream
AudioInputStream playbackInputStream = AudioSystem.getAudioInputStream(
format, audioInputStream);
if (playbackInputStream == null) {
shutDown("Unable to convert stream of format " + audioInputStream +
" to format " + format);
return;
}
// 為我們的line定義需要的屬性;define the required attributes for our line,
// 確定一個兼容的line格式;and make sure a compatible line is supported.
DataLine.Info info = new DataLine.Info(SourceDataLine.class,
format);
//判斷系統是否支持匹配這個Line.Info的line;
if (!AudioSystem.isLineSupported(info)) {
shutDown("Line matching " + info + " not supported.");
return;
}
//從AudioSystem中得到期望的格式line,類型化為SourceDataLine以用于讀??;get and open the source data line for playback.
try {
line = (SourceDataLine) AudioSystem.getLine(info);
//causing the line to acquire any required system resources and become operational
line.open(format, bufSize);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -