PCM到WAV的轉換(Java)__java

來源:互聯網
上載者:User

公司的另一個產品,監控CTI的時候錄音的格式是PCM.
為了能在IE裡面播放, 需要轉換成標準的WAV. 以前用的是一個COM庫來做轉換, 現在因為各種原因不能用那個庫了(64位支援不好等等),就用Java實現了一個。基本代碼如下。
其實WAV只是PCM檔案加上相關的檔案頭和描述資訊,不算複雜。這段程式參考了網上的一些實現(C/C++),修改了其中的一些錯誤,比如轉換後的檔案能夠播放但是時間長度是錯誤的;或者不能拖動等等。

代碼見下。

private void convertAudioFiles(String src, String target) throws Exception {
   FileInputStream fis = new FileInputStream(src);
   FileOutputStream fos = new FileOutputStream(target);

   //計算長度
   byte[] buf = new byte[1024 * 4];
   int size = fis.read(buf);
   int PCMSize = 0;
   while (size != -1) {
      PCMSize += size;
      size = fis.read(buf);
    }
   fis.close();


   //填入參數,位元速率等等。這裡用的是16位單聲道 8000 hz
   WaveHeader header = new WaveHeader();
   //長度欄位 = 內容的大小(PCMSize) + 頭部欄位的大小(不包括前面4位元組的標識符RIFF以及fileLength本身的4位元組)
   header.fileLength = PCMSize + (44 - 8);
   header.FmtHdrLeth = 16;
   header.BitsPerSample = 16;
   header.Channels = 1;
   header.FormatTag = 0x0001;
   header.SamplesPerSec = 8000;
   header.BlockAlign = (short)(header.Channels * header.BitsPerSample / 8);
   header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
   header.DataHdrLeth = PCMSize;

   byte[] h = header.getHeader();

   assert h.length == 44; //WAV標準,頭部應該是44位元組
   //write header
   fos.write(h, 0, h.length);
   //write data stream
   fis = new FileInputStream(src);
   size = fis.read(buf);
   while (size != -1) {
      fos.write(buf, 0, size);
      size = fis.read(buf);
   }
   fis.close();
   fos.close();
   System.out.println("Convert OK!");
}

WavHeader輔助類。用於產生頭部資訊。

public class WaveHeader {
   public final char fileID[] = {'R', 'I', 'F', 'F'};
   public int fileLength;
   public char wavTag[] = {'W', 'A', 'V', 'E'};;
   public char FmtHdrID[] = {'f', 'm', 't', ' '};
   public int FmtHdrLeth;
   public short FormatTag;
   public short Channels;
   public int SamplesPerSec;
   public int AvgBytesPerSec;
   public short BlockAlign;
   public short BitsPerSample;
   public char DataHdrID[] = {'d','a','t','a'};
   public int DataHdrLeth;

public byte[] getHeader() throws IOException {
   ByteArrayOutputStream bos = new ByteArrayOutputStream();
   WriteChar(bos, fileID);
   WriteInt(bos, fileLength);
   WriteChar(bos, wavTag);
   WriteChar(bos, FmtHdrID);
   WriteInt(bos,FmtHdrLeth);
   WriteShort(bos,FormatTag);
   WriteShort(bos,Channels);
   WriteInt(bos,SamplesPerSec);
   WriteInt(bos,AvgBytesPerSec);
   WriteShort(bos,BlockAlign);
   WriteShort(bos,BitsPerSample);
   WriteChar(bos,DataHdrID);
   WriteInt(bos,DataHdrLeth);
   bos.flush();
   byte[] r = bos.toByteArray();
   bos.close();
   return r;
}

private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException {
   byte[] mybyte = new byte[2];
   mybyte[1] =(byte)( (s << 16) >> 24 );
   mybyte[0] =(byte)( (s << 24) >> 24 );
   bos.write(mybyte);
}


private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException {
   byte[] buf = new byte[4];
   buf[3] =(byte)( n >> 24 );
   buf[2] =(byte)( (n << 8) >> 24 );
   buf[1] =(byte)( (n << 16) >> 24 );
   buf[0] =(byte)( (n << 24) >> 24 );
   bos.write(buf);
}

private void WriteChar(ByteArrayOutputStream bos, char[] id) {
   for (int i=0; i<id.length; i++) {
      char c = id[i];
      bos.write(c);
   }
}
}


來源:http://hi.baidu.com/lff0305/blog/item/7d8ba938246f22cfd5622596.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.