程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java讀取wav文件(波形文件)並繪制波形圖的辦法

java讀取wav文件(波形文件)並繪制波形圖的辦法

編輯:關於JAVA

java讀取wav文件(波形文件)並繪制波形圖的辦法。本站提示廣大學習愛好者:(java讀取wav文件(波形文件)並繪制波形圖的辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是java讀取wav文件(波形文件)並繪制波形圖的辦法正文


本文實例講述了java讀取wav文件(波形文件)並繪制波形圖的辦法。分享給年夜家供年夜家參考。詳細以下:

由於比來有很多網友訊問我波形文件讀寫方面的成績,出於讓年夜家更便利和讓代碼可以或許獲得更好的改良,我將這部門(波形文件的讀寫)代碼開源在GitHub下面。

地址為https://github.com/sintrb/WaveAccess/,最新的代碼、例子、文檔都在那下面,我會在我時光精神許可的條件下對該項目停止保護,同時也願望對這方面有興致的網友可以或許參加到該開源項目上。

以下內容根本都過時了,你可以直接去GitHub下面浏覽、下載該項目。

因項目須要讀取.wav文件(波形文件)並繪制波形圖,是以簡略的做了這方面的封裝。

其實重要是對wav文件讀取的封裝,上面是一個wav文件讀取器的封裝:

// filename: WaveFileReader.java 
// RobinTang 
// 2012-08-23 
import java.io.*; 
public class WaveFileReader { 
  private String filename = null; 
  private int[][] data = null; 
  private int len = 0; 
  private String chunkdescriptor = null; 
  static private int lenchunkdescriptor = 4; 
  private long chunksize = 0; 
  static private int lenchunksize = 4; 
  private String waveflag = null; 
  static private int lenwaveflag = 4; 
  private String fmtubchunk = null; 
  static private int lenfmtubchunk = 4; 
  private long subchunk1size = 0; 
  static private int lensubchunk1size = 4; 
  private int audioformat = 0; 
  static private int lenaudioformat = 2; 
  private int numchannels = 0; 
  static private int lennumchannels = 2; 
  private long samplerate = 0; 
  static private int lensamplerate = 2; 
  private long byterate = 0; 
  static private int lenbyterate = 4; 
  private int blockalign = 0; 
  static private int lenblockling = 2; 
  private int bitspersample = 0; 
  static private int lenbitspersample = 2; 
  private String datasubchunk = null; 
  static private int lendatasubchunk = 4; 
  private long subchunk2size = 0; 
  static private int lensubchunk2size = 4; 
  private FileInputStream fis = null; 
  private BufferedInputStream bis = null; 
  private boolean issuccess = false; 
  public WaveFileReader(String filename) { 
    this.initReader(filename); 
  } 
  // 斷定能否創立wav讀取器勝利 
  public boolean isSuccess() { 
    return issuccess; 
  } 
  // 獲得每一個采樣的編碼長度,8bit或許16bit 
  public int getBitPerSample(){ 
    return this.bitspersample; 
  } 
  // 獲得采樣率 
  public long getSampleRate(){ 
    return this.samplerate; 
  } 
  // 獲得聲道個數,1代表單聲道 2代表平面聲 
  public int getNumChannels(){ 
    return this.numchannels; 
  } 
  // 獲得數據長度,也就是一共采樣若干個 
  public int getDataLen(){ 
    return this.len; 
  } 
  // 獲得數據 
  // 數據是一個二維數組,[n][m]代表第n個聲道的第m個采樣值 
  public int[][] getData(){ 
    return this.data; 
  } 
  private void initReader(String filename){ 
    this.filename = filename; 
    try { 
      fis = new FileInputStream(this.filename); 
      bis = new BufferedInputStream(fis); 
      this.chunkdescriptor = readString(lenchunkdescriptor); 
      if(!chunkdescriptor.endsWith("RIFF")) 
        throw new IllegalArgumentException("RIFF miss, " + filename + " is not a wave file."); 
      this.chunksize = readLong(); 
      this.waveflag = readString(lenwaveflag); 
      if(!waveflag.endsWith("WAVE")) 
        throw new IllegalArgumentException("WAVE miss, " + filename + " is not a wave file."); 
      this.fmtubchunk = readString(lenfmtubchunk); 
      if(!fmtubchunk.endsWith("fmt ")) 
        throw new IllegalArgumentException("fmt miss, " + filename + " is not a wave file."); 
      this.subchunk1size = readLong(); 
      this.audioformat = readInt(); 
      this.numchannels = readInt(); 
      this.samplerate = readLong(); 
      this.byterate = readLong(); 
      this.blockalign = readInt(); 
      this.bitspersample = readInt(); 
      this.datasubchunk = readString(lendatasubchunk); 
      if(!datasubchunk.endsWith("data")) 
        throw new IllegalArgumentException("data miss, " + filename + " is not a wave file."); 
      this.subchunk2size = readLong(); 
      this.len = (int)(this.subchunk2size/(this.bitspersample/8)/this.numchannels); 
      this.data = new int[this.numchannels][this.len]; 
       
      for(int i=0; i<this.len; ++i){ 
        for(int n=0; n<this.numchannels; ++n){ 
          if(this.bitspersample == 8){ 
            this.data[n][i] = bis.read(); 
          } 
          else if(this.bitspersample == 16){ 
            this.data[n][i] = this.readInt(); 
          } 
        } 
      } 
      issuccess = true; 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
    finally{ 
      try{ 
      if(bis != null) 
        bis.close(); 
      if(fis != null) 
        fis.close(); 
      } 
      catch(Exception e1){ 
        e1.printStackTrace(); 
      } 
    } 
  } 
  private String readString(int len){ 
    byte[] buf = new byte[len]; 
    try { 
      if(bis.read(buf)!=len) 
        throw new IOException("no more data!!!"); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
    return new String(buf); 
  } 
  private int readInt(){ 
    byte[] buf = new byte[2]; 
    int res = 0; 
    try { 
      if(bis.read(buf)!=2) 
        throw new IOException("no more data!!!"); 
      res = (buf[0]&0x000000FF) | (((int)buf[1])<<8); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
    return res; 
  } 
  private long readLong(){ 
    long res = 0; 
    try { 
      long[] l = new long[4]; 
      for(int i=0; i<4; ++i){ 
        l[i] = bis.read(); 
        if(l[i]==-1){ 
          throw new IOException("no more data!!!"); 
        } 
      } 
      res = l[0] | (l[1]<<8) | (l[2]<<16) | (l[3]<<24); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
    return res; 
  } 
  private byte[] readBytes(int len){ 
    byte[] buf = new byte[len]; 
    try { 
      if(bis.read(buf)!=len) 
        throw new IOException("no more data!!!"); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
    return buf; 
  } 
} 

為了繪制波形,是以做了一個從JPanel教程而來的波形繪制面板:

// filename: DrawPanel.java 
// RobinTang 
// 2012-08-23 
import java.awt.Color; 
import java.awt.Graphics; 
import javax.swing.JPanel; 
@SuppressWarnings("serial") 
public class DrawPanel extends JPanel { 
  private int[] data = null; 
  public DrawPanel(int[] data) { 
    this.data = data; 
  } 
  @Override 
  protected void paintComponent(Graphics g) { 
    int ww = getWidth(); 
    int hh = getHeight(); 
    g.setColor(Color.WHITE); 
    g.fillRect(0, 0, ww, hh); 
    int len = data.length; 
    int step = len/ww; 
    if(step==0) 
      step = 1; 
    int prex = 0, prey = 0; //上一個坐標 
    int x = 0, y = 0; 
    g.setColor(Color.RED); 
    double k = hh/2.0/32768.0; 
    for(int i=0; i<ww; ++i){ 
      x = i; 
      // 上面是個三點掏出並繪制 
      // 現實中應當依照采樣率來設置距離 
      y = hh-(int)(data[i*3]*k+hh/2); 
      System.out.print(y); 
      System.out.print(" "); 
      if(i!=0){ 
        g.drawLine(x, y, prex, prey); 
      } 
      prex = x; 
      prey = y; 
    } 
  } 
} 

有了這些以後便可以挪用繪制了,簡略的:

// WaveFileReadDemo.java 
// RobinTang 
// 2012-08-23 
import javax.swing.JFrame; 
public class WaveFileReadDemo { 
  /** 
   * @param args 
   */ 
  public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    String filename = "file.wav"; 
    JFrame frame = new JFrame(); 
    WaveFileReader reader = new WaveFileReader(filename); 
    if(reader.isSuccess()){ 
      int[] data = reader.getData()[0]; //獲得第一聲道 
      DrawPanel drawPanel = new DrawPanel(data); // 創立一個繪制波形的面板 
      frame.add(drawPanel); 
      frame.setTitle(filename); 
      frame.setSize(800, 400); 
      frame.setLocationRelativeTo(null); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setVisible(true); 
    } 
    else{ 
      System.err.println(filename + "不是一個正常的wav文件"); 
    } 
  } 
} 

工程的源代碼可以在我的百度網盤上找到,直接到開源JAVA

放上後果圖一張:

願望本文所述對年夜家的java法式設計有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved