wave混音的实现(1)
先看关于wav文件的头信息
下面是封装好的一个辅助类。用于生成头部信息。
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);}}}