📄 msg711.c
字号:
/* * G711 handling (includes A-Law & MU-Law) * * Copyright (C) 2002 Eric Pouech * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <assert.h>#include <stdarg.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winnls.h"#include "mmsystem.h"#include "mmreg.h"#include "msacm.h"#include "../msacmdrv.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(g711);/*********************************************************************** * G711_drvOpen */static DWORD G711_drvOpen(LPCSTR str){ return 1;}/*********************************************************************** * G711_drvClose */static DWORD G711_drvClose(DWORD dwDevID){ return 1;}typedef struct tagAcmG711Data{ void (*convert)(PACMDRVSTREAMINSTANCE adsi, const unsigned char*, LPDWORD, unsigned char*, LPDWORD);} AcmG711Data;/* table to list all supported formats... those are the basic ones. this * also helps given a unique index to each of the supported formats */typedef struct{ int nChannels; int nBits; int rate;} Format;static Format PCM_Formats[] ={ /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000}, /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025}, /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050}, /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100},};static Format ALaw_Formats[] ={ {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},};static Format ULaw_Formats[] ={ {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100},};#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))#define NUM_ALAW_FORMATS (sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0]))#define NUM_ULAW_FORMATS (sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0]))/*********************************************************************** * G711_GetFormatIndex */static DWORD G711_GetFormatIndex(LPWAVEFORMATEX wfx){ int i, hi; Format* fmts; switch (wfx->wFormatTag) { case WAVE_FORMAT_PCM: hi = NUM_PCM_FORMATS; fmts = PCM_Formats; break; case WAVE_FORMAT_ALAW: hi = NUM_ALAW_FORMATS; fmts = ALaw_Formats; break; case WAVE_FORMAT_MULAW: hi = NUM_ULAW_FORMATS; fmts = ULaw_Formats; break; default: return 0xFFFFFFFF; } for (i = 0; i < hi; i++) { if (wfx->nChannels == fmts[i].nChannels && wfx->nSamplesPerSec == fmts[i].rate && wfx->wBitsPerSample == fmts[i].nBits) return i; } return 0xFFFFFFFF;}/*********************************************************************** * R16 * * Read a 16 bit sample (correctly handles endianess) */static inline short R16(const unsigned char* src){ return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));}/*********************************************************************** * W16 * * Write a 16 bit sample (correctly handles endianess) */static inline void W16(unsigned char* dst, short s){ dst[0] = LOBYTE(s); dst[1] = HIBYTE(s);}/* You can uncomment this if you don't want the statically generated conversion * table, but rather recompute the Xlaw => PCM conversion for each sample#define NO_FASTDECODE * Since the conversion tables are rather small (2k), I don't think it's really * interesting not to use them, but keeping the actual conversion code around * is helpful to regenerate the tables when needed. *//* -------------------------------------------------------------------------------*//* * 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 *//* * g711.c * * u-law, A-law and linear PCM conversions. *//* * December 30, 1994: * Functions linear2alaw, linear2ulaw have been updated to correctly * convert unquantized 16 bit values. * Tables for direct u- to A-law and A- to u-law conversions have been * corrected. * Borge Lindberg, Center for PersonKommunikation, Aalborg University. * bli@cpk.auc.dk * */#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */#define QUANT_MASK (0xf) /* Quantization field mask. */#define NSEGS (8) /* Number of A-law segments. */#define SEG_SHIFT (4) /* Left shift for segment number. */#define SEG_MASK (0x70) /* Segment field mask. */static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF};static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};/* copy from CCITT G.711 specifications */static unsigned char _u2a[128] = { /* 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};static unsigned char _a2u[128] = { /* 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 shortsearch( int val, /* changed from "short" *drago* */ short *table, int size) /* changed from "short" *drago* */{ int i; /* changed from "short" *drago* */ for (i = 0; i < size; i++) { if (val <= *table++) return (i); } return (size);}/* * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law * * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. * * Linear Input Code Compressed Code * ------------------------ --------------- * 0000000wxyza 000wxyz * 0000001wxyza 001wxyz * 000001wxyzab 010wxyz * 00001wxyzabc 011wxyz * 0001wxyzabcd 100wxyz * 001wxyzabcde 101wxyz * 01wxyzabcdef 110wxyz * 1wxyzabcdefg 111wxyz * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */static inline unsigned charlinear2alaw(int pcm_val) /* 2's complement (16-bit range) */ /* changed from "short" *drago* */{ int mask; /* changed from "short" *drago* */ int seg; /* changed from "short" *drago* */ unsigned char aval; pcm_val = pcm_val >> 3; if (pcm_val >= 0) { mask = 0xD5; /* sign (7th) bit = 1 */ } else { mask = 0x55; /* sign bit = 0 */ pcm_val = -pcm_val - 1; } /* Convert the scaled magnitude to segment number. */ seg = search(pcm_val, seg_aend, 8); /* Combine the sign, segment, and quantization bits. */ if (seg >= 8) /* out of range, return maximum value. */ return (unsigned char) (0x7F ^ mask); else { aval = (unsigned char) seg << SEG_SHIFT; if (seg < 2) aval |= (pcm_val >> 1) & QUANT_MASK; else aval |= (pcm_val >> seg) & QUANT_MASK; return (aval ^ mask); }}#ifdef NO_FASTDECODE/* * alaw2linear() - Convert an A-law value to 16-bit linear PCM * */static inline intalaw2linear(unsigned char a_val){ int t; /* changed from "short" *drago* */ int seg; /* changed from "short" *drago* */ a_val ^= 0x55; t = (a_val & QUANT_MASK) << 4; seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; switch (seg) { case 0: t += 8; break; case 1: t += 0x108; break; default: t += 0x108; t <<= seg - 1; } return ((a_val & SIGN_BIT) ? t : -t);}#else/* EPP (for Wine): * this array has been statically generated from the above routine */static unsigned short _a2l[] = {0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -