GARGLE.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:5k
源码类别:

Windows编程

开发平台:

Visual C++

  1. #include "fdfilter.h"
  2. #include "filter.h"
  3. CGargle::CGargle( int nFreq, int nChannels, int nBytesPerSample )
  4.     {
  5.     m_nPhase = 0;
  6.     m_Shape = SHAPE_TRIANGLE;
  7.     m_nGargleRate = 10;
  8.     m_nBytesPerSample = nBytesPerSample;
  9.     m_nSamplesPerSec = nFreq;
  10.     m_nChannels = nChannels;
  11.     }
  12. //Below resutls in cl error C2600 - the compiler
  13. //has already generated a default destructor due
  14. //to the abstract delcaration of the CGargle class
  15. //in FDFILTER.H
  16. //CGargle::~CGargle()
  17. //    {
  18. //    }
  19. // Copy the required information about the new format for the buffer
  20. HRESULT CGargle::SetFormat( PWAVEFORMATEX pwfx )
  21.     {
  22.     if( NULL == pwfx )
  23.         return ResultFromScode( E_POINTER );
  24.     m_nSamplesPerSec = pwfx->nSamplesPerSec;
  25.     m_nChannels = pwfx->nChannels;
  26.     m_nBytesPerSample = pwfx->wBitsPerSample / 8;
  27.     return NOERROR;    
  28.     }
  29. //
  30. // MessItAbout
  31. //
  32. // Mess the sound about by modulating it with a waveform.
  33. // We know the frequency of the modulation (from the slider setting
  34. // which we were told through our internal interface, IGargle, and
  35. // which we stored in m_GargleRate).  At the end of the call we
  36. // record what part of the waveform we finished at in m_Phase and
  37. // we resume at that point next time.
  38. // Uses and updates m_Phase
  39. // Uses m_SamplesPerSec, m_Channels, m_GargleRate, m_Shape
  40. //
  41. void CGargle::MessItAbout( PBYTE pbIn, DWORD cb, PBYTE pbOut )
  42. {
  43.     // We know how many samples per sec and how
  44.     // many channels so we can calculate the modulation period in samples.
  45.     //
  46.     int Period = (m_nSamplesPerSec * m_nChannels) / m_nGargleRate;
  47.     while( cb > 0 ) {
  48.         --cb;
  49.         // If m_Shape is 0 (triangle) then we multiply by a triangular waveform
  50.         // that runs 0..Period/2..0..Period/2..0... else by a square one that
  51.         // is either 0 or Period/2 (same maximum as the triangle) or zero.
  52.         //
  53.         {
  54.             // m_Phase is the number of samples from the start of the period.
  55.             // We keep this running from one call to the next,
  56.             // but if the period changes so as to make this more
  57.             // than Period then we reset to 0 with a bang.  This may cause
  58.             // an audible click or pop (but, hey! it's only a sample!)
  59.             //
  60.             ++m_nPhase;
  61.             if( m_nPhase > Period )
  62.                 m_nPhase = 0;
  63.             int M = m_nPhase;      // m is what we modulate with
  64.             if( m_Shape == SHAPE_TRIANGLE ) {   // Triangle
  65.                 if( M > Period / 2 )
  66.                     M = Period - M;  // handle downslope
  67.             } else if( m_Shape == SHAPE_TRIANGLE ) {             // Square wave
  68.                 if( M <= Period / 2 )
  69.                     M = Period / 2;
  70.                 else M = 0;
  71.             }
  72.             if( m_nBytesPerSample == 1 ) {
  73.                 // 8 bit sound uses 0..255 representing -128..127
  74.                 // Any overflow, even by 1, would sound very bad.
  75.                 // so we clip paranoically after modulating.
  76.                 // I think it should never clip by more than 1
  77.                 //
  78.                 int i = *pbIn - 128;            // sound sample, zero based
  79.                 i = (i * M * 2) / Period;       // modulate
  80.                 if(i > 127)                     // clip
  81.                     i = 127;
  82.                 if(i < -128)
  83.                     i = -128;
  84.                *pbOut = (unsigned char)(i + 128);       // reset zero offset to 128
  85.             } else if( m_nBytesPerSample == 2 ) {
  86.                 // 16 bit sound uses 16 bits properly (0 means 0)
  87.                 // We still clip paranoically
  88.                 //
  89.                 short int *psi = (short int *)pbOut;
  90.                 int i = *((short int *)pbIn);   // in a register, we might hope
  91.                 i = (i*M*2)/Period;     // modulate
  92.                 if(i > 32767)
  93.                     i = 32767;          // clip
  94.                 if(i < -32768)
  95.                     i = -32768;
  96.                 *psi = (short)i;
  97.                 ++pbIn; // nudge it on another 8 bits here to get a 16 bit step
  98.                 ++pbOut;
  99.                 --cb;   // and nudge the count too.
  100.             } else {
  101. //               DbgBreak("Too many bytes per sample");
  102.                // just leave it alone!
  103.             }
  104.         }
  105.         ++pbIn;   // move on 8 bits to next sound sample
  106.         ++pbOut;
  107.     }
  108. } // MessItAbout
  109. //
  110. // Transform
  111. //
  112. //
  113. HRESULT CGargle::Transform( PBYTE pbIn, int cbWrite, PBYTE pbOut )
  114. {
  115.     // Actually transform the data
  116.     //
  117.     if( m_nSamplesPerSec && m_nChannels && m_nBytesPerSample )
  118.         MessItAbout( pbIn, cbWrite, pbOut );
  119.     return NOERROR;
  120. } // Transform