<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          java實現(xiàn)錄音功能

          共 22814字,需瀏覽 46分鐘

           ·

          2021-04-29 17:33

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          76套java從入門到精通實戰(zhàn)課程分享

          前幾次博客中也是用java實現(xiàn)錄音機的各種功能,這次是比先前有了一點優(yōu)化,將錄音的功能單獨提取出來,這個程序的實現(xiàn)用到了編碼器LAME.exe這個的作用是將錄音得到的wav文件編碼成MP3文件,這樣的結(jié)果是容量大大減少,因為LAME編碼器經(jīng)測試在編碼過程中路徑中帶有空格問題未能解決,所以只能找了一個笨的方法,為了將其放到指定的文件夾下(這個文件夾路徑是帶有空格的),所以只能先存放到D盤,然后利用文件操作將其復(fù)制到指定的路徑下,然后再刪除,程序中還用到了圖片,修改了java的圖標(biāo),所以在運行時可將其注釋掉,寫的很爛,相互學(xué)習(xí)哈!

          /*
           * 實現(xiàn)錄音機的功能
           * 1.在原來的基礎(chǔ)上界面更加精簡,字體變大使用戶更加方便
           * 2.在停止錄音后便直接保存為.mp3文件
           * 3.對停止錄音進(jìn)行改進(jìn),將錄音按鈕設(shè)計成類似微信的形式,按下時進(jìn)行錄音,松開即停止錄音并保存即可
           * 4.在錄音的時候在面板上顯示音頻波,表示正在錄音
           */
          package com.liuyun.MyRecord6;
           
          import java.awt.*;
           
          import javax.swing.*;
          import java.awt.event.*;
          import java.io.*;
           
          import javax.sound.sampled.*;
           
          import java.lang.*;
           
          public class MyRecord6 extends JFrame implements MouseListener{
           
           //定義錄音格式
           AudioFormat af = null;
           //定義目標(biāo)數(shù)據(jù)行,可以從中讀取音頻數(shù)據(jù),該 TargetDataLine 接口提供從目標(biāo)數(shù)據(jù)行的緩沖區(qū)讀取所捕獲數(shù)據(jù)的方法。
           TargetDataLine td = null;
           //定義源數(shù)據(jù)行,源數(shù)據(jù)行是可以寫入數(shù)據(jù)的數(shù)據(jù)行。它充當(dāng)其混頻器的源。應(yīng)用程序?qū)⒁纛l字節(jié)寫入源數(shù)據(jù)行,這樣可處理字節(jié)緩沖并將它們傳遞給混頻器。
           SourceDataLine sd = null;
           //定義字節(jié)數(shù)組輸入輸出流
           ByteArrayInputStream bais = null;
           ByteArrayOutputStream baos = null;
           //定義音頻輸入流
           AudioInputStream ais = null;
           //定義停止錄音的標(biāo)志,來控制錄音線程的運行
           Boolean stopflag = false;
           //記錄開始錄音的時間
           long startPlay;
           //設(shè)置一個播放的標(biāo)志
           Boolean playflag;
           //每次保存的最后的文件名
           File tarFile = null;
           //定義音頻波形每次顯示的字節(jié)數(shù)
           int intBytes = 0;
           //定義每次錄音的時候每次提取字節(jié)來畫音頻波
           byte audioDataBuffer[] = null;
           //定義所需要的組件
           JPanel jp1,jp2,jp3;
           JLabel jl1=null;
           JButton captureBtn;
           //設(shè)置畫波形線程的終止的標(biāo)志
           boolean flag = true;
           //定義播放錄音時的一個計數(shù)值
           int cnt;
           //定義播放錄音時一個緩沖數(shù)組
           byte btsPlay[] = null;
           
           int gridx, gridy, gridwidth, gridheight, anchor, fill, ipadx, ipady;
           double weightx, weighty;
           Insets inset;
           GridBagConstraints c;
           
           public static void main(String[] args) {
            
           //創(chuàng)造一個實例
           MyRecord6 mr = new MyRecord6();
            
           }
           //構(gòu)造函數(shù)
           public MyRecord6()
           {
            //組件初始化
            jp1 = new JPanel();
            jp2 = new JPanel();
            jp3 = new JPanel();
           
            //定義jp1的字體
            Font jpFont = new Font("華文新魏",Font.BOLD,40);
            jl1 = new JLabel("請留下您想說的話");
            jl1.setFont(jpFont);
            jl1.setForeground(Color.red);
            jp1.add(jl1);
            //定義按鈕上面的字體
            Font btFont = new Font("華文新魏",Font.BOLD,40);
            captureBtn = new JButton("按住 說話");
            //setForeground可以設(shè)置按鈕上面字體的顏色
            captureBtn.setForeground(Color.RED);
            captureBtn.setFont(btFont);
            //對開始錄音按鈕進(jìn)行鼠標(biāo)監(jiān)聽
            captureBtn.addMouseListener(this);
            
            
            this.add(jp1,BorderLayout.NORTH);
            this.add(jp2,BorderLayout.CENTER);
            this.add(jp3,BorderLayout.SOUTH);
            GridBagLayout gridbag = null;
            jp3.setLayout(gridbag = new GridBagLayout());
            gridx=1;
            gridy=2;
            gridwidth=1;
            gridheight=1;
            weightx=1;
            weighty=1;
            anchor=GridBagConstraints.CENTER;
            fill=GridBagConstraints.HORIZONTAL;
            inset=new Insets(1,1,1,1);
            ipadx=0;
            ipady=30;
            c = new GridBagConstraints(gridx, gridy, gridwidth, gridheight,
              weightx, weighty, anchor, fill, inset, ipadx, ipady);
            gridbag.setConstraints(captureBtn, c);
            jp3.add(captureBtn);
           
            //設(shè)置窗口的屬性
            this.setSize(800,500);
            this.setTitle("錄音機");
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //設(shè)置窗口居中
            this.setLocationRelativeTo(null);
            //將窗口的邊框去掉
            this.setUndecorated(true);
            this.setVisible(true);
            //設(shè)置窗口上的圖標(biāo)
            Image img = this.getToolkit().getImage(getClass().getResource("/image/Recorder.jpg"));
            this.setIconImage(img);
            //設(shè)置窗口在最前端顯示
            this.setAlwaysOnTop(true);
           }
           public void mouseClicked(MouseEvent e) {
            
           }
           public void mousePressed(MouseEvent e) {
            //當(dāng)開始錄音按鈕被按下時就開始錄音
            if(e.getSource().equals(captureBtn))
            {
                   //改變按鈕上面的字的內(nèi)容
                   captureBtn.setText("松開 結(jié)束");
             
                   //調(diào)用錄音的方法
                   capture();
                   
                   //記錄開始錄音的時間
                   startPlay = System.currentTimeMillis();
            }
            
           }
           
           public void mouseReleased(MouseEvent e) {
            //當(dāng)松開錄音按鈕時停止錄音并保存錄音的文件
            if(e.getSource().equals(captureBtn))
            {
             //調(diào)用停止錄音的方法
             stop();
             //當(dāng)松開按鈕后對顯示波形的面板進(jìn)行清空
             jp2.repaint();
             //改變按鈕上面的字的內(nèi)容
             captureBtn.setText("按住 說話");
             //調(diào)用保存錄音的方法
             save();
             //將其放到指定的路徑下
             //定義最終要存放的文件路徑
             String destPath = "D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/";
             copyFile("D:/"+tarFile.getName(), destPath);
             
             System.exit(0);
            }
           }
           
           public void mouseEntered(MouseEvent e) {
            
            
           }
           public void mouseExited(MouseEvent e) {
            
            
           }
           //開始錄音
           public void capture()
           {
            try {
             //af為AudioFormat也就是音頻格式
             af = getAudioFormat();
             DataLine.Info info = new DataLine.Info(TargetDataLine.class,af);
             td = (TargetDataLine)(AudioSystem.getLine(info));
             
             //打開具有指定格式的行,這樣可使行獲得所有所需的系統(tǒng)資源并變得可操作。
             td.open(af);
             //允許某一數(shù)據(jù)行執(zhí)行數(shù)據(jù) I/O
             td.start();
             
             //啟動顯示波形的進(jìn)程
             RecordWave aw = new RecordWave();
             Thread t2 = new Thread(aw);
             t2.start();
             //把顯示波形的進(jìn)程標(biāo)志設(shè)為true
             flag = true;
             
             Record record = new Record();
             Thread t1 = new Thread(record);
             t1.start();
            } catch (Exception ex) {
             ex.printStackTrace();
             return;
            }
           }
           //停止錄音
           public void stop()
           {
            stopflag = true;
            //將畫波形的進(jìn)程終止
            flag = false;
           }
           //保存錄音
           public void save()
           {
            af = getAudioFormat();
                  byte audioData[] = baos.toByteArray();
                  bais = new ByteArrayInputStream(audioData);
                  ais = new AudioInputStream(bais,af, audioData.length / af.getFrameSize());
                  //定義最終保存的文件名
                  File file = null;
                  //寫入文件
                  try { 
                   //以當(dāng)前的時間命名錄音的名字
                   //將錄音的文件存放到F盤下語音文件夾下
                   File filePath = new File("D:/AudioFile");
                   String tarPath = "D:/";
                   if(!filePath.exists())
                   {//如果文件不存在,則創(chuàng)建該目錄
                    filePath.mkdirs();
                   }
                   long time = System.currentTimeMillis();
                   file = new File(filePath+"/"+time+".wav");      
                      AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);
                      //將錄音產(chǎn)生的wav文件轉(zhuǎn)換為容量較小的mp3格式
                      //定義產(chǎn)生后文件名
                      tarFile = new File(tarPath+time+".mp3"); 
                      Runtime run = null;
                      //測試當(dāng)前的路徑
                      
                      try {
              run = Runtime.getRuntime();
              //調(diào)用編碼器來將wav文件轉(zhuǎn)換為mp3文件
                          //把編碼得到的mp3文件先存放到D盤下,然后利用文件拷貝函數(shù)將它放到指定的文件夾下同時將D盤下的文件刪除
              Process p=run.exec(filePath+"/"+"lame -b 16 "+filePath+"/"+file.getName()+" "+tarPath+tarFile.getName()); //16為碼率,可自行修改
              //釋放進(jìn)程
              p.getOutputStream().close();
              p.getInputStream().close();
              p.getErrorStream().close();
              //等待
              p.waitFor();
           
          //    //刪除之前保存的的wav文件
          //    if(file.exists())
          //    {
          //     file.delete();
          //    }
              
          //    //定義最終要存放的文件路徑
          //    String destPath = "D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/";
          //    copyFile(tarPath+tarFile.getName(), destPath);
             } catch (Exception e) {
              e.printStackTrace();
             }finally{
              //最后都要執(zhí)行的語句
              //run調(diào)用lame解碼器最后釋放內(nèi)存
              run.freeMemory();
             }
                      
                  } catch (Exception e) {
                      e.printStackTrace();
                  }finally{
                   //關(guān)閉流
                   try {
                    
                    if(bais != null)
                    {
                     bais.close();
                    } 
                    if(ais != null)
                    {
                     ais.close();  
                    }
             } catch (Exception e) {
              e.printStackTrace();
             }    
                  }
           }
           //文件拷貝方法
           public void copyFile(String srcPath , String destPath)
           {
            File srcFile = new File(srcPath);
            //如果目的文件夾沒有則創(chuàng)建目的文件夾
            (new File(destPath)).mkdirs();
            //在目的文件夾下創(chuàng)建要復(fù)制的文件
            File destFile = new File(destPath+"/"+srcFile.getName());
            if(srcFile.isFile() && srcFile.exists())
            {
             InputStream in = null;
             OutputStream out = null;
             try {
              in = new FileInputStream(srcFile);
              out = new FileOutputStream(destFile);
              //設(shè)置緩沖數(shù)組
              byte[] buff = new byte[1024*5];   
                    int len = 0;   
                    while ((len = in.read(buff)) != -1) 
                    {   
                        out.write(buff, 0, len);   
                    }
          //          //測試該函數(shù)是否執(zhí)行
          //          System.out.println("ok1");
                     
             } catch(Exception e) {
              e.printStackTrace();
             }finally{
              //關(guān)閉流,先開的后關(guān)閉
              try {
               if(out != null)
               {
                out.close(); 
               }
               if(in != null)
               {
                in.close();
               }
              } catch (Exception e) {
               e.printStackTrace();
              }
             }
            }
            //復(fù)制過后刪除源文件夾中的的文件
            if(srcFile.exists())
            {
             srcFile.delete();
            }
           }
           //設(shè)置AudioFormat的參數(shù)
           public AudioFormat getAudioFormat() 
           {
            //下面注釋部分是另外一種音頻格式,兩者都可以
            AudioFormat.Encoding encoding = AudioFormat.Encoding.
                  PCM_SIGNED ;
            float rate = 8000f;
            int sampleSize = 16;
            String signedString = "signed";
            boolean bigEndian = true;
            int channels = 1;
            return new AudioFormat(encoding, rate, sampleSize, channels,
              (sampleSize / 8) * channels, rate, bigEndian);
          //  //采樣率是每秒播放和錄制的樣本數(shù)
          //  float sampleRate = 16000.0F;
          //  // 采樣率8000,11025,16000,22050,44100
          //  //sampleSizeInBits表示每個具有此格式的聲音樣本中的位數(shù)
          //  int sampleSizeInBits = 16;
          //  // 8,16
          //  int channels = 1;
          //  // 單聲道為1,立體聲為2
          //  boolean signed = true;
          //  // true,false
          //  boolean bigEndian = true;
          //  // true,false
          //  return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);
           }
           //錄音類,因為要用到MyRecord類中的變量,所以將其做成內(nèi)部類
           class Record implements Runnable
           {
            //定義存放錄音的字節(jié)數(shù)組,作為緩沖區(qū)
            byte bts[] = new byte[10000];
            //將字節(jié)數(shù)組包裝到流里,最終存入到baos中
            //重寫run函數(shù)
            public void run() { 
             baos = new ByteArrayOutputStream();  
             try {
              stopflag = false;
              while(stopflag != true)
              {
               //當(dāng)停止錄音沒按下時,該線程一直執(zhí)行 
               //從數(shù)據(jù)行的輸入緩沖區(qū)讀取音頻數(shù)據(jù)。
               //要讀取bts.length長度的字節(jié),cnt 是實際讀取的字節(jié)數(shù)
               int cnt = td.read(bts, 0, bts.length);
               if(cnt > 0)
               {
                baos.write(bts, 0, cnt);
               }
               
               //開始從音頻流中讀取字節(jié)數(shù)
               byte copyBts[] = bts;
               bais = new ByteArrayInputStream(copyBts);
               ais = new AudioInputStream(bais, af, copyBts.length/af.getFrameSize());
               try{
                DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, af);
                         sd = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
                         sd.open(af);
                         sd.start();
                         
                         //從音頻流中讀取
                         int Buffer_Size = 10000;
                         audioDataBuffer = new byte[Buffer_Size];
                         int outBytes;
                    
                intBytes = ais.read(audioDataBuffer, 0,audioDataBuffer.length);
                
          //      不寫到混頻器中這樣就不會播放
          //      if (intBytes >= 0) {
          //       outBytes = sd.write(audioDataBuffer, 0,audioDataBuffer.length);
          //      }   
               }catch (Exception e) {
                e.printStackTrace();
               }
              }
             } catch (Exception e) {
              e.printStackTrace();
             }finally{
              try {
               //intBytes = -1;
               //關(guān)閉打開的字節(jié)數(shù)組流
               if(baos != null)
               {
                baos.close();
               } 
              } catch (Exception e) {
               e.printStackTrace();
              }finally{
               //下面這句td.drain()不能要,這樣如果不播放數(shù)據(jù)就阻塞再次錄音會出現(xiàn)其他程序訪問錯誤
               //td.drain();
               td.close();
               //刷新顯示波形的面板
               jp2.repaint();
              }
             }
            }
            
           }
           
           //畫波形的類
           //因為要使用一些主函數(shù)中的數(shù)據(jù),所以做成內(nèi)部類
           class RecordWave extends JPanel implements Runnable
           {
            //用畫筆畫出波形
            public void paint(Graphics g)
            {
             super.paint(g);
             g.fillRect(jp2.getX(),jp2.getY() , 800, 380);
             if( audioDataBuffer != null)
             {
              g.drawLine(jp2.getWidth() / 256, 700, jp2.getWidth() / 256, 700);
              
              for(int i=0; i<audioDataBuffer.length-1; ++i)
              {
               g.setColor(Color.RED);
               g.drawLine(i * jp2.getWidth() / 256, (int)audioDataBuffer[i]+200 , (i + 1)
           
                 * jp2.getWidth() / 256, (int)audioDataBuffer[i+1]+200);
              }
             }
            }
            public void run() 
            {
             //刷新波形
             while(true)
             {
              //System.out.println("ok");
              try {
               synchronized (this) {
                //隔多長時間獲取
                Thread.sleep(300);
               }
              } catch (Exception e) {
           
               e.printStackTrace();
              }
              this.paint(jp2.getGraphics());
              //終止線程
              if(flag == false)
              {
               break;
              }
             }
            } 
           }
            
          }


          ————————————————

          版權(quán)聲明:本文為CSDN博主「jsjliuyun」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

          原文鏈接:

          https://blog.csdn.net/computer_liuyun/article/details/17468555






          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點贊支持下哈 

          瀏覽 117
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费无码毛片一区二区本码视频 | 婷婷爱五月天 | 俺去也在线视频 | 奇米色色网 | 国产精品欧美一级 |