> 文章列表 > Android flac to wav

Android flac to wav

Android flac to wav

Android flac to wav

flac格式的音频属于“无损压缩”,对于我们最常说的“无损音频”来说,一般都是指传统CD格式中的16bit/44.1kHz采样率的文件格式,而知所以称为无损压缩,也是因为其包含了20Hz-22.05kHz这个完全覆盖人耳可闻范围的频响频率而得名。

简介

FLAC即是FreeLossless Audio Codec的缩写,全称应该叫OGGFLAC,中文可解为无损音频压缩编码。它是OGG计划的一部分,当然也就是开源、免费的了,这也难怪它这么快就得到了多家MP3厂商的支持。

FLAC是一套著名的自由音频压缩编码,其特点是无损压缩。FLAC压缩比可以达到2:1,对于无损压缩来说,这已经是相当高的比例了;而且它解码速度快,只需进行整数运算即可完成整个解码过程,对CPU的运算能力要求很低,所以普通的随身听,都可以轻松实现实时解码。

不同于其他有损压缩编码如MP3 及AAC,它不会破坏任何原有的音频资讯,所以可以还原音乐光盘音质。现在它已被很多软件及硬件音频产品所支持。简而言之,FLAC与MP3相仿,但是是无损压缩的,也就是说音频以FLAC方式压缩不会丢失任何信息。这种压缩与Zip的方式类似,但是FLAC将给你更大的压缩比率,因为

FLAC是专门针对音频的特点设计的压缩方式,并且你可以使用播放器播放FLAC压缩的文件,就象通常播放你的MP3文件一样。

补充:为无损格式,较ape而言,他体积大点,但是兼容性好,编码速度快,播放器支持更广

flac与mp3的区别

音质不同:flac不会破坏任何原有的音频信息,可以还原音乐光盘音质。mp3旨在大大减少音频数据量,利用mpeg音频第三层技术,将音乐压缩成1:10甚至1:12的小文件。压缩比不同:flac是一种专为pcm音频特性而设计的压缩模式,可以使用播放器直接播放FLAC压缩的文件。mp3其优点是压缩后占用空间小,适用于移动设备的存储和使用。

1、音质不同:flac不会破坏任何原有的音频信息,可以还原音乐光盘音质。mp3旨在大大减少音频数据量,利用mpeg音频第三层技术,将音乐压缩成1:10甚至1:12的小文件。

2、音频不同:flac音频以FLAC编码压缩后不会丢失任何信息,将FLAC文件还原为WAV文件后,与压缩前的WAV文件内容相同。mp3利用人耳对高频声音信号不敏感的特性,将时域波形信号转换成频域信号,并划分成多个频段,对不同的频段使用不同的压缩率,对高频加大压缩比对低频信号使用小压缩比,保证信号不失真。

3、压缩比不同:flac是一种专为pcm音频特性而设计的压缩模式,可以使用播放器直接播放FLAC压缩的文件。mp3其优点是压缩后占用空间小,适用于移动设备的存储和使用。

使用FLAC-library-Java库来实现 flac与wav互转。

