欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java讀取wav文件(波形文件)并繪制波形圖的方法

 更新時(shí)間:2015年06月26日 10:04:20   作者:RobinTang  
這篇文章主要介紹了java讀取wav文件(波形文件)并繪制波形圖的方法,涉及java操作多媒體音頻文件轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下

本文實(shí)例講述了java讀取wav文件(波形文件)并繪制波形圖的方法。分享給大家供大家參考。具體如下:

因?yàn)樽罱胁簧倬W(wǎng)友詢問(wèn)我波形文件讀寫方面的問(wèn)題,出于讓大家更方便以及讓代碼能夠得到更好的改進(jìn),我將這部分(波形文件的讀寫)代碼開源在GitHub上面。

地址為https://github.com/sintrb/WaveAccess/,最新的代碼、例子、文檔都在那上面,我會(huì)在我時(shí)間精力允許的前提下對(duì)該項(xiàng)目進(jìn)行維護(hù),同時(shí)也希望對(duì)這方面有興趣的網(wǎng)友能夠加入到該開源項(xiàng)目上。

以下內(nèi)容基本都過(guò)期了,你可以直接去GitHub上面閱讀、下載該項(xiàng)目。

因項(xiàng)目需要讀取.wav文件(波形文件)并繪制波形圖,因此簡(jiǎn)單的做了這方面的封裝。

其實(shí)主要是對(duì)wav文件讀取的封裝,下面是一個(gè)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); 
  } 
  // 判斷是否創(chuàng)建wav讀取器成功 
  public boolean isSuccess() { 
    return issuccess; 
  } 
  // 獲取每個(gè)采樣的編碼長(zhǎng)度,8bit或者16bit 
  public int getBitPerSample(){ 
    return this.bitspersample; 
  } 
  // 獲取采樣率 
  public long getSampleRate(){ 
    return this.samplerate; 
  } 
  // 獲取聲道個(gè)數(shù),1代表單聲道 2代表立體聲 
  public int getNumChannels(){ 
    return this.numchannels; 
  } 
  // 獲取數(shù)據(jù)長(zhǎng)度,也就是一共采樣多少個(gè) 
  public int getDataLen(){ 
    return this.len; 
  } 
  // 獲取數(shù)據(jù) 
  // 數(shù)據(jù)是一個(gè)二維數(shù)組,[n][m]代表第n個(gè)聲道的第m個(gè)采樣值 
  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; 
  } 
} 

為了繪制波形,因此做了一個(gè)從JPanel教程而來(lái)的波形繪制面板:

// 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; //上一個(gè)坐標(biāo) 
    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; 
      // 下面是個(gè)三點(diǎn)取出并繪制 
      // 實(shí)際中應(yīng)該按照采樣率來(lái)設(shè)置間隔 
      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; 
    } 
  } 
} 

有了這些之后就可以調(diào)用繪制了,簡(jiǎn)單的:

// 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); // 創(chuàng)建一個(gè)繪制波形的面板 
      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 + "不是一個(gè)正常的wav文件"); 
    } 
  } 
} 

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

放上效果圖一張:

希望本文所述對(duì)大家的java程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Java中的Kotlin?內(nèi)部類原理

    Java中的Kotlin?內(nèi)部類原理

    這篇文章主要介紹了Java中的Kotlin?內(nèi)部類原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-06-06
  • Java實(shí)現(xiàn)堆排序(大根堆)的示例代碼

    Java實(shí)現(xiàn)堆排序(大根堆)的示例代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)堆排序(大根堆)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java中使用opencv的問(wèn)題

    Java中使用opencv的問(wèn)題

    這篇文章主要介紹了Java中使用opencv的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Java多線程 ReentrantReadWriteLock原理及實(shí)例詳解

    Java多線程 ReentrantReadWriteLock原理及實(shí)例詳解

    這篇文章主要介紹了Java多線程 ReentrantReadWriteLock原理及實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • JPA中@CreatedDate和@LastModifiedDate的使用方式

    JPA中@CreatedDate和@LastModifiedDate的使用方式

    這篇文章主要介紹了JPA中@CreatedDate和@LastModifiedDate的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 一問(wèn)詳解SpringBoot配置文件優(yōu)先級(jí)

    一問(wèn)詳解SpringBoot配置文件優(yōu)先級(jí)

    在SpringBoot項(xiàng)目當(dāng)中,我們要想配置一個(gè)屬性,可以通過(guò)這三種方式當(dāng)中的任意一種來(lái)配置都可以,那么優(yōu)先級(jí)怎么算,本文主要介紹了一問(wèn)詳解SpringBoot配置文件優(yōu)先級(jí),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • SpringCloud整合Nacos實(shí)現(xiàn)流程詳解

    SpringCloud整合Nacos實(shí)現(xiàn)流程詳解

    這篇文章主要介紹了SpringCloud整合Nacos實(shí)現(xiàn)流程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • springboot配置https訪問(wèn)的方法

    springboot配置https訪問(wèn)的方法

    這篇文章主要介紹了springboot配置https訪問(wèn)的方法,需要的朋友可以參考下
    2018-11-11
  • 高效Java尺寸壓縮技巧,節(jié)省資源成本

    高效Java尺寸壓縮技巧,節(jié)省資源成本

    如果你想了解如何優(yōu)化Java應(yīng)用程序的尺寸,節(jié)省存儲(chǔ)空間并提升性能,那么你來(lái)對(duì)地方了,本指南將教你簡(jiǎn)單實(shí)用的技巧和最佳實(shí)踐,幫助你輕松減小Java應(yīng)用程序的體積,讓你的代碼更高效、更精簡(jiǎn),讓我們一起開始吧,讓Java應(yīng)用程序變得更小巧而強(qiáng)大!
    2023-12-12
  • Java C++題解leetcode1620網(wǎng)絡(luò)信號(hào)最好的坐標(biāo)

    Java C++題解leetcode1620網(wǎng)絡(luò)信號(hào)最好的坐標(biāo)

    這篇文章主要為大家介紹了Java C++題解leetcode1620網(wǎng)絡(luò)信號(hào)最好的坐標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論