home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / waveconv / pcm.c < prev    next >
C/C++ Source or Header  |  1992-09-29  |  5KB  |  190 lines

  1. /** pcm.c
  2.  *
  3.      Copyright (C) Microsoft Corp. 1991, 1992.  All rights reserved.
  4.  
  5.      You have a royalty-free right to use, modify, reproduce and 
  6.      distribute the Sample Files (and/or any modified version) in 
  7.      any way you find useful, provided that you agree that 
  8.      Microsoft has no warranty obligations or liability for any 
  9.      Sample Application Files which are modified. 
  10.      
  11.      If you did not get this from Microsoft Sources, then it may not be the
  12.      most current version.  This sample code in particular will be updated
  13.      and include more documentation.  
  14.  
  15.      Sources are:
  16.          The MM Sys File Transfer BBS: The phone number is 206 936-4082.
  17.     CompuServe: WINSDK forum, MDK section.
  18.     Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
  19.  
  20.     
  21. */
  22.  
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <mmsystem.h>
  28. #include <mmreg.h>
  29. #include "pcm.h"
  30.  
  31.  
  32. #define MAX_CHANNELS    2
  33.  
  34. /*
  35.  
  36. WARNING:
  37.     This function is completely UNTESTED!!!!  Beware.
  38.  
  39.  */
  40.  
  41. DWORD PCMAPI pcmtopcm(LPPCMWAVEFORMAT lpwfPCMSrc, HPSTR hpSrc, LPPCMWAVEFORMAT lpwfPCMDst, HPSTR hpDst, DWORD dwSrcLen)
  42. {
  43.     DWORD   dwTotalPos;
  44.     DWORD   dwTotalDst;
  45.     BYTE    bSrcChannels;
  46.     BYTE    bDstChannels;
  47.     DWORD   dwSrcSampleRate;
  48.     DWORD   dwDstSampleRate;
  49.     WORD    wSrcBPS;    // Bits Per Sample
  50.     WORD    wDstBPS;
  51.     short   newSample16[MAX_CHANNELS];
  52.     BYTE    newSample8[MAX_CHANNELS];
  53.     WORD    wDecimationFactor;
  54.     WORD    wInterpFactor;
  55.     
  56.     BOOL    fBPSUP=FALSE;    // convert BPS up
  57.     BOOL    fBPSDOWN=FALSE;    // convert BPS down
  58.     BYTE    m;
  59.     WORD    w;
  60.     
  61.  
  62.     bSrcChannels=(BYTE)lpwfPCMSrc->wf.nChannels;
  63.     bDstChannels=(BYTE)lpwfPCMDst->wf.nChannels;
  64.  
  65.  
  66.     dwSrcSampleRate=lpwfPCMSrc->wf.nSamplesPerSec;
  67.     dwDstSampleRate=lpwfPCMDst->wf.nSamplesPerSec;
  68.  
  69.     if(dwSrcSampleRate<dwDstSampleRate)
  70.     {
  71.     wDecimationFactor=(WORD)(dwDstSampleRate/dwSrcSampleRate);
  72.     }
  73.     else if(dwDstSampleRate<dwSrcSampleRate)
  74.     wInterpFactor=(WORD)(dwSrcSampleRate/dwDstSampleRate);
  75.     else
  76.     wInterpFactor=1;
  77.     
  78.  
  79.     wSrcBPS=lpwfPCMSrc->wBitsPerSample;
  80.     wDstBPS=lpwfPCMDst->wBitsPerSample;
  81.  
  82.     if(wSrcBPS<=8 && wDstBPS>8)
  83.     fBPSUP=TRUE;
  84.     if(wSrcBPS>8 && wDstBPS<=8)
  85.     fBPSDOWN=TRUE;
  86.  
  87.     dwTotalPos=dwTotalDst=0;
  88.     
  89.     //
  90.     //  step through each sample of PCM data and decode it to the requested
  91.     //  PCM format (8 or 16 bit, mono/stereo, and sample rate).
  92.     //
  93.     while (dwTotalPos < dwSrcLen)
  94.     {
  95.     if(wDecimationFactor)
  96.     {
  97.         // skip 
  98.         if(wSrcBPS<=8)
  99.         {
  100.         hpSrc+=wDecimationFactor;
  101.         dwTotalPos+=wDecimationFactor;
  102.         }
  103.         else
  104.         {
  105.         hpSrc+=2*wDecimationFactor;
  106.         dwTotalPos+=2*wDecimationFactor;
  107.         }
  108.     }
  109.         for (m = 0; m < bSrcChannels; m++)
  110.         {
  111.         if(fBPSUP)
  112.         {
  113.         newSample16[m]=(*hpSrc++ << 8 ) ^ 0x8000;
  114.         dwTotalPos++;
  115.         }
  116.         else if(fBPSDOWN)
  117.         {
  118.         newSample8[m]=(BYTE)((*(short far *)hpSrc ^0x8000) + 0x0080) >> 8;
  119.         dwTotalPos+=2;
  120.         hpSrc+=2;
  121.         }
  122.         else if(wSrcBPS<=8)
  123.         {
  124.         newSample8[m]=*hpSrc++;
  125.         dwTotalPos++;
  126.         }
  127.         else
  128.         {
  129.         newSample16[m]=*(short far*)hpSrc;
  130.         dwTotalPos+=2;
  131.         hpSrc+=2;
  132.         }
  133.         }
  134.  
  135.  
  136.     for(w=0; w < wInterpFactor; w++)
  137.     {
  138.         for (m = 0; m < bDstChannels; m++)
  139.         {
  140.         if(fBPSDOWN || wDstBPS<=8)
  141.         {
  142.             *hpDst++=newSample8[bSrcChannels<bDstChannels ? (bSrcChannels-1) : m];
  143.             dwTotalDst++;
  144.         }
  145.         else
  146.         {
  147.             *(short far *)hpDst=newSample16[ bSrcChannels<bDstChannels ? (bSrcChannels-1) : m];
  148.             dwTotalDst+=2;
  149.             hpDst+=2;
  150.         }
  151.         }
  152.     
  153.     }
  154.     }
  155.  
  156.     return (dwTotalDst);
  157. }
  158.  
  159. //---------------------------------------------------------------------------
  160. //
  161. //  the code below provides 'support' routines for building/verifying PCM
  162. //  headers, etc.
  163. //
  164. //---------------------------------------------------------------------------
  165.  
  166. BOOL PCMAPI pcmIsValidFormat(LPWAVEFORMATEX lpwfx)
  167. {
  168.     if (!lpwfx)
  169.         return (FALSE);
  170.  
  171.     if (lpwfx->wFormatTag != WAVE_FORMAT_PCM)
  172.         return (FALSE);
  173.  
  174.     if ((lpwfx->wBitsPerSample != 8) && (lpwfx->wBitsPerSample != 16))
  175.         return (FALSE);
  176.  
  177.     if ((lpwfx->nChannels < 1) || (lpwfx->nChannels > MAX_CHANNELS))
  178.         return (FALSE);
  179.  
  180.     if((lpwfx->nSamplesPerSec != 44100) &&
  181.        (lpwfx->nSamplesPerSec != 22050) &&
  182.        (lpwfx->nSamplesPerSec != 11025)     )
  183.     return (FALSE);
  184.     
  185.     return (TRUE);
  186. } /* pcmIsValidFormat() */
  187.  
  188.  
  189. /** EOF: pcm.c **/
  190.