GARGLE.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:5k
源码类别:
Windows编程
开发平台:
Visual C++
- #include "fdfilter.h"
- #include "filter.h"
- CGargle::CGargle( int nFreq, int nChannels, int nBytesPerSample )
- {
- m_nPhase = 0;
- m_Shape = SHAPE_TRIANGLE;
- m_nGargleRate = 10;
- m_nBytesPerSample = nBytesPerSample;
- m_nSamplesPerSec = nFreq;
- m_nChannels = nChannels;
- }
- //Below resutls in cl error C2600 - the compiler
- //has already generated a default destructor due
- //to the abstract delcaration of the CGargle class
- //in FDFILTER.H
- //CGargle::~CGargle()
- // {
- // }
- // Copy the required information about the new format for the buffer
- HRESULT CGargle::SetFormat( PWAVEFORMATEX pwfx )
- {
- if( NULL == pwfx )
- return ResultFromScode( E_POINTER );
- m_nSamplesPerSec = pwfx->nSamplesPerSec;
- m_nChannels = pwfx->nChannels;
- m_nBytesPerSample = pwfx->wBitsPerSample / 8;
- return NOERROR;
- }
- //
- // MessItAbout
- //
- // Mess the sound about by modulating it with a waveform.
- // We know the frequency of the modulation (from the slider setting
- // which we were told through our internal interface, IGargle, and
- // which we stored in m_GargleRate). At the end of the call we
- // record what part of the waveform we finished at in m_Phase and
- // we resume at that point next time.
- // Uses and updates m_Phase
- // Uses m_SamplesPerSec, m_Channels, m_GargleRate, m_Shape
- //
- void CGargle::MessItAbout( PBYTE pbIn, DWORD cb, PBYTE pbOut )
- {
- // We know how many samples per sec and how
- // many channels so we can calculate the modulation period in samples.
- //
- int Period = (m_nSamplesPerSec * m_nChannels) / m_nGargleRate;
- while( cb > 0 ) {
- --cb;
- // If m_Shape is 0 (triangle) then we multiply by a triangular waveform
- // that runs 0..Period/2..0..Period/2..0... else by a square one that
- // is either 0 or Period/2 (same maximum as the triangle) or zero.
- //
- {
- // m_Phase is the number of samples from the start of the period.
- // We keep this running from one call to the next,
- // but if the period changes so as to make this more
- // than Period then we reset to 0 with a bang. This may cause
- // an audible click or pop (but, hey! it's only a sample!)
- //
- ++m_nPhase;
- if( m_nPhase > Period )
- m_nPhase = 0;
- int M = m_nPhase; // m is what we modulate with
- if( m_Shape == SHAPE_TRIANGLE ) { // Triangle
- if( M > Period / 2 )
- M = Period - M; // handle downslope
- } else if( m_Shape == SHAPE_TRIANGLE ) { // Square wave
- if( M <= Period / 2 )
- M = Period / 2;
- else M = 0;
- }
- if( m_nBytesPerSample == 1 ) {
- // 8 bit sound uses 0..255 representing -128..127
- // Any overflow, even by 1, would sound very bad.
- // so we clip paranoically after modulating.
- // I think it should never clip by more than 1
- //
- int i = *pbIn - 128; // sound sample, zero based
- i = (i * M * 2) / Period; // modulate
- if(i > 127) // clip
- i = 127;
- if(i < -128)
- i = -128;
- *pbOut = (unsigned char)(i + 128); // reset zero offset to 128
- } else if( m_nBytesPerSample == 2 ) {
- // 16 bit sound uses 16 bits properly (0 means 0)
- // We still clip paranoically
- //
- short int *psi = (short int *)pbOut;
- int i = *((short int *)pbIn); // in a register, we might hope
- i = (i*M*2)/Period; // modulate
- if(i > 32767)
- i = 32767; // clip
- if(i < -32768)
- i = -32768;
- *psi = (short)i;
- ++pbIn; // nudge it on another 8 bits here to get a 16 bit step
- ++pbOut;
- --cb; // and nudge the count too.
- } else {
- // DbgBreak("Too many bytes per sample");
- // just leave it alone!
- }
- }
- ++pbIn; // move on 8 bits to next sound sample
- ++pbOut;
- }
- } // MessItAbout
- //
- // Transform
- //
- //
- HRESULT CGargle::Transform( PBYTE pbIn, int cbWrite, PBYTE pbOut )
- {
- // Actually transform the data
- //
- if( m_nSamplesPerSec && m_nChannels && m_nBytesPerSample )
- MessItAbout( pbIn, cbWrite, pbOut );
- return NOERROR;
- } // Transform