package cn.org.hentai.jtt1078.codec; import cn.org.hentai.jtt1078.util.ByteUtils; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /** * Created by houcheng on 2019-12-11. */ public class G711UCodec extends AudioCodec { static final int ULAW = 1; static final int ALAW = 2; /* 16384 entries per table (16 bit) */ static byte[] linear_to_ulaw = new byte[65536]; /* 16384 entries per table (8 bit) */ static short[] ulaw_to_linear = new short[256]; static final int SIGN_BIT = 0x80; static final int QUANT_MASK = 0x0f; static final int NSEGS = 0x08; static final int SEG_SHIFT = 0x04; static final int SEG_MASK = 0x70; static final int BIAS = 0x84; static final int CLIP = 8159; static short[] seg_aend = { 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF }; static short[] seg_uend = { 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF }; int[] _u2a = { /* u- to A-law conversions */ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* corrected: 81, 82, 83, 84, 85, 86, 87, 88, should be: */ 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128}; int[] _a2u = { /* A- to u-law conversions */ 1, 3, 5, 7, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, /* corrected: 73, 74, 75, 76, 77, 78, 79, 79, should be: */ 73, 74, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127}; static { // 初始化ulaw表 for (int i = 0; i < 256; i++) ulaw_to_linear[i] = ulaw2linear((byte)i); // 初始化ulaw2linear表 for (int i = 0; i < 65535; i++) linear_to_ulaw[i] = linear2ulaw((short)i); } public static short ulaw2linear(byte u_val) { short t; u_val = (byte)(~u_val); t = (short)(((u_val & QUANT_MASK) << 3) + BIAS); t <<= (u_val & SEG_MASK) >>> SEG_SHIFT; return ((u_val & SIGN_BIT) > 0 ? (short)(BIAS - t) : (short)(t - BIAS)); } public static byte linear2ulaw(short pcm_val) { short mask; short seg; byte uval; pcm_val = (short)(pcm_val >> 2); if (pcm_val < 0) { pcm_val = (short)(-pcm_val); mask = 0x7f; } else { mask = 0xff; } if (pcm_val > CLIP) pcm_val = CLIP; pcm_val += (BIAS >> 2); seg = search(pcm_val, seg_uend, (short)8); if (seg >= 8) { return (byte)(0x7f ^ mask); } else { uval = (byte) ((seg << 4) | ((pcm_val >> (seg + 1)) & 0xF)); return (byte)(uval ^ mask); } } static short search(short val, short[] table, short size) { for (short i = 0; i < size; i++) { if (val <= table[i]) return i; } return size; } static void ulaw_to_pcm16(int src_length, byte[] src_samples, byte[] dst_samples) { for (int i = 0, k = 0; i < src_length; i++) { short s = ulaw_to_linear[src_samples[i] & 0xff]; dst_samples[k++] = (byte)(s & 0xff); dst_samples[k++] = (byte)((s >> 8) & 0xff); } } static void pcm16_to_ulaw(int src_length, byte[] src_samples, byte[] dst_samples) { short[] s_samples = ByteUtils.toShortArray(src_samples); for (int i = 0, k = 0; i < s_samples.length; i++) { dst_samples[k++] = linear2ulaw(s_samples[i]); } } @Override public byte[] toPCM(byte[] data) { byte[] temp; // 如果前四字节是00 01 52 00,则是海思头,需要去掉 if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) { temp = new byte[data.length - 4]; System.arraycopy(data, 4, temp, 0, temp.length); } else temp = data; byte[] dest = new byte[temp.length * 2]; ulaw_to_pcm16(temp.length, temp, dest); return dest; } @Override public byte[] fromPCM(byte[] data) { byte[] dest = new byte[data.length / 2]; pcm16_to_ulaw(data.length, data, dest); return dest; } public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("d:\\fuck121212121.pcm"); int len = -1; byte[] buff = new byte[320]; AudioCodec codec = new G711UCodec(); ByteArrayOutputStream baos = new ByteArrayOutputStream(4096 * 1024); while ((len = fis.read(buff)) > -1) { baos.write(buff, 0, len); } new FileOutputStream("D:\\temp\\fuckfuckfuck.g711u").write(codec.fromPCM(baos.toByteArray())); } }