⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 captureplaybackserver.java

📁 java语言编写的语音聊天室程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
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 + -