📄 msg711.c
字号:
0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,};static int inlinealaw2linear(unsigned char a_val){ return (short)_a2l[a_val];}#endif#define BIAS (0x84) /* Bias for linear code. */#define CLIP 8159/* * linear2ulaw() - Convert a linear PCM value to u-law * * In order to simplify the encoding process, the original linear magnitude * is biased by adding 33 which shifts the encoding range from (0 - 8158) to * (33 - 8191). The result can be seen in the following encoding table: * * Biased Linear Input Code Compressed Code * ------------------------ --------------- * 00000001wxyza 000wxyz * 0000001wxyzab 001wxyz * 000001wxyzabc 010wxyz * 00001wxyzabcd 011wxyz * 0001wxyzabcde 100wxyz * 001wxyzabcdef 101wxyz * 01wxyzabcdefg 110wxyz * 1wxyzabcdefgh 111wxyz * * Each biased linear code has a leading 1 which identifies the segment * number. The value of the segment number is equal to 7 minus the number * of leading 0's. The quantization interval is directly available as the * four bits wxyz. * The trailing bits (a - h) are ignored. * * Ordinarily the complement of the resulting code word is used for * transmission, and so the code word is complemented before it is returned. * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */static inline unsigned charlinear2ulaw(short pcm_val) /* 2's complement (16-bit range) */{ short mask; short seg; unsigned char uval; /* Get the sign and the magnitude of the value. */ pcm_val = pcm_val >> 2; if (pcm_val < 0) { pcm_val = -pcm_val; mask = 0x7F; } else { mask = 0xFF; } if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ pcm_val += (BIAS >> 2); /* Convert the scaled magnitude to segment number. */ seg = search(pcm_val, seg_uend, 8); /* * Combine the sign, segment, quantization bits; * and complement the code word. */ if (seg >= 8) /* out of range, return maximum value. */ return (unsigned char) (0x7F ^ mask); else { uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); return (uval ^ mask); }}#ifdef NO_FASTDECODE/* * ulaw2linear() - Convert a u-law value to 16-bit linear PCM * * First, a biased linear code is derived from the code word. An unbiased * output can then be obtained by subtracting 33 from the biased code. * * Note that this function expects to be passed the complement of the * original code word. This is in keeping with ISDN conventions. */static inline shortulaw2linear(unsigned char u_val){ short t; /* Complement to obtain normal u-law value. */ u_val = ~u_val; /* * Extract and bias the quantization bits. Then * shift up by the segment number and subtract out the bias. */ t = ((u_val & QUANT_MASK) << 3) + BIAS; t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));}#else/* EPP (for Wine): * this array has been statically generated from the above routine */static unsigned short _u2l[] = {0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,};static inline short ulaw2linear(unsigned char u_val){ return (short)_u2l[u_val];}#endif/* A-law to u-law conversion */static inline unsigned charalaw2ulaw(unsigned char aval){ aval &= 0xff; return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : (0x7F ^ _a2u[aval ^ 0x55]));}/* u-law to A-law conversion */static inline unsigned charulaw2alaw(unsigned char uval){ uval &= 0xff; return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));}/* -------------------------------------------------------------------------------*/static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize, *dstsize / 2); DWORD i; short w; *srcsize = len; *dstsize = len * 2; for (i = 0; i < len; i++) { w = alaw2linear(*src++); W16(dst, w); dst += 2; }}static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize / 2, *dstsize); DWORD i; *srcsize = len * 2; *dstsize = len; for (i = 0; i < len; i++) { *dst++ = linear2alaw(R16(src)); src += 2; }}static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize, *dstsize / 2); DWORD i; short w; *srcsize = len; *dstsize = len * 2; for (i = 0; i < len; i++) { w = ulaw2linear(*src++); W16(dst, w); dst += 2; }}static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize / 2, *dstsize); DWORD i; *srcsize = len * 2; *dstsize = len; for (i = 0; i < len; i++) { *dst++ = linear2ulaw(R16(src)); src += 2; }}static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize, *dstsize); DWORD i; *srcsize = len; *dstsize = len; for (i = 0; i < len; i++) *dst++ = alaw2ulaw(*src++);}static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD srcsize, unsigned char* dst, LPDWORD dstsize){ DWORD len = min(*srcsize, *dstsize); DWORD i; *srcsize = len; *dstsize = len; for (i = 0; i < len; i++) *dst++ = ulaw2alaw(*src++);}/*********************************************************************** * G711_DriverDetails * */static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add){ add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; add->wMid = 0xFF; add->wPid = 0x00; add->vdwACM = 0x01000000; add->vdwDriver = 0x01000000; add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */ add->cFilterTags = 0; add->hicon = NULL; MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1, add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1, add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); add->szFeatures[0] = 0; return MMSYSERR_NOERROR;}/*********************************************************************** * G711_FormatTagDetails * */static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery){ static WCHAR szPcm[]={'P','C','M',0}; static WCHAR szALaw[]={'A','-','L','a','w',0}; static WCHAR szULaw[]={'U','-','L','a','w',0}; switch (dwQuery) { case ACM_FORMATTAGDETAILSF_INDEX: if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE; break; case ACM_FORMATTAGDETAILSF_LARGESTSIZE: if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) { aftd->dwFormatTagIndex = 1; break; } /* fall thru */ case ACM_FORMATTAGDETAILSF_FORMATTAG: switch (aftd->dwFormatTag) { case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break; case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break; default: return ACMERR_NOTPOSSIBLE; } break; default: WARN("Unsupported query %08lx\n", dwQuery); return MMSYSERR_NOTSUPPORTED; } aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; switch (aftd->dwFormatTagIndex) { case 0: aftd->dwFormatTag = WAVE_FORMAT_PCM; aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); aftd->cStandardFormats = NUM_PCM_FORMATS; lstrcpyW(aftd->szFormatTag, szPcm); break; case 1: aftd->dwFormatTag = WAVE_FORMAT_ALAW; aftd->cbFormatSize = sizeof(WAVEFORMATEX); aftd->cStandardFormats = NUM_ALAW_FORMATS; lstrcpyW(aftd->szFormatTag, szALaw); break; case 2: aftd->dwFormatTag = WAVE_FORMAT_MULAW; aftd->cbFormatSize = sizeof(WAVEFORMATEX); aftd->cStandardFormats = NUM_ULAW_FORMATS; lstrcpyW(aftd->szFormatTag, szULaw); break; } return MMSYSERR_NOERROR;}/*********************************************************************** * G711_FormatDetails * */static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery){ switch (dwQuery) { case ACM_FORMATDETAILSF_FORMAT: if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; break; case ACM_FORMATDETAILSF_INDEX: afd->pwfx->wFormatTag = afd->dwFormatTag; switch (afd->dwFormatTag) { case WAVE_FORMAT_PCM: if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2; afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; break; case WAVE_FORMAT_ALAW: if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits; afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels; afd->pwfx->cbSize = 0; break; case WAVE_FORMAT_MULAW: if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits; afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -