文章插圖

文章插圖
前幾次博客中也是用java實現錄音機的各種功能 , 這次是比先前有了一點優化 , 將錄音的功能單獨提取出來 , 這個程序的實現用到了編碼器LAME.exe這個的作用是將錄音得到的wav文件編碼成MP3文件 , 這樣的結果是容量大大減少 , 因為LAME編碼器經測試在編碼過程中路徑中帶有空格問題未能解決 , 所以只能找了一個笨的方法 , 為了將其放到指定的文件夾下(這個文件夾路徑是帶有空格的) , 所以只能先存放到D盤 , 然后利用文件操作將其復制到指定的路徑下 , 然后再刪除 , 程序中還用到了圖片 , 修改了java的圖標 , 所以在運行時可將其注釋掉 , 寫的很爛 , 相互學習哈!
【grid布局方式 gridbagconstraints什么意思】/** 實現錄音機的功能* 1.在原來的基礎上界面更加精簡 , 字體變大使用戶更加方便* 2.在停止錄音后便直接保存為.mp3文件* 3.對停止錄音進行改進 , 將錄音按鈕設計成類似微信的形式 , 按下時進行錄音 , 松開即停止錄音并保存即可* 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;//定義目標數據行,可以從中讀取音頻數據,該 TargetDataLine 接口提供從目標數據行的緩沖區讀取所捕獲數據的方法 。TargetDataLine td = null;//定義源數據行,源數據行是可以寫入數據的數據行 。它充當其混頻器的源 。應用程序將音頻字節寫入源數據行 , 這樣可處理字節緩沖并將它們傳遞給混頻器 。SourceDataLine sd = null;//定義字節數組輸入輸出流ByteArrayInputStream bais = null;ByteArrayOutputStream baos = null;//定義音頻輸入流AudioInputStream ais = null;//定義停止錄音的標志 , 來控制錄音線程的運行Boolean stopflag = false;//記錄開始錄音的時間long startPlay;//設置一個播放的標志Boolean playflag;//每次保存的最后的文件名File tarFile = null;//定義音頻波形每次顯示的字節數int intBytes = 0;//定義每次錄音的時候每次提取字節來畫音頻波byte audioDataBuffer[] = null;//定義所需要的組件JPanel jp1,jp2,jp3;JLabel jl1=null;JButton captureBtn;//設置畫波形線程的終止的標志boolean flag = true;//定義播放錄音時的一個計數值int cnt;//定義播放錄音時一個緩沖數組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) {//創造一個實例MyRecord6 mr = new MyRecord6();}//構造函數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可以設置按鈕上面字體的顏色captureBtn.setForeground(Color.RED);captureBtn.setFont(btFont);//對開始錄音按鈕進行鼠標監聽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);//設置窗口的屬性this.setSize(800,500);this.setTitle(“錄音機”);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置窗口居中this.setLocationRelativeTo(null);//將窗口的邊框去掉this.setUndecorated(true);this.setVisible(true);//設置窗口上的圖標Image img = this.getToolkit().getImage(getClass().getResource(“/image/Recorder.jpg”));this.setIconImage(img);//設置窗口在最前端顯示this.setAlwaysOnTop(true);}public void mouseClicked(MouseEvent e) {}public void mousePressed(MouseEvent e) {//當開始錄音按鈕被按下時就開始錄音if(e.getSource().equals(captureBtn)){//改變按鈕上面的字的內容captureBtn.setText(“松開 結束”);//調用錄音的方法capture();//記錄開始錄音的時間startPlay = System.currentTimeMillis();}}public void mouseReleased(MouseEvent e) {//當松開錄音按鈕時停止錄音并保存錄音的文件if(e.getSource().equals(captureBtn)){//調用停止錄音的方法stop();//當松開按鈕后對顯示波形的面板進行清空jp2.repaint();//改變按鈕上面的字的內容captureBtn.setText(“按住 說話”);//調用保存錄音的方法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));//打開具有指定格式的行 , 這樣可使行獲得所有所需的系統資源并變得可操作 。td.open(af);//允許某一數據行執行數據 I/Otd.start();//啟動顯示波形的進程RecordWave aw = new RecordWave();Thread t2 = new Thread(aw);t2.start();//把顯示波形的進程標志設為trueflag = true;Record record = new Record();Thread t1 = new Thread(record);t1.start();} catch (Exception ex) {ex.printStackTrace();return;}}//停止錄音public void stop(){stopflag = true;//將畫波形的進程終止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 {//以當前的時間命名錄音的名字//將錄音的文件存放到F盤下語音文件夾下File filePath = new File(“D:/AudioFile”);String tarPath = “D:/”;if(!filePath.exists()){//如果文件不存在 , 則創建該目錄filePath.mkdirs();}long time = System.currentTimeMillis();file = new File(filePath+”/”+time+”.wav”);AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);//將錄音產生的wav文件轉換為容量較小的mp3格式//定義產生后文件名tarFile = new File(tarPath+time+”.mp3″);Runtime run = null;//測試當前的路徑try {run = Runtime.getRuntime();//調用編碼器來將wav文件轉換為mp3文件//把編碼得到的mp3文件先存放到D盤下 , 然后利用文件拷貝函數將它放到指定的文件夾下同時將D盤下的文件刪除Process p=run.exec(filePath+”/”+”lame -b 16 “+filePath+”/”+file.getName()+” “+tarPath+tarFile.getName()); //16為碼率 , 可自行修改//釋放進程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{//最后都要執行的語句//run調用lame解碼器最后釋放內存run.freeMemory();}} catch (Exception e) {e.printStackTrace();}finally{//關閉流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);//如果目的文件夾沒有則創建目的文件夾(new File(destPath)).mkdirs();//在目的文件夾下創建要復制的文件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);//設置緩沖數組byte[] buff = new byte[1024*5];int len = 0;while ((len = in.read(buff)) != -1){out.write(buff, 0, len);}// //測試該函數是否執行// System.out.println(“ok1”);} catch(Exception e) {e.printStackTrace();}finally{//關閉流 , 先開的后關閉try {if(out != null){out.close();}if(in != null){in.close();}} catch (Exception e) {e.printStackTrace();}}}//復制過后刪除源文件夾中的的文件if(srcFile.exists()){srcFile.delete();}}//設置AudioFormat的參數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);// //采樣率是每秒播放和錄制的樣本數// float sampleRate = 16000.0F;// // 采樣率8000,11025,16000,22050,44100// //sampleSizeInBits表示每個具有此格式的聲音樣本中的位數// 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類中的變量 , 所以將其做成內部類class Record implements Runnable{//定義存放錄音的字節數組,作為緩沖區byte bts[] = new byte[10000];//將字節數組包裝到流里 , 最終存入到baos中//重寫run函數public void run() {baos = new ByteArrayOutputStream();try {stopflag = false;while(stopflag != true){//當停止錄音沒按下時 , 該線程一直執行//從數據行的輸入緩沖區讀取音頻數據 。//要讀取bts.length長度的字節,cnt 是實際讀取的字節數int cnt = td.read(bts, 0, bts.length);if(cnt > 0){baos.write(bts, 0, cnt);}//開始從音頻流中讀取字節數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;//關閉打開的字節數組流if(baos != null){baos.close();}} catch (Exception e) {e.printStackTrace();}finally{//下面這句td.drain()不能要 , 這樣如果不播放數據就阻塞再次錄音會出現其他程序訪問錯誤//td.drain();td.close();//刷新顯示波形的面板jp2.repaint();}}}}//畫波形的類//因為要使用一些主函數中的數據 , 所以做成內部類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;}}}}}
- 非接觸式ic卡讀取方式 非接觸讀卡器使用方法
- 金融市場的交割方式 按金融交易的交割方式
- 云部署方式有哪三種?有何差異? 云部署模式分為哪幾種
- 中國知網cnki數據庫推薦使用的專門閱讀器 中國知網cnki數據庫提供的檢索方式包括
- 入口設計的布局形式 界面設計布局方式
- vlan間路由有幾種方式 實現vlan間路由有哪些方式?各自是怎樣實現的
- 和女生打招呼的方式用準確了 微信上怎么和女生打招呼
- 男人最喜歡女人撒嬌的4個方式 男人都喜歡這三種撒嬌方式
- js 解析json字符串方式 json串解析三種方法
- DNS查詢的方式有 查看域名的dns
