下面是封裝好的一個輔助類。用於生成頭部資訊。

package example.audiotest;

 

import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
*
* @author cninjazh
* WavHeader輔助類。用於生成頭部資訊。
* WAV標準,頭部應該是44位元組
*/
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;
/*
* pre-define wave header for 256kbps, 16bit, 16kHz, 1(mono), pcm
* 填入參數,位元速率等等。這裡用的是16位單聲道 16000Hz
* fileLength = 內容的大小(dataSize) + 頭部欄位的大小(不包括前面4位元組的識別字RIFF以及fileLength本身的4位元組)
* avgBytesPerSec = 8bit/16bit、11kHz/16kHz的WAV流進行傳輸(最大流量為16*16=256kbps=32KB/s)
*/
public WaveHeader(int dataSize) {
fileLength = dataSize + (44 - 8);
fmtHdrLeth = 16;
bitsPerSample = 16;
channels = 1;
formatTag = 0x0001;
samplesPerSec = 16000;
blockAlign = (short) (channels * bitsPerSample / 8);
avgBytesPerSec = blockAlign * samplesPerSec;
dataHdrLeth = dataSize;
}

 

public WaveHeader(int dataSize, short bitsPerSample, int samplesPerSec) {
fileLength = dataSize + (44 - 8);
fmtHdrLeth = 16;
this.bitsPerSample = bitsPerSample;
channels = 1;
formatTag = 0x0001;
this.samplesPerSec = samplesPerSec;
blockAlign = (short) (channels * bitsPerSample / 8);
avgBytesPerSec = blockAlign * samplesPerSec;
dataHdrLeth = dataSize;
}

 

public byte[] getHeader() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/*
* ①RIFF WAVE Chunk
==================================
| |所占位元組數| 具體內容 |
==================================
ID | 4 Bytes | 'RIFF' |
----------------------------------
Size | 4 Bytes | |
----------------------------------
Type | 4 Bytes | 'WAVE' |
----------------------------------
*/
WriteChar(bos, fileID);//以RIFF作為標識
WriteInt(bos, fileLength);//size,該size的大小是整個WAVE檔大小減去8個位元組
WriteChar(bos, wavTag);//Type欄位,為"WAVE"表示是Wav檔
/*
* ②Format Chunk
====================================================================
| | 位元組數 | 具體內容 |
====================================================================
ID | 4 Bytes | 'fmt ' |
--------------------------------------------------------------------
Size | 4 Bytes | 數值為16或18,18則最後又附加資訊 |
-------------------------------------------------------------------- ----
FormatTag | 2 Bytes | 編碼方式,一般為0x0001 | |
-------------------------------------------------------------------- |
Channels | 2 Bytes | 聲道數目,1--單聲道;2--雙聲道 | |
-------------------------------------------------------------------- |
SamplesPerSec | 4 Bytes | 採樣頻率 | |
-------------------------------------------------------------------- |
AvgBytesPerSec| 4 Bytes | 每秒所需位元組數 | |===> WAVE_FORMAT
-------------------------------------------------------------------- |
BlockAlign | 2 Bytes | 資料塊對齊單位(每個採樣需要的位元組數) | |
-------------------------------------------------------------------- |
BitsPerSample | 2 Bytes | 每個採樣需要的bit數 | |
-------------------------------------------------------------------- |
| | 2 Bytes | 附加資訊(可選,通過Size來判斷有無) | |
-------------------------------------------------------------------- ----
*/
WriteChar(bos, fmtHdrID);//以"fmt "作為標識
WriteInt(bos, fmtHdrLeth);//一般長度為16個位元組,如果是18個位元組則有附加資訊,寫在最後兩個位元組上
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);
}
}
}
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()