Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsg711.c
Go to the documentation of this file.
00001 /* 00002 * G711 handling (includes A-Law & MU-Law) 00003 * 00004 * Copyright (C) 2002 Eric Pouech 00005 * 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include <assert.h> 00023 #include <stdarg.h> 00024 #include <string.h> 00025 #include "windef.h" 00026 #include "winbase.h" 00027 #include "wingdi.h" 00028 #include "winuser.h" 00029 #include "winnls.h" 00030 #include "mmsystem.h" 00031 #include "mmreg.h" 00032 #include "msacm.h" 00033 #include "msacmdrv.h" 00034 #include "wine/debug.h" 00035 00036 WINE_DEFAULT_DEBUG_CHANNEL(g711); 00037 00038 /*********************************************************************** 00039 * G711_drvOpen 00040 */ 00041 static LRESULT G711_drvOpen(LPCSTR str) 00042 { 00043 return 1; 00044 } 00045 00046 /*********************************************************************** 00047 * G711_drvClose 00048 */ 00049 static LRESULT G711_drvClose(DWORD_PTR dwDevID) 00050 { 00051 return 1; 00052 } 00053 00054 typedef struct tagAcmG711Data 00055 { 00056 void (*convert)(PACMDRVSTREAMINSTANCE adsi, 00057 const unsigned char*, LPDWORD, unsigned char*, LPDWORD); 00058 } AcmG711Data; 00059 00060 /* table to list all supported formats... those are the basic ones. this 00061 * also helps given a unique index to each of the supported formats 00062 */ 00063 typedef struct 00064 { 00065 int nChannels; 00066 int nBits; 00067 int rate; 00068 } Format; 00069 00070 static const Format PCM_Formats[] = 00071 { 00072 /*{1, 8, 8000}, {2, 8, 8000}, */{1, 16, 8000}, {2, 16, 8000}, 00073 /*{1, 8, 11025}, {2, 8, 11025}, */{1, 16, 11025}, {2, 16, 11025}, 00074 /*{1, 8, 22050}, {2, 8, 22050}, */{1, 16, 22050}, {2, 16, 22050}, 00075 /*{1, 8, 44100}, {2, 8, 44100}, */{1, 16, 44100}, {2, 16, 44100}, 00076 }; 00077 00078 static const Format ALaw_Formats[] = 00079 { 00080 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, 00081 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100}, 00082 }; 00083 00084 static const Format ULaw_Formats[] = 00085 { 00086 {1, 8, 8000}, {2, 8, 8000}, {1, 8, 11025}, {2, 8, 11025}, 00087 {1, 8, 22050}, {2, 8, 22050}, {1, 8, 44100}, {2, 8, 44100}, 00088 }; 00089 00090 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) 00091 #define NUM_ALAW_FORMATS (sizeof(ALaw_Formats) / sizeof(ALaw_Formats[0])) 00092 #define NUM_ULAW_FORMATS (sizeof(ULaw_Formats) / sizeof(ULaw_Formats[0])) 00093 00094 /*********************************************************************** 00095 * G711_GetFormatIndex 00096 */ 00097 static DWORD G711_GetFormatIndex(const WAVEFORMATEX *wfx) 00098 { 00099 int i, hi; 00100 const Format* fmts; 00101 00102 switch (wfx->wFormatTag) 00103 { 00104 case WAVE_FORMAT_PCM: 00105 hi = NUM_PCM_FORMATS; 00106 fmts = PCM_Formats; 00107 break; 00108 case WAVE_FORMAT_ALAW: 00109 hi = NUM_ALAW_FORMATS; 00110 fmts = ALaw_Formats; 00111 break; 00112 case WAVE_FORMAT_MULAW: 00113 hi = NUM_ULAW_FORMATS; 00114 fmts = ULaw_Formats; 00115 break; 00116 default: 00117 return 0xFFFFFFFF; 00118 } 00119 00120 for (i = 0; i < hi; i++) 00121 { 00122 if (wfx->nChannels == fmts[i].nChannels && 00123 wfx->nSamplesPerSec == fmts[i].rate && 00124 wfx->wBitsPerSample == fmts[i].nBits) 00125 return i; 00126 } 00127 00128 return 0xFFFFFFFF; 00129 } 00130 00131 /*********************************************************************** 00132 * R16 00133 * 00134 * Read a 16 bit sample (correctly handles endianness) 00135 */ 00136 static inline short R16(const unsigned char* src) 00137 { 00138 return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8)); 00139 } 00140 00141 /*********************************************************************** 00142 * W16 00143 * 00144 * Write a 16 bit sample (correctly handles endianness) 00145 */ 00146 static inline void W16(unsigned char* dst, short s) 00147 { 00148 dst[0] = LOBYTE(s); 00149 dst[1] = HIBYTE(s); 00150 } 00151 00152 /* You can uncomment this if you don't want the statically generated conversion 00153 * table, but rather recompute the Xlaw => PCM conversion for each sample 00154 #define NO_FASTDECODE 00155 * Since the conversion tables are rather small (2k), I don't think it's really 00156 * interesting not to use them, but keeping the actual conversion code around 00157 * is helpful to regenerate the tables when needed. 00158 */ 00159 00160 /* -------------------------------------------------------------------------------*/ 00161 00162 /* 00163 * This source code is a product of Sun Microsystems, Inc. and is provided 00164 * for unrestricted use. Users may copy or modify this source code without 00165 * charge. 00166 * 00167 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING 00168 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 00169 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 00170 * 00171 * Sun source code is provided with no support and without any obligation on 00172 * the part of Sun Microsystems, Inc. to assist in its use, correction, 00173 * modification or enhancement. 00174 * 00175 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 00176 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE 00177 * OR ANY PART THEREOF. 00178 * 00179 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 00180 * or profits or other special, indirect and consequential damages, even if 00181 * Sun has been advised of the possibility of such damages. 00182 * 00183 * Sun Microsystems, Inc. 00184 * 2550 Garcia Avenue 00185 * Mountain View, California 94043 00186 */ 00187 00188 /* 00189 * g711.c 00190 * 00191 * u-law, A-law and linear PCM conversions. 00192 */ 00193 00194 /* 00195 * December 30, 1994: 00196 * Functions linear2alaw, linear2ulaw have been updated to correctly 00197 * convert unquantized 16 bit values. 00198 * Tables for direct u- to A-law and A- to u-law conversions have been 00199 * corrected. 00200 * Borge Lindberg, Center for PersonKommunikation, Aalborg University. 00201 * bli@cpk.auc.dk 00202 * 00203 */ 00204 00205 #define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */ 00206 #define QUANT_MASK (0xf) /* Quantization field mask. */ 00207 #define NSEGS (8) /* Number of A-law segments. */ 00208 #define SEG_SHIFT (4) /* Left shift for segment number. */ 00209 #define SEG_MASK (0x70) /* Segment field mask. */ 00210 00211 static const short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF}; 00212 static const short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; 00213 00214 /* copy from CCITT G.711 specifications */ 00215 static const unsigned char _u2a[128] = { /* u- to A-law conversions */ 00216 1, 1, 2, 2, 3, 3, 4, 4, 00217 5, 5, 6, 6, 7, 7, 8, 8, 00218 9, 10, 11, 12, 13, 14, 15, 16, 00219 17, 18, 19, 20, 21, 22, 23, 24, 00220 25, 27, 29, 31, 33, 34, 35, 36, 00221 37, 38, 39, 40, 41, 42, 43, 44, 00222 46, 48, 49, 50, 51, 52, 53, 54, 00223 55, 56, 57, 58, 59, 60, 61, 62, 00224 64, 65, 66, 67, 68, 69, 70, 71, 00225 72, 73, 74, 75, 76, 77, 78, 79, 00226 /* corrected: 00227 81, 82, 83, 84, 85, 86, 87, 88, 00228 should be: */ 00229 80, 82, 83, 84, 85, 86, 87, 88, 00230 89, 90, 91, 92, 93, 94, 95, 96, 00231 97, 98, 99, 100, 101, 102, 103, 104, 00232 105, 106, 107, 108, 109, 110, 111, 112, 00233 113, 114, 115, 116, 117, 118, 119, 120, 00234 121, 122, 123, 124, 125, 126, 127, 128}; 00235 00236 static const unsigned char _a2u[128] = { /* A- to u-law conversions */ 00237 1, 3, 5, 7, 9, 11, 13, 15, 00238 16, 17, 18, 19, 20, 21, 22, 23, 00239 24, 25, 26, 27, 28, 29, 30, 31, 00240 32, 32, 33, 33, 34, 34, 35, 35, 00241 36, 37, 38, 39, 40, 41, 42, 43, 00242 44, 45, 46, 47, 48, 48, 49, 49, 00243 50, 51, 52, 53, 54, 55, 56, 57, 00244 58, 59, 60, 61, 62, 63, 64, 64, 00245 65, 66, 67, 68, 69, 70, 71, 72, 00246 /* corrected: 00247 73, 74, 75, 76, 77, 78, 79, 79, 00248 should be: */ 00249 73, 74, 75, 76, 77, 78, 79, 80, 00250 00251 80, 81, 82, 83, 84, 85, 86, 87, 00252 88, 89, 90, 91, 92, 93, 94, 95, 00253 96, 97, 98, 99, 100, 101, 102, 103, 00254 104, 105, 106, 107, 108, 109, 110, 111, 00255 112, 113, 114, 115, 116, 117, 118, 119, 00256 120, 121, 122, 123, 124, 125, 126, 127}; 00257 00258 static short 00259 search( 00260 int val, /* changed from "short" *drago* */ 00261 const short *table, 00262 int size) /* changed from "short" *drago* */ 00263 { 00264 int i; /* changed from "short" *drago* */ 00265 00266 for (i = 0; i < size; i++) { 00267 if (val <= *table++) 00268 return (i); 00269 } 00270 return (size); 00271 } 00272 00273 /* 00274 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law 00275 * 00276 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. 00277 * 00278 * Linear Input Code Compressed Code 00279 * ------------------------ --------------- 00280 * 0000000wxyza 000wxyz 00281 * 0000001wxyza 001wxyz 00282 * 000001wxyzab 010wxyz 00283 * 00001wxyzabc 011wxyz 00284 * 0001wxyzabcd 100wxyz 00285 * 001wxyzabcde 101wxyz 00286 * 01wxyzabcdef 110wxyz 00287 * 1wxyzabcdefg 111wxyz 00288 * 00289 * For further information see John C. Bellamy's Digital Telephony, 1982, 00290 * John Wiley & Sons, pps 98-111 and 472-476. 00291 */ 00292 static inline unsigned char 00293 linear2alaw(int pcm_val) /* 2's complement (16-bit range) */ 00294 /* changed from "short" *drago* */ 00295 { 00296 int mask; /* changed from "short" *drago* */ 00297 int seg; /* changed from "short" *drago* */ 00298 unsigned char aval; 00299 00300 pcm_val = pcm_val >> 3; 00301 00302 if (pcm_val >= 0) { 00303 mask = 0xD5; /* sign (7th) bit = 1 */ 00304 } else { 00305 mask = 0x55; /* sign bit = 0 */ 00306 pcm_val = -pcm_val - 1; 00307 } 00308 00309 /* Convert the scaled magnitude to segment number. */ 00310 seg = search(pcm_val, seg_aend, 8); 00311 00312 /* Combine the sign, segment, and quantization bits. */ 00313 00314 if (seg >= 8) /* out of range, return maximum value. */ 00315 return (unsigned char) (0x7F ^ mask); 00316 else { 00317 aval = (unsigned char) seg << SEG_SHIFT; 00318 if (seg < 2) 00319 aval |= (pcm_val >> 1) & QUANT_MASK; 00320 else 00321 aval |= (pcm_val >> seg) & QUANT_MASK; 00322 return (aval ^ mask); 00323 } 00324 } 00325 00326 #ifdef NO_FASTDECODE 00327 /* 00328 * alaw2linear() - Convert an A-law value to 16-bit linear PCM 00329 * 00330 */ 00331 static inline int 00332 alaw2linear(unsigned char a_val) 00333 { 00334 int t; /* changed from "short" *drago* */ 00335 int seg; /* changed from "short" *drago* */ 00336 00337 a_val ^= 0x55; 00338 00339 t = (a_val & QUANT_MASK) << 4; 00340 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; 00341 switch (seg) { 00342 case 0: 00343 t += 8; 00344 break; 00345 case 1: 00346 t += 0x108; 00347 break; 00348 default: 00349 t += 0x108; 00350 t <<= seg - 1; 00351 } 00352 return ((a_val & SIGN_BIT) ? t : -t); 00353 } 00354 #else 00355 /* EPP (for Wine): 00356 * this array has been statically generated from the above routine 00357 */ 00358 static const unsigned short _a2l[] = { 00359 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 00360 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, 00361 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 00362 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, 00363 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 00364 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, 00365 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 00366 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00, 00367 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 00368 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58, 00369 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 00370 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58, 00371 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 00372 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960, 00373 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 00374 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0, 00375 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 00376 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80, 00377 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 00378 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40, 00379 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 00380 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00, 00381 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 00382 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500, 00383 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 00384 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8, 00385 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 00386 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8, 00387 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 00388 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0, 00389 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 00390 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350, 00391 }; 00392 static inline int 00393 alaw2linear(unsigned char a_val) 00394 { 00395 return (short)_a2l[a_val]; 00396 } 00397 #endif 00398 00399 #define BIAS (0x84) /* Bias for linear code. */ 00400 #define CLIP 8159 00401 00402 /* 00403 * linear2ulaw() - Convert a linear PCM value to u-law 00404 * 00405 * In order to simplify the encoding process, the original linear magnitude 00406 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to 00407 * (33 - 8191). The result can be seen in the following encoding table: 00408 * 00409 * Biased Linear Input Code Compressed Code 00410 * ------------------------ --------------- 00411 * 00000001wxyza 000wxyz 00412 * 0000001wxyzab 001wxyz 00413 * 000001wxyzabc 010wxyz 00414 * 00001wxyzabcd 011wxyz 00415 * 0001wxyzabcde 100wxyz 00416 * 001wxyzabcdef 101wxyz 00417 * 01wxyzabcdefg 110wxyz 00418 * 1wxyzabcdefgh 111wxyz 00419 * 00420 * Each biased linear code has a leading 1 which identifies the segment 00421 * number. The value of the segment number is equal to 7 minus the number 00422 * of leading 0's. The quantization interval is directly available as the 00423 * four bits wxyz. * The trailing bits (a - h) are ignored. 00424 * 00425 * Ordinarily the complement of the resulting code word is used for 00426 * transmission, and so the code word is complemented before it is returned. 00427 * 00428 * For further information see John C. Bellamy's Digital Telephony, 1982, 00429 * John Wiley & Sons, pps 98-111 and 472-476. 00430 */ 00431 static inline unsigned char 00432 linear2ulaw(short pcm_val) /* 2's complement (16-bit range) */ 00433 { 00434 short mask; 00435 short seg; 00436 unsigned char uval; 00437 00438 /* Get the sign and the magnitude of the value. */ 00439 pcm_val = pcm_val >> 2; 00440 if (pcm_val < 0) { 00441 pcm_val = -pcm_val; 00442 mask = 0x7F; 00443 } else { 00444 mask = 0xFF; 00445 } 00446 if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ 00447 pcm_val += (BIAS >> 2); 00448 00449 /* Convert the scaled magnitude to segment number. */ 00450 seg = search(pcm_val, seg_uend, 8); 00451 00452 /* 00453 * Combine the sign, segment, quantization bits; 00454 * and complement the code word. 00455 */ 00456 if (seg >= 8) /* out of range, return maximum value. */ 00457 return (unsigned char) (0x7F ^ mask); 00458 else { 00459 uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); 00460 return (uval ^ mask); 00461 } 00462 } 00463 00464 #ifdef NO_FASTDECODE 00465 /* 00466 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM 00467 * 00468 * First, a biased linear code is derived from the code word. An unbiased 00469 * output can then be obtained by subtracting 33 from the biased code. 00470 * 00471 * Note that this function expects to be passed the complement of the 00472 * original code word. This is in keeping with ISDN conventions. 00473 */ 00474 static inline short 00475 ulaw2linear(unsigned char u_val) 00476 { 00477 short t; 00478 00479 /* Complement to obtain normal u-law value. */ 00480 u_val = ~u_val; 00481 00482 /* 00483 * Extract and bias the quantization bits. Then 00484 * shift up by the segment number and subtract out the bias. 00485 */ 00486 t = ((u_val & QUANT_MASK) << 3) + BIAS; 00487 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; 00488 00489 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); 00490 } 00491 #else 00492 /* EPP (for Wine): 00493 * this array has been statically generated from the above routine 00494 */ 00495 static const unsigned short _u2l[] = { 00496 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 00497 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, 00498 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 00499 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, 00500 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 00501 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, 00502 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 00503 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844, 00504 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 00505 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64, 00506 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 00507 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74, 00508 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 00509 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C, 00510 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 00511 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000, 00512 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 00513 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C, 00514 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 00515 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C, 00516 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 00517 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC, 00518 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 00519 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC, 00520 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 00521 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C, 00522 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 00523 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C, 00524 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 00525 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084, 00526 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 00527 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000, 00528 }; 00529 static inline short ulaw2linear(unsigned char u_val) 00530 { 00531 return (short)_u2l[u_val]; 00532 } 00533 #endif 00534 00535 /* A-law to u-law conversion */ 00536 static inline unsigned char 00537 alaw2ulaw(unsigned char aval) 00538 { 00539 aval &= 0xff; 00540 return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : 00541 (0x7F ^ _a2u[aval ^ 0x55])); 00542 } 00543 00544 /* u-law to A-law conversion */ 00545 static inline unsigned char 00546 ulaw2alaw(unsigned char uval) 00547 { 00548 uval &= 0xff; 00549 return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : 00550 (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); 00551 } 00552 00553 /* -------------------------------------------------------------------------------*/ 00554 00555 static void cvtXXalaw16K(PACMDRVSTREAMINSTANCE adsi, 00556 const unsigned char* src, LPDWORD srcsize, 00557 unsigned char* dst, LPDWORD dstsize) 00558 { 00559 DWORD len = min(*srcsize, *dstsize / 2); 00560 DWORD i; 00561 short w; 00562 00563 *srcsize = len; 00564 *dstsize = len * 2; 00565 for (i = 0; i < len; i++) 00566 { 00567 w = alaw2linear(*src++); 00568 W16(dst, w); dst += 2; 00569 } 00570 } 00571 00572 static void cvtXX16alawK(PACMDRVSTREAMINSTANCE adsi, 00573 const unsigned char* src, LPDWORD srcsize, 00574 unsigned char* dst, LPDWORD dstsize) 00575 { 00576 DWORD len = min(*srcsize / 2, *dstsize); 00577 DWORD i; 00578 00579 *srcsize = len * 2; 00580 *dstsize = len; 00581 for (i = 0; i < len; i++) 00582 { 00583 *dst++ = linear2alaw(R16(src)); src += 2; 00584 } 00585 } 00586 00587 static void cvtXXulaw16K(PACMDRVSTREAMINSTANCE adsi, 00588 const unsigned char* src, LPDWORD srcsize, 00589 unsigned char* dst, LPDWORD dstsize) 00590 { 00591 DWORD len = min(*srcsize, *dstsize / 2); 00592 DWORD i; 00593 short w; 00594 00595 *srcsize = len; 00596 *dstsize = len * 2; 00597 for (i = 0; i < len; i++) 00598 { 00599 w = ulaw2linear(*src++); 00600 W16(dst, w); dst += 2; 00601 } 00602 } 00603 00604 static void cvtXX16ulawK(PACMDRVSTREAMINSTANCE adsi, 00605 const unsigned char* src, LPDWORD srcsize, 00606 unsigned char* dst, LPDWORD dstsize) 00607 { 00608 DWORD len = min(*srcsize / 2, *dstsize); 00609 DWORD i; 00610 00611 *srcsize = len * 2; 00612 *dstsize = len; 00613 for (i = 0; i < len; i++) 00614 { 00615 *dst++ = linear2ulaw(R16(src)); src += 2; 00616 } 00617 } 00618 00619 static void cvtXXalawulawK(PACMDRVSTREAMINSTANCE adsi, 00620 const unsigned char* src, LPDWORD srcsize, 00621 unsigned char* dst, LPDWORD dstsize) 00622 { 00623 DWORD len = min(*srcsize, *dstsize); 00624 DWORD i; 00625 00626 *srcsize = len; 00627 *dstsize = len; 00628 00629 for (i = 0; i < len; i++) 00630 *dst++ = alaw2ulaw(*src++); 00631 } 00632 00633 00634 static void cvtXXulawalawK(PACMDRVSTREAMINSTANCE adsi, 00635 const unsigned char* src, LPDWORD srcsize, 00636 unsigned char* dst, LPDWORD dstsize) 00637 { 00638 DWORD len = min(*srcsize, *dstsize); 00639 DWORD i; 00640 00641 *srcsize = len; 00642 *dstsize = len; 00643 00644 for (i = 0; i < len; i++) 00645 *dst++ = ulaw2alaw(*src++); 00646 } 00647 00648 /*********************************************************************** 00649 * G711_DriverDetails 00650 * 00651 */ 00652 static LRESULT G711_DriverDetails(PACMDRIVERDETAILSW add) 00653 { 00654 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 00655 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 00656 add->wMid = 0xFF; 00657 add->wPid = 0x00; 00658 add->vdwACM = 0x01000000; 00659 add->vdwDriver = 0x01000000; 00660 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 00661 add->cFormatTags = 3; /* PCM, G711 A-LAW & MU-LAW */ 00662 add->cFilterTags = 0; 00663 add->hicon = NULL; 00664 MultiByteToWideChar( CP_ACP, 0, "WINE-G711", -1, 00665 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); 00666 MultiByteToWideChar( CP_ACP, 0, "Wine G711 converter", -1, 00667 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); 00668 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, 00669 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); 00670 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, 00671 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); 00672 add->szFeatures[0] = 0; 00673 00674 return MMSYSERR_NOERROR; 00675 } 00676 00677 /*********************************************************************** 00678 * G711_FormatTagDetails 00679 * 00680 */ 00681 static LRESULT G711_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) 00682 { 00683 static const WCHAR szPcm[]={'P','C','M',0}; 00684 static const WCHAR szALaw[]={'A','-','L','a','w',0}; 00685 static const WCHAR szULaw[]={'U','-','L','a','w',0}; 00686 00687 switch (dwQuery) 00688 { 00689 case ACM_FORMATTAGDETAILSF_INDEX: 00690 if (aftd->dwFormatTagIndex >= 3) return ACMERR_NOTPOSSIBLE; 00691 break; 00692 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 00693 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) 00694 { 00695 aftd->dwFormatTagIndex = 1; 00696 break; 00697 } 00698 /* fall thru */ 00699 case ACM_FORMATTAGDETAILSF_FORMATTAG: 00700 switch (aftd->dwFormatTag) 00701 { 00702 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; 00703 case WAVE_FORMAT_ALAW: aftd->dwFormatTagIndex = 1; break; 00704 case WAVE_FORMAT_MULAW: aftd->dwFormatTagIndex = 2; break; 00705 default: return ACMERR_NOTPOSSIBLE; 00706 } 00707 break; 00708 default: 00709 WARN("Unsupported query %08x\n", dwQuery); 00710 return MMSYSERR_NOTSUPPORTED; 00711 } 00712 00713 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 00714 switch (aftd->dwFormatTagIndex) 00715 { 00716 case 0: 00717 aftd->dwFormatTag = WAVE_FORMAT_PCM; 00718 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); 00719 aftd->cStandardFormats = NUM_PCM_FORMATS; 00720 lstrcpyW(aftd->szFormatTag, szPcm); 00721 break; 00722 case 1: 00723 aftd->dwFormatTag = WAVE_FORMAT_ALAW; 00724 aftd->cbFormatSize = sizeof(WAVEFORMATEX); 00725 aftd->cStandardFormats = NUM_ALAW_FORMATS; 00726 lstrcpyW(aftd->szFormatTag, szALaw); 00727 break; 00728 case 2: 00729 aftd->dwFormatTag = WAVE_FORMAT_MULAW; 00730 aftd->cbFormatSize = sizeof(WAVEFORMATEX); 00731 aftd->cStandardFormats = NUM_ULAW_FORMATS; 00732 lstrcpyW(aftd->szFormatTag, szULaw); 00733 break; 00734 } 00735 return MMSYSERR_NOERROR; 00736 } 00737 00738 /*********************************************************************** 00739 * G711_FormatDetails 00740 * 00741 */ 00742 static LRESULT G711_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) 00743 { 00744 switch (dwQuery) 00745 { 00746 case ACM_FORMATDETAILSF_FORMAT: 00747 if (G711_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 00748 break; 00749 case ACM_FORMATDETAILSF_INDEX: 00750 afd->pwfx->wFormatTag = afd->dwFormatTag; 00751 switch (afd->dwFormatTag) 00752 { 00753 case WAVE_FORMAT_PCM: 00754 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; 00755 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; 00756 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; 00757 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; 00758 afd->pwfx->nBlockAlign = afd->pwfx->nChannels * 2; 00759 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; 00760 break; 00761 case WAVE_FORMAT_ALAW: 00762 if (afd->dwFormatIndex >= NUM_ALAW_FORMATS) return ACMERR_NOTPOSSIBLE; 00763 afd->pwfx->nChannels = ALaw_Formats[afd->dwFormatIndex].nChannels; 00764 afd->pwfx->nSamplesPerSec = ALaw_Formats[afd->dwFormatIndex].rate; 00765 afd->pwfx->wBitsPerSample = ALaw_Formats[afd->dwFormatIndex].nBits; 00766 afd->pwfx->nBlockAlign = ALaw_Formats[afd->dwFormatIndex].nChannels; 00767 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels; 00768 afd->pwfx->cbSize = 0; 00769 break; 00770 case WAVE_FORMAT_MULAW: 00771 if (afd->dwFormatIndex >= NUM_ULAW_FORMATS) return ACMERR_NOTPOSSIBLE; 00772 afd->pwfx->nChannels = ULaw_Formats[afd->dwFormatIndex].nChannels; 00773 afd->pwfx->nSamplesPerSec = ULaw_Formats[afd->dwFormatIndex].rate; 00774 afd->pwfx->wBitsPerSample = ULaw_Formats[afd->dwFormatIndex].nBits; 00775 afd->pwfx->nBlockAlign = ULaw_Formats[afd->dwFormatIndex].nChannels; 00776 afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nChannels; 00777 afd->pwfx->cbSize = 0; 00778 break; 00779 default: 00780 WARN("Unsupported tag %08x\n", afd->dwFormatTag); 00781 return MMSYSERR_INVALPARAM; 00782 } 00783 break; 00784 default: 00785 WARN("Unsupported query %08x\n", dwQuery); 00786 return MMSYSERR_NOTSUPPORTED; 00787 } 00788 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; 00789 afd->szFormat[0] = 0; /* let MSACM format this for us... */ 00790 00791 return MMSYSERR_NOERROR; 00792 } 00793 00794 /*********************************************************************** 00795 * G711_FormatSuggest 00796 * 00797 */ 00798 static LRESULT G711_FormatSuggest(PACMDRVFORMATSUGGEST adfs) 00799 { 00800 /* some tests ... */ 00801 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) || 00802 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) || 00803 G711_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 00804 /* FIXME: should do those tests against the real size (according to format tag */ 00805 00806 /* If no suggestion for destination, then copy source value */ 00807 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)) 00808 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; 00809 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) 00810 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; 00811 00812 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) 00813 { 00814 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) 00815 adfs->pwfxDst->wBitsPerSample = 8; 00816 else 00817 adfs->pwfxDst->wBitsPerSample = 16; 00818 } 00819 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) 00820 { 00821 switch (adfs->pwfxSrc->wFormatTag) 00822 { 00823 case WAVE_FORMAT_PCM: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_ALAW; break; 00824 case WAVE_FORMAT_ALAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break; 00825 case WAVE_FORMAT_MULAW: adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; break; 00826 } 00827 } 00828 /* check if result is ok */ 00829 if (G711_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; 00830 00831 /* recompute other values */ 00832 switch (adfs->pwfxDst->wFormatTag) 00833 { 00834 case WAVE_FORMAT_PCM: 00835 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels * 2; 00836 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; 00837 break; 00838 case WAVE_FORMAT_ALAW: 00839 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels; 00840 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels; 00841 break; 00842 case WAVE_FORMAT_MULAW: 00843 adfs->pwfxDst->nBlockAlign = adfs->pwfxDst->nChannels; 00844 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxSrc->nChannels; 00845 break; 00846 default: 00847 FIXME("\n"); 00848 break; 00849 } 00850 00851 return MMSYSERR_NOERROR; 00852 } 00853 00854 /*********************************************************************** 00855 * G711_Reset 00856 * 00857 */ 00858 static void G711_Reset(PACMDRVSTREAMINSTANCE adsi, AcmG711Data* aad) 00859 { 00860 } 00861 00862 /*********************************************************************** 00863 * G711_StreamOpen 00864 * 00865 */ 00866 static LRESULT G711_StreamOpen(PACMDRVSTREAMINSTANCE adsi) 00867 { 00868 AcmG711Data* aad; 00869 00870 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC)); 00871 00872 if (G711_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF || 00873 G711_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF) 00874 return ACMERR_NOTPOSSIBLE; 00875 00876 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmG711Data)); 00877 if (aad == 0) return MMSYSERR_NOMEM; 00878 00879 adsi->dwDriver = (DWORD_PTR)aad; 00880 00881 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 00882 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 00883 { 00884 goto theEnd; 00885 } 00886 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW && 00887 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 00888 { 00889 /* resampling or mono <=> stereo not available 00890 * G711 algo only define 16 bit per sample output 00891 */ 00892 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00893 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 00894 adsi->pwfxDst->wBitsPerSample != 16) 00895 goto theEnd; 00896 00897 /* g711 A-Law decoding... */ 00898 if (adsi->pwfxDst->wBitsPerSample == 16) 00899 aad->convert = cvtXXalaw16K; 00900 } 00901 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 00902 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW) 00903 { 00904 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00905 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 00906 adsi->pwfxSrc->wBitsPerSample != 16) 00907 goto theEnd; 00908 00909 /* g711 coding... */ 00910 if (adsi->pwfxSrc->wBitsPerSample == 16) 00911 aad->convert = cvtXX16alawK; 00912 } 00913 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW && 00914 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 00915 { 00916 /* resampling or mono <=> stereo not available 00917 * G711 algo only define 16 bit per sample output 00918 */ 00919 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00920 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 00921 adsi->pwfxDst->wBitsPerSample != 16) 00922 goto theEnd; 00923 00924 /* g711 MU-Law decoding... */ 00925 if (adsi->pwfxDst->wBitsPerSample == 16) 00926 aad->convert = cvtXXulaw16K; 00927 } 00928 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 00929 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW) 00930 { 00931 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00932 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels || 00933 adsi->pwfxSrc->wBitsPerSample != 16) 00934 goto theEnd; 00935 00936 /* g711 coding... */ 00937 if (adsi->pwfxSrc->wBitsPerSample == 16) 00938 aad->convert = cvtXX16ulawK; 00939 } 00940 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW && 00941 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW) 00942 { 00943 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00944 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels) 00945 goto theEnd; 00946 00947 /* MU-Law => A-Law... */ 00948 aad->convert = cvtXXulawalawK; 00949 } 00950 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW && 00951 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW) 00952 { 00953 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec || 00954 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels) 00955 goto theEnd; 00956 00957 /* A-Law => MU-Law... */ 00958 aad->convert = cvtXXalawulawK; 00959 } 00960 else goto theEnd; 00961 00962 G711_Reset(adsi, aad); 00963 00964 return MMSYSERR_NOERROR; 00965 00966 theEnd: 00967 HeapFree(GetProcessHeap(), 0, aad); 00968 adsi->dwDriver = 0L; 00969 return MMSYSERR_NOTSUPPORTED; 00970 } 00971 00972 /*********************************************************************** 00973 * G711_StreamClose 00974 * 00975 */ 00976 static LRESULT G711_StreamClose(PACMDRVSTREAMINSTANCE adsi) 00977 { 00978 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver); 00979 return MMSYSERR_NOERROR; 00980 } 00981 00982 /*********************************************************************** 00983 * G711_StreamSize 00984 * 00985 */ 00986 static LRESULT G711_StreamSize(const ACMDRVSTREAMINSTANCE *adsi, PACMDRVSTREAMSIZE adss) 00987 { 00988 switch (adss->fdwSize) 00989 { 00990 case ACM_STREAMSIZEF_DESTINATION: 00991 /* cbDstLength => cbSrcLength */ 00992 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 00993 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || 00994 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) 00995 { 00996 adss->cbSrcLength = adss->cbDstLength * 2; 00997 } 00998 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || 00999 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && 01000 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 01001 { 01002 adss->cbSrcLength = adss->cbDstLength / 2; 01003 } 01004 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || 01005 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && 01006 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || 01007 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) 01008 { 01009 adss->cbSrcLength = adss->cbDstLength; 01010 } 01011 else 01012 { 01013 return MMSYSERR_NOTSUPPORTED; 01014 } 01015 break; 01016 case ACM_STREAMSIZEF_SOURCE: 01017 /* cbSrcLength => cbDstLength */ 01018 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && 01019 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || 01020 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) 01021 { 01022 adss->cbDstLength = adss->cbSrcLength / 2; 01023 } 01024 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || 01025 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && 01026 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) 01027 { 01028 adss->cbDstLength = adss->cbSrcLength * 2; 01029 } 01030 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_ALAW || 01031 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MULAW) && 01032 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_ALAW || 01033 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MULAW)) 01034 { 01035 adss->cbDstLength = adss->cbSrcLength; 01036 } 01037 else 01038 { 01039 return MMSYSERR_NOTSUPPORTED; 01040 } 01041 break; 01042 default: 01043 WARN("Unsupported query %08x\n", adss->fdwSize); 01044 return MMSYSERR_NOTSUPPORTED; 01045 } 01046 FIXME("\n"); 01047 return MMSYSERR_NOERROR; 01048 } 01049 01050 /*********************************************************************** 01051 * G711_StreamConvert 01052 * 01053 */ 01054 static LRESULT G711_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh) 01055 { 01056 AcmG711Data* aad = (AcmG711Data*)adsi->dwDriver; 01057 DWORD nsrc = adsh->cbSrcLength; 01058 DWORD ndst = adsh->cbDstLength; 01059 01060 if (adsh->fdwConvert & 01061 ~(ACM_STREAMCONVERTF_BLOCKALIGN| 01062 ACM_STREAMCONVERTF_END| 01063 ACM_STREAMCONVERTF_START)) 01064 { 01065 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert); 01066 } 01067 /* ACM_STREAMCONVERTF_BLOCKALIGN 01068 * currently all conversions are block aligned, so do nothing for this flag 01069 * ACM_STREAMCONVERTF_END 01070 * no pending data, so do nothing for this flag 01071 */ 01072 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START)) 01073 { 01074 G711_Reset(adsi, aad); 01075 } 01076 01077 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst); 01078 adsh->cbSrcLengthUsed = nsrc; 01079 adsh->cbDstLengthUsed = ndst; 01080 01081 return MMSYSERR_NOERROR; 01082 } 01083 01084 /************************************************************************** 01085 * G711_DriverProc [exported] 01086 */ 01087 LRESULT CALLBACK G711_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 01088 LPARAM dwParam1, LPARAM dwParam2) 01089 { 01090 TRACE("(%08lx %p %04x %08lx %08lx);\n", 01091 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 01092 01093 switch (wMsg) 01094 { 01095 case DRV_LOAD: return 1; 01096 case DRV_FREE: return 1; 01097 case DRV_OPEN: return G711_drvOpen((LPSTR)dwParam1); 01098 case DRV_CLOSE: return G711_drvClose(dwDevID); 01099 case DRV_ENABLE: return 1; 01100 case DRV_DISABLE: return 1; 01101 case DRV_QUERYCONFIGURE: return 1; 01102 case DRV_CONFIGURE: MessageBoxA(0, "MS G711 (a-Law & mu-Law) filter !", "Wine Driver", MB_OK); return 1; 01103 case DRV_INSTALL: return DRVCNF_RESTART; 01104 case DRV_REMOVE: return DRVCNF_RESTART; 01105 01106 case ACMDM_DRIVER_NOTIFY: 01107 /* no caching from other ACM drivers is done so far */ 01108 return MMSYSERR_NOERROR; 01109 01110 case ACMDM_DRIVER_DETAILS: 01111 return G711_DriverDetails((PACMDRIVERDETAILSW)dwParam1); 01112 01113 case ACMDM_FORMATTAG_DETAILS: 01114 return G711_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2); 01115 01116 case ACMDM_FORMAT_DETAILS: 01117 return G711_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2); 01118 01119 case ACMDM_FORMAT_SUGGEST: 01120 return G711_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1); 01121 01122 case ACMDM_STREAM_OPEN: 01123 return G711_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1); 01124 01125 case ACMDM_STREAM_CLOSE: 01126 return G711_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1); 01127 01128 case ACMDM_STREAM_SIZE: 01129 return G711_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2); 01130 01131 case ACMDM_STREAM_CONVERT: 01132 return G711_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2); 01133 01134 case ACMDM_HARDWARE_WAVE_CAPS_INPUT: 01135 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT: 01136 /* this converter is not a hardware driver */ 01137 case ACMDM_FILTERTAG_DETAILS: 01138 case ACMDM_FILTER_DETAILS: 01139 /* this converter is not a filter */ 01140 case ACMDM_STREAM_RESET: 01141 /* only needed for asynchronous driver... we aren't, so just say it */ 01142 return MMSYSERR_NOTSUPPORTED; 01143 case ACMDM_STREAM_PREPARE: 01144 case ACMDM_STREAM_UNPREPARE: 01145 /* nothing special to do here... so don't do anything */ 01146 return MMSYSERR_NOERROR; 01147 01148 default: 01149 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 01150 } 01151 } Generated on Sun May 27 2012 04:24:50 for ReactOS by
1.7.6.1
|