ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

msg711.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.