1.flac to wav
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.zip.DataFormatException;public final class SimpleDecodeFlacToWav {public static void main(String[] args) throws IOException, DataFormatException {if (args.length != 2) {System.err.println("Usage: java SimpleDecodeFlacToWav InFile.flac OutFile.wav");System.exit(1);return;}try (BitInputStream in = new BitInputStream(new BufferedInputStream(new FileInputStream(args[0])));OutputStream out = new BufferedOutputStream(new FileOutputStream(args[1]))) {decodeFile(in, out);}}public static void decodeFile(BitInputStream in, OutputStream out) throws IOException, DataFormatException {// Handle FLAC header and metadata blocksif (in.readUint(32) != 0x664C6143)throw new DataFormatException("Invalid magic string");int sampleRate = -1;int numChannels = -1;int sampleDepth = -1;long numSamples = -1;for (boolean last = false; !last; ) {last = in.readUint(1) != 0;int type = in.readUint(7);int length = in.readUint(24);if (type == 0) {  // Stream info blockin.readUint(16);in.readUint(16);in.readUint(24);in.readUint(24);sampleRate = in.readUint(20);numChannels = in.readUint(3) + 1;sampleDepth = in.readUint(5) + 1;numSamples = (long)in.readUint(18) << 18 | in.readUint(18);for (int i = 0; i < 16; i++)in.readUint(8);} else {for (int i = 0; i < length; i++)in.readUint(8);}}if (sampleRate == -1)throw new DataFormatException("Stream info metadata block absent");if (sampleDepth % 8 != 0)throw new RuntimeException("Sample depth not supported");// Start writing WAV file headerslong sampleDataLen = numSamples * numChannels * (sampleDepth / 8);writeString("RIFF", out);writeLittleInt(4, (int)sampleDataLen + 36, out);writeString("WAVE", out);writeString("fmt ", out);writeLittleInt(4, 16, out);writeLittleInt(2, 0x0001, out);writeLittleInt(2, numChannels, out);writeLittleInt(4, sampleRate, out);writeLittleInt(4, sampleRate * numChannels * (sampleDepth / 8), out);writeLittleInt(2, numChannels * (sampleDepth / 8), out);writeLittleInt(2, sampleDepth, out);writeString("data", out);writeLittleInt(4, (int)sampleDataLen, out);// Decode FLAC audio frames and write raw sampleswhile (decodeFrame(in, numChannels, sampleDepth, out));}private static void writeLittleInt(int numBytes, int val, OutputStream out) throws IOException {for (int i = 0; i < numBytes; i++)out.write(val >>> (i * 8));}private static void writeString(String s, OutputStream out) throws IOException {out.write(s.getBytes(StandardCharsets.UTF_8));}private static boolean decodeFrame(BitInputStream in, int numChannels, int sampleDepth, OutputStream out)throws IOException, DataFormatException {// Read a ton of header fields, and ignore most of themint temp = in.readByte();if (temp == -1)return false;int sync = temp << 6 | in.readUint(6);if (sync != 0x3FFE)throw new DataFormatException("Sync code expected");in.readUint(1);in.readUint(1);int blockSizeCode = in.readUint(4);int sampleRateCode = in.readUint(4);int chanAsgn = in.readUint(4);in.readUint(3);in.readUint(1);temp = Integer.numberOfLeadingZeros(~(in.readUint(8) << 24)) - 1;for (int i = 0; i < temp; i++)in.readUint(8);int blockSize;if (blockSizeCode == 1)blockSize = 192;else if (2 <= blockSizeCode && blockSizeCode <= 5)blockSize = 576 << (blockSizeCode - 2);else if (blockSizeCode == 6)blockSize = in.readUint(8) + 1;else if (blockSizeCode == 7)blockSize = in.readUint(16) + 1;else if (8 <= blockSizeCode && blockSizeCode <= 15)blockSize = 256 << (blockSizeCode - 8);elsethrow new DataFormatException("Reserved block size");if (sampleRateCode == 12)in.readUint(8);else if (sampleRateCode == 13 || sampleRateCode == 14)in.readUint(16);in.readUint(8);// Decode each channel's subframe, then skip footerint[][] samples = new int[numChannels][blockSize];decodeSubframes(in, sampleDepth, chanAsgn, samples);in.alignToByte();in.readUint(16);// Write the decoded samplesfor (int i = 0; i < blockSize; i++) {for (int j = 0; j < numChannels; j++) {int val = samples[j][i];if (sampleDepth == 8)val += 128;writeLittleInt(sampleDepth / 8, val, out);}}return true;}private static void decodeSubframes(BitInputStream in, int sampleDepth, int chanAsgn, int[][] result)throws IOException, DataFormatException {int blockSize = result[0].length;long[][] subframes = new long[result.length][blockSize];if (0 <= chanAsgn && chanAsgn <= 7) {for (int ch = 0; ch < result.length; ch++)decodeSubframe(in, sampleDepth, subframes[ch]);} else if (8 <= chanAsgn && chanAsgn <= 10) {decodeSubframe(in, sampleDepth + (chanAsgn == 9 ? 1 : 0), subframes[0]);decodeSubframe(in, sampleDepth + (chanAsgn == 9 ? 0 : 1), subframes[1]);if (chanAsgn == 8) {for (int i = 0; i < blockSize; i++)subframes[1][i] = subframes[0][i] - subframes[1][i];} else if (chanAsgn == 9) {for (int i = 0; i < blockSize; i++)subframes[0][i] += subframes[1][i];} else if (chanAsgn == 10) {for (int i = 0; i < blockSize; i++) {long side = subframes[1][i];long right = subframes[0][i] - (side >> 1);subframes[1][i] = right;subframes[0][i] = right + side;}}} elsethrow new DataFormatException("Reserved channel assignment");for (int ch = 0; ch < result.length; ch++) {for (int i = 0; i < blockSize; i++)result[ch][i] = (int)subframes[ch][i];}}private static void decodeSubframe(BitInputStream in, int sampleDepth, long[] result)throws IOException, DataFormatException {in.readUint(1);int type = in.readUint(6);int shift = in.readUint(1);if (shift == 1) {while (in.readUint(1) == 0)shift++;}sampleDepth -= shift;if (type == 0)  // Constant codingArrays.fill(result, 0, result.length, in.readSignedInt(sampleDepth));else if (type == 1) {  // Verbatim codingfor (int i = 0; i < result.length; i++)result[i] = in.readSignedInt(sampleDepth);} else if (8 <= type && type <= 12)decodeFixedPredictionSubframe(in, type - 8, sampleDepth, result);else if (32 <= type && type <= 63)decodeLinearPredictiveCodingSubframe(in, type - 31, sampleDepth, result);elsethrow new DataFormatException("Reserved subframe type");for (int i = 0; i < result.length; i++)result[i] <<= shift;}private static void decodeFixedPredictionSubframe(BitInputStream in, int predOrder, int sampleDepth, long[] result)throws IOException, DataFormatException {for (int i = 0; i < predOrder; i++)result[i] = in.readSignedInt(sampleDepth);decodeResiduals(in, predOrder, result);restoreLinearPrediction(result, FIXED_PREDICTION_COEFFICIENTS[predOrder], 0);}private static final int[][] FIXED_PREDICTION_COEFFICIENTS = {{},{1},{2, -1},{3, -3, 1},{4, -6, 4, -1},};private static void decodeLinearPredictiveCodingSubframe(BitInputStream in, int lpcOrder, int sampleDepth, long[] result)throws IOException, DataFormatException {for (int i = 0; i < lpcOrder; i++)result[i] = in.readSignedInt(sampleDepth);int precision = in.readUint(4) + 1;int shift = in.readSignedInt(5);int[] coefs = new int[lpcOrder];for (int i = 0; i < coefs.length; i++)coefs[i] = in.readSignedInt(precision);decodeResiduals(in, lpcOrder, result);restoreLinearPrediction(result, coefs, shift);}private static void decodeResiduals(BitInputStream in, int warmup, long[] result) throws IOException, DataFormatException {int method = in.readUint(2);if (method >= 2)throw new DataFormatException("Reserved residual coding method");int paramBits = method == 0 ? 4 : 5;int escapeParam = method == 0 ? 0xF : 0x1F;int partitionOrder = in.readUint(4);int numPartitions = 1 << partitionOrder;if (result.length % numPartitions != 0)throw new DataFormatException("Block size not divisible by number of Rice partitions");int partitionSize = result.length / numPartitions;for (int i = 0; i < numPartitions; i++) {int start = i * partitionSize + (i == 0 ? warmup : 0);int end = (i + 1) * partitionSize;int param = in.readUint(paramBits);if (param < escapeParam) {for (int j = start; j < end; j++)result[j] = in.readRiceSignedInt(param);} else {int numBits = in.readUint(5);for (int j = start; j < end; j++)result[j] = in.readSignedInt(numBits);}}}private static void restoreLinearPrediction(long[] result, int[] coefs, int shift) {for (int i = coefs.length; i < result.length; i++) {long sum = 0;for (int j = 0; j < coefs.length; j++)sum += result[i - 1 - j] * coefs[j];result[i] += sum >> shift;}}}final class BitInputStream implements AutoCloseable {private InputStream in;private long bitBuffer;private int bitBufferLen;public BitInputStream(InputStream in) {this.in = in;}public void alignToByte() {bitBufferLen -= bitBufferLen % 8;}public int readByte() throws IOException {if (bitBufferLen >= 8)return readUint(8);elsereturn in.read();}public int readUint(int n) throws IOException {while (bitBufferLen < n) {int temp = in.read();if (temp == -1)throw new EOFException();bitBuffer = (bitBuffer << 8) | temp;bitBufferLen += 8;}bitBufferLen -= n;int result = (int)(bitBuffer >>> bitBufferLen);if (n < 32)result &= (1 << n) - 1;return result;}public int readSignedInt(int n) throws IOException {return (readUint(n) << (32 - n)) >> (32 - n);}public long readRiceSignedInt(int param) throws IOException {long val = 0;while (readUint(1) == 0)val++;val = (val << param) | readUint(param);return (val >>> 1) ^ -(val & 1);}public void close() throws IOException {in.close();}}
2. wav to flac
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.zip.DataFormatException;public final class SimpleEncodeWavToFlac {public static void main(String[] args) throws IOException, DataFormatException {if (args.length != 2) {System.err.println("Usage: java SimpleEncodeWavToFlac InFile.wav OutFile.flac");System.exit(1);return;}try (InputStream in = new BufferedInputStream(new FileInputStream(args[0]));BitOutputStream out = new BitOutputStream(new BufferedOutputStream(new FileOutputStream(args[1])))) {encodeFile(in, out);}}public static void encodeFile(InputStream in, BitOutputStream out) throws IOException, DataFormatException {// Read and parse WAV file headersif (!readString(in, 4).equals("RIFF"))throw new DataFormatException("Invalid RIFF file header");readLittleInt(in, 4);if (!readString(in, 4).equals("WAVE"))throw new DataFormatException("Invalid WAV file header");if (!readString(in, 4).equals("fmt "))throw new DataFormatException("Unrecognized WAV file chunk");if (readLittleInt(in, 4) != 16)throw new DataFormatException("Unsupported WAV file type");if (readLittleInt(in, 2) != 0x0001)throw new DataFormatException("Unsupported WAV file codec");int numChannels = readLittleInt(in, 2);if (numChannels < 0 || numChannels > 8)throw new RuntimeException("Too many (or few) audio channels");int sampleRate = readLittleInt(in, 4);if (sampleRate <= 0 || sampleRate >= (1 << 20))throw new RuntimeException("Sample rate too large or invalid");readLittleInt(in, 4);readLittleInt(in, 2);int sampleDepth = readLittleInt(in, 2);if (sampleDepth == 0 || sampleDepth > 32 || sampleDepth % 8 != 0)throw new RuntimeException("Unsupported sample depth");if (!readString(in, 4).equals("data"))throw new DataFormatException("Unrecognized WAV file chunk");int sampleDataLen = readLittleInt(in, 4);if (sampleDataLen <= 0 || sampleDataLen % (numChannels * (sampleDepth / 8)) != 0)throw new DataFormatException("Invalid length of audio sample data");// Start writing FLAC file header and stream info metadata blockout.writeInt(32, 0x664C6143);out.writeInt(1, 1);out.writeInt(7, 0);out.writeInt(24, 34);out.writeInt(16, BLOCK_SIZE);out.writeInt(16, BLOCK_SIZE);out.writeInt(24, 0);out.writeInt(24, 0);out.writeInt(20, sampleRate);out.writeInt(3, numChannels - 1);out.writeInt(5, sampleDepth - 1);int numSamples = sampleDataLen / (numChannels * (sampleDepth / 8));out.writeInt(18, numSamples >>> 18);out.writeInt(18, numSamples >>>  0);for (int i = 0; i < 16; i++)out.writeInt(8, 0);// Read raw samples and encode FLAC audio framesfor (int i = 0; numSamples > 0; i++) {int blockSize = Math.min(numSamples, BLOCK_SIZE);encodeFrame(in, i, numChannels, sampleDepth, sampleRate, blockSize, out);numSamples -= blockSize;}}private static final int BLOCK_SIZE = 4096;private static String readString(InputStream in, int len) throws IOException {byte[] temp = new byte[len];for (int i = 0; i < temp.length; i++) {int b = in.read();if (b == -1)throw new EOFException();temp[i] = (byte)b;}return new String(temp, StandardCharsets.UTF_8);}private static int readLittleInt(InputStream in, int n) throws IOException {int result = 0;for (int i = 0; i < n; i++) {int b = in.read();if (b == -1)throw new EOFException();result |= b << (i * 8);}return result;}private static void encodeFrame(InputStream in, int frameIndex, int numChannels, int sampleDepth, int sampleRate, int blockSize, BitOutputStream out) throws IOException {int[][] samples = new int[numChannels][blockSize];int bytesPerSample = sampleDepth / 8;for (int i = 0; i < blockSize; i++) {for (int ch = 0; ch < numChannels; ch++) {int val = 0;for (int j = 0; j < bytesPerSample; j++) {int b = in.read();if (b == -1)throw new EOFException();val |= b << (j * 8);}if (sampleDepth == 8)samples[ch][i] = val - 128;elsesamples[ch][i] = (val << (32 - sampleDepth)) >> (32 - sampleDepth);}}out.resetCrcs();out.writeInt(14, 0x3FFE);out.writeInt(1, 0);out.writeInt(1, 0);out.writeInt(4, 7);out.writeInt(4, sampleRate % 10 == 0 ? 14 : 13);out.writeInt(4, numChannels - 1);switch (sampleDepth) {case  8:  out.writeInt(3, 1);  break;case 16:  out.writeInt(3, 4);  break;case 24:  out.writeInt(3, 6);  break;case 32:  out.writeInt(3, 0);  break;default:  throw new IllegalArgumentException();}out.writeInt(1, 0);out.writeInt(8, 0xFC | (frameIndex >>> 30));for (int i = 24; i >= 0; i -= 6)out.writeInt(8, 0x80 | ((frameIndex >>> i) & 0x3F));out.writeInt(16, blockSize - 1);out.writeInt(16, sampleRate / (sampleRate % 10 == 0 ? 10 : 1));out.writeInt(8, out.crc8);for (int[] chanSamples : samples)encodeSubframe(chanSamples, sampleDepth, out);out.alignToByte();out.writeInt(16, out.crc16);}private static void encodeSubframe(int[] samples, int sampleDepth, BitOutputStream out) throws IOException {out.writeInt(1, 0);out.writeInt(6, 1);  // Verbatim codingout.writeInt(1, 0);for (int x : samples)out.writeInt(sampleDepth, x);}}final class BitOutputStream implements AutoCloseable {private OutputStream out;private long bitBuffer;private int bitBufferLen;public int crc8;public int crc16;public BitOutputStream(OutputStream out) {this.out = out;bitBuffer = 0;bitBufferLen = 0;resetCrcs();}public void resetCrcs() {crc8 = 0;crc16 = 0;}public void alignToByte() throws IOException {writeInt((64 - bitBufferLen) % 8, 0);}public void writeInt(int n, int val) throws IOException {bitBuffer = (bitBuffer << n) | (val & ((1L << n) - 1));bitBufferLen += n;while (bitBufferLen >= 8) {bitBufferLen -= 8;int b = (int)(bitBuffer >>> bitBufferLen) & 0xFF;out.write(b);crc8 ^= b;crc16 ^= b << 8;for (int i = 0; i < 8; i++) {crc8 = (crc8 << 1) ^ ((crc8 >>> 7) * 0x107);crc16 = (crc16 << 1) ^ ((crc16 >>> 15) * 0x18005);}}}public void close() throws IOException {out.close();}}
3.wav 2 flac
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.zip.DataFormatException;public final class DecodeFlacResidueToWav {public static void main(String[] args) throws IOException, DataFormatException {if (args.length != 2) {System.err.println("Usage: java DecodeFlacResidueToWav InFile.flac OutFile.wav");System.exit(1);return;}try (BitInputStream in = new BitInputStream(new BufferedInputStream(new FileInputStream(args[0])));OutputStream out = new BufferedOutputStream(new FileOutputStream(args[1]))) {decodeFile(in, out);}}public static void decodeFile(BitInputStream in, OutputStream out) throws IOException, DataFormatException {// Handle FLAC header and metadata blocksif (in.readUint(32) != 0x664C6143)throw new DataFormatException("Invalid magic string");int sampleRate = -1;int numChannels = -1;int sampleDepth = -1;long numSamples = -1;for (boolean last = false; !last; ) {last = in.readUint(1) != 0;int type = in.readUint(7);int length = in.readUint(24);if (type == 0) {  // Stream info blockin.readUint(16);in.readUint(16);in.readUint(24);in.readUint(24);sampleRate = in.readUint(20);numChannels = in.readUint(3) + 1;sampleDepth = in.readUint(5) + 1;numSamples = (long)in.readUint(18) << 18 | in.readUint(18);for (int i = 0; i < 16; i++)in.readUint(8);} else {for (int i = 0; i < length; i++)in.readUint(8);}}if (sampleRate == -1)throw new DataFormatException("Stream info metadata block absent");if (sampleDepth % 8 != 0)throw new RuntimeException("Sample depth not supported");// Start writing WAV file headerslong sampleDataLen = numSamples * numChannels * (sampleDepth / 8);writeString("RIFF", out);writeLittleInt(4, (int)sampleDataLen + 36, out);writeString("WAVE", out);writeString("fmt ", out);writeLittleInt(4, 16, out);writeLittleInt(2, 0x0001, out);writeLittleInt(2, numChannels, out);writeLittleInt(4, sampleRate, out);writeLittleInt(4, sampleRate * numChannels * (sampleDepth / 8), out);writeLittleInt(2, numChannels * (sampleDepth / 8), out);writeLittleInt(2, sampleDepth, out);writeString("data", out);writeLittleInt(4, (int)sampleDataLen, out);// Decode FLAC audio frames and write raw sampleswhile (decodeFrame(in, numChannels, sampleDepth, out));}private static void writeLittleInt(int numBytes, int val, OutputStream out) throws IOException {for (int i = 0; i < numBytes; i++)out.write(val >>> (i * 8));}private static void writeString(String s, OutputStream out) throws IOException {out.write(s.getBytes(StandardCharsets.UTF_8));}private static boolean decodeFrame(BitInputStream in, int numChannels, int sampleDepth, OutputStream out) throws IOException, DataFormatException {// Read a ton of header fields, and ignore most of themint temp = in.readByte();if (temp == -1)return false;int sync = temp << 6 | in.readUint(6);if (sync != 0x3FFE)throw new DataFormatException("Sync code expected");in.readUint(1);in.readUint(1);int blockSizeCode = in.readUint(4);int sampleRateCode = in.readUint(4);int chanAsgn = in.readUint(4);in.readUint(3);in.readUint(1);temp = Integer.numberOfLeadingZeros(~(in.readUint(8) << 24)) - 1;for (int i = 0; i < temp; i++)in.readUint(8);int blockSize;if (blockSizeCode == 1)blockSize = 192;else if (2 <= blockSizeCode && blockSizeCode <= 5)blockSize = 576 << (blockSizeCode - 2);else if (blockSizeCode == 6)blockSize = in.readUint(8) + 1;else if (blockSizeCode == 7)blockSize = in.readUint(16) + 1;else if (8 <= blockSizeCode && blockSizeCode <= 15)blockSize = 256 << (blockSizeCode - 8);elsethrow new DataFormatException("Reserved block size");if (sampleRateCode == 12)in.readUint(8);else if (sampleRateCode == 13 || sampleRateCode == 14)in.readUint(16);in.readUint(8);// Decode each channel's subframe, then skip footerint[][] samples = new int[numChannels][blockSize];decodeSubframes(in, sampleDepth, chanAsgn, samples);in.alignToByte();in.readUint(16);// Write the decoded samplesfor (int i = 0; i < blockSize; i++) {for (int j = 0; j < numChannels; j++) {int val = samples[j][i];if (sampleDepth == 8)val += 128;writeLittleInt(sampleDepth / 8, val, out);}}return true;}private static void decodeSubframes(BitInputStream in, int sampleDepth, int chanAsgn, int[][] result) throws IOException, DataFormatException {int blockSize = result[0].length;long[][] subframes = new long[result.length][blockSize];if (0 <= chanAsgn && chanAsgn <= 7) {for (int ch = 0; ch < result.length; ch++)decodeSubframe(in, sampleDepth, subframes[ch]);} else if (8 <= chanAsgn && chanAsgn <= 10) {decodeSubframe(in, sampleDepth + (chanAsgn == 9 ? 1 : 0), subframes[0]);decodeSubframe(in, sampleDepth + (chanAsgn == 9 ? 0 : 1), subframes[1]);} elsethrow new DataFormatException("Reserved channel assignment");for (int ch = 0; ch < result.length; ch++) {for (int i = 0; i < blockSize; i++)result[ch][i] = (int)subframes[ch][i];}}private static void decodeSubframe(BitInputStream in, int sampleDepth, long[] result) throws IOException, DataFormatException {in.readUint(1);int type = in.readUint(6);int shift = in.readUint(1);if (shift == 1) {while (in.readUint(1) == 0)shift++;}sampleDepth -= shift;if (type == 0)  // Constant codingin.readSignedInt(sampleDepth);else if (type == 1) {  // Verbatim codingfor (int i = 0; i < result.length; i++)in.readSignedInt(sampleDepth);} else if (8 <= type && type <= 12)decodeFixedPredictionSubframe(in, type - 8, sampleDepth, result);else if (32 <= type && type <= 63)decodeLinearPredictiveCodingSubframe(in, type - 31, sampleDepth, result);elsethrow new DataFormatException("Reserved subframe type");for (int i = 0; i < result.length; i++)result[i] <<= shift;}private static void decodeFixedPredictionSubframe(BitInputStream in, int predOrder, int sampleDepth, long[] result) throws IOException, DataFormatException {for (int i = 0; i < predOrder; i++)in.readSignedInt(sampleDepth);decodeResiduals(in, predOrder, result);}private static void decodeLinearPredictiveCodingSubframe(BitInputStream in, int lpcOrder, int sampleDepth, long[] result) throws IOException, DataFormatException {for (int i = 0; i < lpcOrder; i++)in.readSignedInt(sampleDepth);int precision = in.readUint(4) + 1;in.readSignedInt(5);for (int i = 0; i < lpcOrder; i++)in.readSignedInt(precision);decodeResiduals(in, lpcOrder, result);}private static void decodeResiduals(BitInputStream in, int warmup, long[] result) throws IOException, DataFormatException {int method = in.readUint(2);if (method >= 2)throw new DataFormatException("Reserved residual coding method");int paramBits = method == 0 ? 4 : 5;int escapeParam = method == 0 ? 0xF : 0x1F;int partitionOrder = in.readUint(4);int numPartitions = 1 << partitionOrder;if (result.length % numPartitions != 0)throw new DataFormatException("Block size not divisible by number of Rice partitions");int partitionSize = result.length / numPartitions;for (int i = 0; i < numPartitions; i++) {int start = i * partitionSize + (i == 0 ? warmup : 0);int end = (i + 1) * partitionSize;int param = in.readUint(paramBits);if (param < escapeParam) {for (int j = start; j < end; j++)result[j] = in.readRiceSignedInt(param);} else {int numBits = in.readUint(5);for (int j = start; j < end; j++)result[j] = in.readSignedInt(numBits);}}}}final class BitInputStream implements AutoCloseable {private InputStream in;private long bitBuffer;private int bitBufferLen;public BitInputStream(InputStream in) {this.in = in;}public void alignToByte() {bitBufferLen -= bitBufferLen % 8;}public int readByte() throws IOException {if (bitBufferLen >= 8)return readUint(8);elsereturn in.read();}public int readUint(int n) throws IOException {while (bitBufferLen < n) {int temp = in.read();if (temp == -1)throw new EOFException();bitBuffer = (bitBuffer << 8) | temp;bitBufferLen += 8;}bitBufferLen -= n;int result = (int)(bitBuffer >>> bitBufferLen);if (n < 32)result &= (1 << n) - 1;return result;}public int readSignedInt(int n) throws IOException {return (readUint(n) << (32 - n)) >> (32 - n);}public long readRiceSignedInt(int param) throws IOException {long val = 0;while (readUint(1) == 0)val++;val = (val << param) | readUint(param);return (val >>> 1) ^ -(val & 1);}public void close() throws IOException {in.close();}}
4.小结

wav2flac的过程结束后,flac文件的体积没啥变化,没有压缩。可以播放。

5.使用完整的jar包

wav2flac的过程结束后,flac文件的体积会变小。可以播放。详情参考githup库

6.资料

flac

flac convert

githup