home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
- //
- // synth.cpp
- //
- // Audio Signal Generator Source Filter
-
-
- #include <windows.h>
- #include <streams.h>
- #include <math.h>
-
- #include <initguid.h>
- #include <olectl.h>
- #include <olectlid.h>
-
- #define _AUDIOSYNTH_IMPLEMENTATION_
-
- #include "isynth.h"
- #include "synth.h"
- #include "synthprp.h"
-
- // setup data
-
- AMOVIESETUP_MEDIATYPE sudOpPinTypes = { &MEDIATYPE_Audio // clsMajorType
- , &MEDIASUBTYPE_NULL }; // clsMinorType
-
- AMOVIESETUP_PIN sudOpPin = { L"Output" // strName
- , FALSE // bRendered
- , TRUE // bOutput
- , FALSE // bZero
- , FALSE // bMany
- , &CLSID_NULL // clsConnectsToFilter
- , L"Input" // strConnectsToPin
- , 1 // nTypes
- , &sudOpPinTypes }; // lpTypes
-
- AMOVIESETUP_FILTER sudSynth = { &CLSID_SynthFilter // clsID
- , L"Audio Synthesizer" // strName
- , MERIT_UNLIKELY // dwMerit
- , 1 // nPins
- , &sudOpPin }; // lpPin
-
- // -------------------------------------------------------------------------
- // g_Templates
- // -------------------------------------------------------------------------
- // COM global table of objects in this dll
-
- CFactoryTemplate g_Templates[2] = {
-
- {L"Audio Synthesizer", &CLSID_SynthFilter, CSynthFilter::CreateInstance},
- {L"Audio Synthesizer Property Page", &CLSID_SynthPropertyPage, CSynthProperties::CreateInstance}
-
- };
- int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
-
- // -------------------------------------------------------------------------
- // CSynthFilter, the main filter object
- // -------------------------------------------------------------------------
- //
- // CreateInstance
- //
- // The only allowed way to create Synthesizers
-
- CUnknown *CSynthFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr) {
-
- CUnknown *punk = new CSynthFilter(lpunk, phr);
- if (punk == NULL) {
- *phr = E_OUTOFMEMORY;
- }
-
- return punk;
- }
-
- //
- // GetSetupData
- //
- LPAMOVIESETUP_FILTER CSynthFilter::GetSetupData()
- {
- return &sudSynth;
- }
-
- //
- // CSynthFilter::Constructor
- //
- // initialise a CSynthStream object so that we have a pin.
-
- CSynthFilter::CSynthFilter(LPUNKNOWN lpunk, HRESULT *phr)
- : CSource(NAME("Audio Synthesizer Filter"),lpunk, CLSID_SynthFilter, phr)
- , CPersistStream(lpunk, phr)
- , m_hWndPropertyPage (NULL)
- {
- CAutoLock l(&m_cStateLock);
-
- m_paStreams = (CSourceStream **) new CSynthStream*[1];
- if (m_paStreams == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
-
- m_paStreams[0] = new CSynthStream(phr, this, L"Audio Synth Stream");
- if (m_paStreams[0] == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
- }
-
- //
- // CSynthFilter::Destructor
- //
- CSynthFilter::~CSynthFilter(void) {
-
- //
- // Base class will free our pins
- //
- }
-
- //
- // NonDelegatingQueryInterface
- //
- // Reveal our property page, persistance, and control interfaces
-
- STDMETHODIMP CSynthFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
-
- CAutoLock l(&m_cStateLock);
-
- if (riid == IID_ISynth) {
- return GetInterface((ISynth *) this, ppv);
- }
- else if (riid == IID_IPersistStream) {
- return GetInterface((IPersistStream *) this, ppv);
- }
- else if (riid == IID_ISpecifyPropertyPages) {
- return GetInterface((ISpecifyPropertyPages *) this, ppv);
- } else {
- return CSource::NonDelegatingQueryInterface(riid, ppv);
- }
- }
-
-
- //
- // GetPages
- //
- STDMETHODIMP CSynthFilter::GetPages(CAUUID * pPages) {
-
- CAutoLock l(&m_cStateLock);
-
- pPages->cElems = 1;
- pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
- if (pPages->pElems == NULL) {
- return E_OUTOFMEMORY;
- }
- *(pPages->pElems) = CLSID_SynthPropertyPage;
-
- return NOERROR;
-
- }
-
- // -------------------------------------------------------------------------
- // --- IPersistStream ---
- // -------------------------------------------------------------------------
-
- #define WRITEOUT(var) hr = pStream->Write(&var, sizeof(var), NULL); \
- if (FAILED(hr)) return hr;
-
- #define READIN(var) hr = pStream->Read(&var, sizeof(var), NULL); \
- if (FAILED(hr)) return hr;
-
- STDMETHODIMP CSynthFilter::GetClassID(CLSID *pClsid)
- {
- *pClsid = CLSID_SynthFilter;
- return NOERROR;
- }
-
- int CSynthFilter::SizeMax ()
- {
- return sizeof (int) * 8;
- }
-
- HRESULT CSynthFilter::WriteToStream(IStream *pStream)
- {
- HRESULT hr;
- int i, k;
-
- get_Frequency (&i); // don't we wish we'd used a structure, now?
- WRITEOUT(i);
- get_Waveform (&i);
- WRITEOUT(i);
- get_Channels (&i);
- WRITEOUT(i);
- get_BitsPerSample (&i);
- WRITEOUT(i);
- get_SamplesPerSec (&i);
- WRITEOUT(i);
- get_Amplitude (&i);
- WRITEOUT(i);
- get_SweepRange (&i, &k);
- WRITEOUT(i);
- WRITEOUT(k);
-
- return hr;
- }
-
-
- HRESULT CSynthFilter::ReadFromStream(IStream *pStream)
- {
- HRESULT hr;
- int i, k;
-
- READIN(i);
- put_Frequency(i);
- READIN(i);
- put_Waveform (i);
- READIN(i);
- put_Channels (i);
- READIN(i);
- put_BitsPerSample (i);
- READIN(i);
- put_SamplesPerSec (i);
- READIN(i);
- put_Amplitude (i);
- READIN(i);
- READIN(k);
- put_SweepRange (i, k);
-
- return hr;
- }
-
- // -------------------------------------------------------------------------
- // ISynth, the control interface for the synthesizer
- // -------------------------------------------------------------------------
-
- //
- // get_Frequency
- //
- STDMETHODIMP CSynthFilter::get_Frequency(int *Frequency) {
-
- m_Synth->get_Frequency(Frequency);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Frequency: %d"), *Frequency));
-
- return NOERROR;
- }
-
-
- //
- // put_Frequency
- //
- STDMETHODIMP CSynthFilter::put_Frequency(int Frequency) {
-
- m_Synth->put_Frequency (Frequency);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Frequency: %d"), Frequency));
-
- return NOERROR;
- }
-
- //
- // get_Waveform
- //
- STDMETHODIMP CSynthFilter::get_Waveform(int *Waveform) {
-
- m_Synth->get_Waveform (Waveform);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Waveform: %d"), *Waveform));
-
- return NOERROR;
- }
-
-
- //
- // put_Waveform
- //
- STDMETHODIMP CSynthFilter::put_Waveform(int Waveform) {
-
- m_Synth->put_Waveform (Waveform);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Waveform: %d"), Waveform));
-
- return NOERROR;
- }
-
- //
- // get_Channels
- //
- STDMETHODIMP CSynthFilter::get_Channels(int *Channels) {
-
- m_Synth->get_Channels (Channels);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Channels: %d"), *Channels));
-
- return NOERROR;
- }
-
- //
- // If the format changes, we need to reconnect
- //
- void CSynthFilter::ReconnectWithNewFormat(void) {
-
- // CAutoLock l(&m_SynthLock);
-
- HRESULT hr;
- IMediaControl *pmc;
- FILTER_STATE State;
-
- if (!m_pGraph)
- return;
-
- hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pmc);
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE, 1, TEXT("Couldn't get IID_IMediaControl")));
- return;
- }
-
- // Get the state and confirm that the graph is stopped
- GetState (0, &State);
- if (State != State_Stopped)
- return;
-
- CBasePin *pPin = GetPin(0);
- hr = m_pGraph->Reconnect (pPin); // Renegotiate the format
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE, 1, TEXT("Reconnect")));
- return;
- }
-
- hr = pmc->Release();
- }
-
-
- //
- // put_Channels
- //
- STDMETHODIMP CSynthFilter::put_Channels(int Channels) {
-
- m_Synth->put_Channels (Channels);
-
- ReconnectWithNewFormat ();
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Channels: %d"), Channels));
-
- return NOERROR;
- }
-
- //
- // get_BitsPerSample
- //
- STDMETHODIMP CSynthFilter::get_BitsPerSample(int *BitsPerSample) {
-
- m_Synth->get_BitsPerSample (BitsPerSample);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_BitsPerSample: %d"), *BitsPerSample));
-
- return NOERROR;
- }
-
-
- //
- // put_BitsPerSample
- //
- STDMETHODIMP CSynthFilter::put_BitsPerSample(int BitsPerSample) {
-
- m_Synth->put_BitsPerSample (BitsPerSample);
-
- ReconnectWithNewFormat ();
-
- DbgLog((LOG_TRACE, 1, TEXT("put_BitsPerSample: %d"), BitsPerSample));
-
- return NOERROR;
- }
-
- //
- // get_SamplesPerSec
- //
- STDMETHODIMP CSynthFilter::get_SamplesPerSec(int *SamplesPerSec) {
-
- m_Synth->get_SamplesPerSec (SamplesPerSec);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_SamplesPerSec: %d"), *SamplesPerSec));
-
- return NOERROR;
- }
-
-
- //
- // put_SamplesPerSec
- //
- STDMETHODIMP CSynthFilter::put_SamplesPerSec(int SamplesPerSec) {
-
- m_Synth->put_SamplesPerSec (SamplesPerSec);
-
- ReconnectWithNewFormat ();
-
- DbgLog((LOG_TRACE, 1, TEXT("put_SamplesPerSec: %d"), SamplesPerSec));
-
- return NOERROR;
- }
-
- //
- // get_Amplitude
- //
- STDMETHODIMP CSynthFilter::get_Amplitude(int *Amplitude) {
-
- m_Synth->get_Amplitude (Amplitude);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Amplitude: %d"), *Amplitude));
-
- return NOERROR;
- }
-
-
- //
- // put_Amplitude
- //
- STDMETHODIMP CSynthFilter::put_Amplitude(int Amplitude) {
-
- m_Synth->put_Amplitude (Amplitude);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Amplitude: %d"), Amplitude));
-
- return NOERROR;
- }
-
-
- //
- // get_SweepRange
- //
- STDMETHODIMP CSynthFilter::get_SweepRange(int *SweepStart, int *SweepEnd) {
-
- m_Synth->get_SweepRange (SweepStart, SweepEnd);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_SweepStart: %d %d"), *SweepStart, *SweepEnd));
-
- return NOERROR;
- }
-
-
- //
- // put_SweepRange
- //
- STDMETHODIMP CSynthFilter::put_SweepRange(int SweepStart, int SweepEnd) {
-
- m_Synth->put_SweepRange (SweepStart, SweepEnd);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_SweepRange: %d %d"), SweepStart, SweepEnd));
-
- return NOERROR;
- }
-
-
- //
- // put_PropertyPagehWnd
- // Our property page passes it's hWnd on creation so we can notify it, via
- // a PostMessage, when it needs to disable the controls which affect the
- // format.
- STDMETHODIMP CSynthFilter::put_PropertyPagehWnd (HWND hWnd) {
-
- m_hWndPropertyPage = hWnd;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_PropertyPagehWnd: %d" ), hWnd));
-
- return NOERROR;
- }
-
- //
- // get_FilterIsStopped
- //
- // Our property page needs to know if the filter is stopped so it
- // can decide whether to enable format change buttons
- //
- STDMETHODIMP CSynthFilter::get_FilterIsStopped (BOOL *fStopped) {
-
- FILTER_STATE State;
-
- GetState (0, &State);
-
- *fStopped = (State == State_Stopped);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_FilterIsStopped: %d" ), *fStopped));
-
- return NOERROR;
- }
-
- // -------------------------------------------------------------------------
- // CSynthStream, the output pin
- // -------------------------------------------------------------------------
-
- //
- // CSynthStream::Constructor
- //
-
- CSynthStream::CSynthStream(HRESULT *phr, CSynthFilter *pParent, LPCWSTR pName)
- : CSourceStream(NAME("Audio Synth output pin"),phr, pParent, pName) {
-
- CAutoLock l(m_pFilter->pStateLock());
-
- {
- CAutoLock l(&m_cSharedState);
-
- m_Synth = new CAudioSynth( );
- pParent->m_Synth = m_Synth;
- if (m_Synth == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
- }
- }
-
-
- //
- // CSynthStream::Destructor
- //
- CSynthStream::~CSynthStream(void) {
-
- CAutoLock l(&m_cSharedState);
-
- delete m_Synth;
- }
-
-
- //
- // FillBuffer
- //
- // Stuffs the buffer with data
- HRESULT CSynthStream::FillBuffer(IMediaSample *pms) {
-
- BYTE *pData;
- long lDataLen;
- int nSamplesPerSec;
- int nBitsPerSample;
- int nChannels;
-
- pms->GetPointer(&pData);
- lDataLen = pms->GetSize();
-
- CAutoLock lShared(&m_cSharedState);
- m_Synth->FillAudioBuffer (pData, lDataLen);
-
- CRefTime rtStart = m_rtSampleTime; // the current time is the sample's start
-
- m_Synth->get_SamplesPerSec (&nSamplesPerSec);
- m_Synth->get_BitsPerSample (&nBitsPerSample);
- m_Synth->get_Channels (&nChannels);
-
- m_rtSampleTime += (long) (1000 * lDataLen /
- (nSamplesPerSec * nChannels * nBitsPerSample / 8));
-
- pms->SetTime((REFERENCE_TIME*)&rtStart,
- (REFERENCE_TIME*)&m_rtSampleTime);
-
- return NOERROR;
- }
-
-
- //
- // Format Support
- //
-
- //
- // GetMediaType
- //
- HRESULT CSynthStream::GetMediaType(CMediaType *pmt) {
-
- CAutoLock l(m_pFilter->pStateLock());
-
- WAVEFORMATEX *pwf = (WAVEFORMATEX *) pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX));
-
- pwf->wFormatTag = WAVE_FORMAT_PCM;
- int iV;
- m_Synth->get_Channels (&iV);
- pwf->nChannels = (WORD) iV;
- m_Synth->get_SamplesPerSec (&iV);
- pwf->nSamplesPerSec = (DWORD) iV;
- m_Synth->get_BitsPerSample (&iV);
- pwf->wBitsPerSample = (WORD) iV;
- pwf->nBlockAlign = pwf->wBitsPerSample * pwf->nChannels / 8;
- pwf->nAvgBytesPerSec = (int) ((DWORD) pwf->nBlockAlign *
- pwf->nSamplesPerSec);
- pwf->cbSize = 0;
-
- pmt->SetType(&MEDIATYPE_Audio);
- pmt->SetTemporalCompression(FALSE);
- pmt->SetSubtype(&GUID_NULL);
-
- return NOERROR;
- }
-
-
- //
- // CheckMediaType
- //
- // Returns E_INVALIDARG if the mediatype is not acceptable, S_OK if it is
- HRESULT CSynthStream::CheckMediaType(const CMediaType *pMediaType) {
-
- CAutoLock l(m_pFilter->pStateLock());
-
- if ( (*(pMediaType->Type()) != MEDIATYPE_Audio) // only output video!
- || (pMediaType->IsTemporalCompressed()) // ...in uncompressed form
- || !(pMediaType->IsFixedSize()) ) { // ...in fixed size samples
- return E_INVALIDARG;
- }
-
- // Check for the subtypes we support
-
- // Get the format area of the media type
-
- return S_OK; // This format is acceptable.
- }
-
- //
- // DecideBufferSize
- //
- // This will always be called after the format has been sucessfully
- // negotiated. So we have a look at m_mt to see what format we agreed to.
- // Then we can ask for buffers of the correct size to contain them.
- HRESULT CSynthStream::DecideBufferSize(IMemAllocator *pAlloc,
- ALLOCATOR_PROPERTIES *pProperties)
- {
- CAutoLock l(m_pFilter->pStateLock());
- ASSERT(pAlloc);
- ASSERT(pProperties);
- HRESULT hr = NOERROR;
-
- pProperties->cbBuffer = WaveBufferSize;
-
- int nBitsPerSample;
- int nSamplesPerSec;
- int nChannels;
-
- m_Synth->get_SamplesPerSec (&nSamplesPerSec);
- m_Synth->get_BitsPerSample (&nBitsPerSample);
- m_Synth->get_Channels (&nChannels);
-
- pProperties->cBuffers = nChannels * (nSamplesPerSec / pProperties->cbBuffer) * (nBitsPerSample / 8);
- // Get 1/2 second worth of buffers
- pProperties->cBuffers /= 2;
-
- // Ask the allocator to reserve us the memory
-
- ALLOCATOR_PROPERTIES Actual;
- hr = pAlloc->SetProperties(pProperties,&Actual);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Is this allocator unsuitable
-
- if (Actual.cbBuffer < pProperties->cbBuffer) {
- return E_FAIL;
- }
- return NOERROR;
- }
-
-
- //
- // SetMediaType
- //
- // Overriden from CBasePin.
- HRESULT CSynthStream::SetMediaType(const CMediaType *pMediaType) {
-
- CAutoLock l(m_pFilter->pStateLock());
-
- HRESULT hr; // return code from base class calls
-
- // Pass the call up to my base class
- hr = CSourceStream::SetMediaType(pMediaType);
- if (SUCCEEDED(hr))
- return NOERROR;
- else
- return hr;
-
- }
-
-
- //
- // OnThreadCreate
- //
- // as we go active reset the stream time to zero
- HRESULT CSynthStream::OnThreadCreate(void) {
-
- CAutoLock lShared(&m_cSharedState);
-
- m_rtSampleTime = 0;
-
- return NOERROR;
- }
-
- //
- // Active
- //
- // Send a message to the property page telling it to disable
- // buttons which change the format when the graph starts running
- HRESULT CSynthStream::Active (void) {
- PostMessage (((CSynthFilter *)m_pFilter)->m_hWndPropertyPage, WM_PROPERTYPAGE_ENABLE, 0, 0);
- return CSourceStream::Active();
- }
-
-
- //
- // Inactive
- //
- // Send a message to the property page telling it to enable
- // buttons which change the format when the graph stops running
- HRESULT CSynthStream::Inactive (void) {
- PostMessage (((CSynthFilter *)m_pFilter)->m_hWndPropertyPage, WM_PROPERTYPAGE_ENABLE, 0, 1);
- return CSourceStream::Inactive();
- }
-
- // -------------------------------------------------------------------------
- // CAudioSynth
- // -------------------------------------------------------------------------
- // Object that knows nothing about ActiveMovie, but just synthesizes
- // waveforms
-
- CAudioSynth::CAudioSynth(
- int Frequency,
- int Waveform,
- int iBitsPerSample,
- int iChannels,
- int iSamplesPerSec,
- int iAmplitude
- )
- : m_bWaveCache(NULL),
- m_wWaveCache(NULL)
- {
-
- ASSERT(Waveform >= WAVE_SINE);
- ASSERT(Waveform < WAVE_LAST);
-
- m_iFrequency = Frequency;
- m_iWaveform = Waveform;
- m_iAmplitude = iAmplitude;
- m_iSweepStart = DefaultSweepStart;
- m_iSweepEnd = DefaultSweepEnd;
-
- // init our WAVEFORMATEX structure
- wfex.wFormatTag = WAVE_FORMAT_PCM;
- wfex.wBitsPerSample = iBitsPerSample;
- wfex.nChannels = iChannels;
- wfex.nSamplesPerSec = iSamplesPerSec;
- wfex.nBlockAlign = wfex.wBitsPerSample * wfex.nChannels / 8;
- wfex.nAvgBytesPerSec = ((DWORD) wfex.nBlockAlign *
- wfex.nSamplesPerSec);
- wfex.cbSize = 0;
- }
-
- //
- // AllocWaveCache
- //
- //
- void CAudioSynth::AllocWaveCache (void) {
- m_iWaveCacheCycles = m_iFrequency;
- m_iWaveCacheSize = (int) wfex.nSamplesPerSec;
-
- if (m_bWaveCache) {
- delete [] m_bWaveCache;
- m_bWaveCache = NULL;
- }
- if (m_wWaveCache) {
- delete [] m_wWaveCache;
- m_wWaveCache = NULL;
- }
-
- if (wfex.wBitsPerSample == 8)
- m_bWaveCache = new BYTE [m_iWaveCacheSize];
- else
- m_wWaveCache = new WORD [m_iWaveCacheSize];
- }
-
- //
- // FillAudioBuffer
- //
- //
- //
- void CAudioSynth::FillAudioBuffer (BYTE pBuf[], int iSize) {
- BOOL fCalcCache = FALSE;
-
- CAutoLock l(&m_SynthLock);
-
- // Only realloc the cache if the format has changed !
-
- if ((wfex.nChannels != wfexLast.nChannels) ||
- (wfex.wBitsPerSample != wfexLast.wBitsPerSample) ||
- (wfex.nSamplesPerSec != wfexLast.nSamplesPerSec)) {
-
- fCalcCache = TRUE;
- AllocWaveCache();
- wfexLast = wfex;
- }
- if (m_iFrequency != m_iFrequencyLast) {
- fCalcCache = TRUE;
- m_iFrequencyLast = m_iFrequency;
- wfexLast = wfex;
- }
- if (m_iWaveform != m_iWaveformLast) {
- fCalcCache = TRUE;
- m_iWaveformLast = m_iWaveform;
- }
- if (m_iAmplitude != m_iAmplitudeLast) {
- fCalcCache = TRUE;
- m_iAmplitudeLast = m_iAmplitude;
- }
-
- if (fCalcCache) {
- switch (m_iWaveform) {
-
- case WAVE_SINE:
- CalcCacheSine ();
- break;
-
- case WAVE_SQUARE:
- CalcCacheSquare ();
- break;
-
- case WAVE_SAWTOOTH:
- CalcCacheSawtooth ();
- break;
-
- case WAVE_SINESWEEP:
- CalcCacheSweep ();
- break;
-
- }
- }
-
- // Copy cache to output buffers
- if (wfex.wBitsPerSample == 8 && wfex.nChannels == 1) {
- while (iSize--) {
- *pBuf++ = m_bWaveCache[m_iWaveCacheIndex++];
- if (m_iWaveCacheIndex >= m_iWaveCacheSize)
- m_iWaveCacheIndex = 0;
- }
- }
- else if (wfex.wBitsPerSample == 8 && wfex.nChannels == 2) {
- iSize /= 2;
- while (iSize--) {
- *pBuf++ = m_bWaveCache[m_iWaveCacheIndex];
- *pBuf++ = m_bWaveCache[m_iWaveCacheIndex++];
- if (m_iWaveCacheIndex >= m_iWaveCacheSize)
- m_iWaveCacheIndex = 0;
- }
- }
- else if (wfex.wBitsPerSample == 16 && wfex.nChannels == 1) {
- WORD * pW = (WORD *) pBuf;
- iSize /= 2;
- while (iSize--) {
- *pW++ = m_wWaveCache[m_iWaveCacheIndex++];
- if (m_iWaveCacheIndex >= m_iWaveCacheSize)
- m_iWaveCacheIndex = 0;
- }
- }
- else if (wfex.wBitsPerSample == 16 && wfex.nChannels == 2) {
- WORD * pW = (WORD *) pBuf;
- iSize /= 4;
- while (iSize--) {
- *pW++ = m_wWaveCache[m_iWaveCacheIndex];
- *pW++ = m_wWaveCache[m_iWaveCacheIndex++];
- if (m_iWaveCacheIndex >= m_iWaveCacheSize)
- m_iWaveCacheIndex = 0;
- }
- }
-
- }
-
- //
- // CalcCacheSine
- //
- //
- void CAudioSynth::CalcCacheSine (void) {
-
- int i;
- double d;
- double amplitude;
- double FTwoPIDivSpS;
-
- amplitude = ((wfex.wBitsPerSample == 8) ? 127 : 32767 )
- * m_iAmplitude / 100;
-
- FTwoPIDivSpS = m_iFrequency * TWOPI / wfex.nSamplesPerSec;
-
- m_iWaveCacheIndex = 0;
- m_iCurrentSample = 0;
-
- if (wfex.wBitsPerSample == 8) {
- BYTE * pB = m_bWaveCache;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- d = FTwoPIDivSpS * i;
- *pB++ = (BYTE) (sin (d) * amplitude) + 128;
- }
- }
- else {
- PWORD pW = (PWORD) m_wWaveCache;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- d = FTwoPIDivSpS * i;
- *pW++ = (WORD) (sin (d) * amplitude);
- }
- }
-
- }
-
- //
- // CalcCacheSquare
- //
- //
- void CAudioSynth::CalcCacheSquare (void) {
-
- int i;
- double d;
- double FTwoPIDivSpS;
- BYTE b0, b1;
- WORD w0, w1;
-
- b0 = (BYTE) 128 - (127 * m_iAmplitude / 100);
- b1 = (BYTE) 128 + (127 * m_iAmplitude / 100);
- w0 = (WORD) (32767. * m_iAmplitude / 100);
- w1 = (WORD) - (32767. * m_iAmplitude / 100);
-
- FTwoPIDivSpS = m_iFrequency * TWOPI / wfex.nSamplesPerSec;
-
- m_iWaveCacheIndex = 0;
- m_iCurrentSample = 0;
-
- if (wfex.wBitsPerSample == 8) {
- BYTE * pB = m_bWaveCache;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- d = FTwoPIDivSpS * i;
- *pB++ = (BYTE) ((sin (d) >= 0) ? b1 : b0);
- }
- }
- else {
- PWORD pW = (PWORD) m_wWaveCache;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- d = FTwoPIDivSpS * i;
- *pW++ = (WORD) ((sin (d) >= 0) ? w1 : w0);
- }
- }
- }
-
- //
- // CalcCacheSawtooth
- //
- void CAudioSynth::CalcCacheSawtooth (void) {
-
- int i;
- double d;
- double amplitude;
- double FTwoPIDivSpS;
- double step;
- double curstep;
- BOOL fLastWasNeg = TRUE;
- BOOL fPositive;
-
- amplitude = ((wfex.wBitsPerSample == 8) ? 255 : 65535 )
- * m_iAmplitude / 100;
-
- FTwoPIDivSpS = m_iFrequency * TWOPI / wfex.nSamplesPerSec;
- step = amplitude * m_iFrequency / wfex.nSamplesPerSec;
-
- m_iWaveCacheIndex = 0;
- m_iCurrentSample = 0;
-
- BYTE * pB = m_bWaveCache;
- PWORD pW = (PWORD) m_wWaveCache;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- d = FTwoPIDivSpS * i;
-
- // OneShot triggered on positive zero crossing
- fPositive = (sin (d) >= 0);
-
- if (fLastWasNeg && fPositive) {
- if (wfex.wBitsPerSample == 8)
- curstep = 128 - amplitude / 2;
- else
- curstep = 32768 - amplitude / 2;
- }
- fLastWasNeg = !fPositive;
-
- if (wfex.wBitsPerSample == 8)
- *pB++ = (BYTE) curstep;
- else
- *pW++ = (WORD) (-32767 + curstep);
-
- curstep += step;
- }
- }
-
- //
- // CalcCacheSweep
- //
- void CAudioSynth::CalcCacheSweep (void) {
-
- int i;
- double d;
- double amplitude;
- double FTwoPIDivSpS;
- double CurrentFreq;
- double DeltaFreq;
-
- amplitude = ((wfex.wBitsPerSample == 8) ? 127 : 32767 )
- * m_iAmplitude / 100;
-
- DeltaFreq = ((double) m_iSweepEnd - m_iSweepStart) / m_iWaveCacheSize;
- CurrentFreq = m_iSweepStart;
-
- m_iWaveCacheIndex = 0;
- m_iCurrentSample = 0;
-
- if (wfex.wBitsPerSample == 8) {
- BYTE * pB = m_bWaveCache;
- d = 0.0;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- FTwoPIDivSpS = (int) CurrentFreq * TWOPI / wfex.nSamplesPerSec;
- CurrentFreq += DeltaFreq;
- d += FTwoPIDivSpS;
- *pB++ = (BYTE) (sin (d) * amplitude) + 128;
- }
- }
- else {
- PWORD pW = (PWORD) m_wWaveCache;
- d = 0.0;
-
- for (i = 0; i < m_iWaveCacheSize; i++) {
- FTwoPIDivSpS = (int) CurrentFreq * TWOPI / wfex.nSamplesPerSec;
- CurrentFreq += DeltaFreq;
- d += FTwoPIDivSpS;
- *pW++ = (WORD) (sin (d) * amplitude);
- }
- }
- }
-
- //
- // get_Frequency
- //
- STDMETHODIMP CAudioSynth::get_Frequency(int *Frequency) {
-
- *Frequency = m_iFrequency;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Frequency: %d"), *Frequency));
-
- return NOERROR;
- }
-
-
- //
- // put_Frequency
- //
- STDMETHODIMP CAudioSynth::put_Frequency(int Frequency) {
-
- CAutoLock l(&m_SynthLock);
-
- m_iFrequency = Frequency;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Frequency: %d"), Frequency));
-
- return NOERROR;
- }
-
- //
- // get_Waveform
- //
- STDMETHODIMP CAudioSynth::get_Waveform(int *Waveform) {
-
- *Waveform = m_iWaveform;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Waveform: %d"), *Waveform));
-
- return NOERROR;
- }
-
-
- //
- // put_Waveform
- //
- STDMETHODIMP CAudioSynth::put_Waveform(int Waveform) {
-
- CAutoLock l(&m_SynthLock);
-
- m_iWaveform = Waveform;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Waveform: %d"), Waveform));
-
- return NOERROR;
- }
-
- //
- // get_Channels
- //
- STDMETHODIMP CAudioSynth::get_Channels(int *Channels) {
-
- *Channels = wfex.nChannels;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Channels: %d"), *Channels));
-
- return NOERROR;
- }
-
-
- //
- // put_Channels
- //
- STDMETHODIMP CAudioSynth::put_Channels(int Channels) {
-
- CAutoLock l(&m_SynthLock);
-
- wfex.nChannels = Channels;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Channels: %d"), Channels));
-
- return NOERROR;
- }
-
- //
- // get_BitsPerSample
- //
- STDMETHODIMP CAudioSynth::get_BitsPerSample(int *BitsPerSample) {
-
- *BitsPerSample = wfex.wBitsPerSample;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_BitsPerSample: %d"), *BitsPerSample));
-
- return NOERROR;
- }
-
-
- //
- // put_BitsPerSample
- //
- STDMETHODIMP CAudioSynth::put_BitsPerSample(int BitsPerSample) {
-
- CAutoLock l(&m_SynthLock);
-
- wfex.wBitsPerSample = BitsPerSample;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_BitsPerSample: %d"), BitsPerSample));
-
- return NOERROR;
- }
-
- //
- // get_SamplesPerSec
- //
- STDMETHODIMP CAudioSynth::get_SamplesPerSec(int *SamplesPerSec) {
-
- *SamplesPerSec = wfex.nSamplesPerSec;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_SamplesPerSec: %d"), *SamplesPerSec));
-
- return NOERROR;
- }
-
-
- //
- // put_SamplesPerSec
- //
- STDMETHODIMP CAudioSynth::put_SamplesPerSec(int SamplesPerSec) {
-
- CAutoLock l(&m_SynthLock);
-
- wfex.nSamplesPerSec = SamplesPerSec;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_SamplesPerSec: %d"), SamplesPerSec));
-
- return NOERROR;
- }
-
- //
- // get_Amplitude
- //
- STDMETHODIMP CAudioSynth::get_Amplitude(int *Amplitude) {
-
- *Amplitude = m_iAmplitude;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_Amplitude: %d"), *Amplitude));
-
- return NOERROR;
- }
-
-
- //
- // put_Amplitude
- //
- STDMETHODIMP CAudioSynth::put_Amplitude(int Amplitude) {
-
- CAutoLock l(&m_SynthLock);
-
- if (Amplitude > MaxAmplitude || Amplitude < MinAmplitude)
- return E_INVALIDARG;
-
- m_iAmplitude = Amplitude;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_Amplitude: %d"), Amplitude));
-
- return NOERROR;
- }
-
-
- //
- // get_SweepRange
- //
- STDMETHODIMP CAudioSynth::get_SweepRange(int *SweepStart, int *SweepEnd) {
-
- *SweepStart = m_iSweepStart;
- *SweepEnd = m_iSweepEnd;
-
- DbgLog((LOG_TRACE, 1, TEXT("get_SweepStart: %d %d"), *SweepStart, *SweepEnd));
-
- return NOERROR;
- }
-
-
- //
- // put_SweepRange
- //
- STDMETHODIMP CAudioSynth::put_SweepRange(int SweepStart, int SweepEnd) {
-
- CAutoLock l(&m_SynthLock);
-
- m_iSweepStart = SweepStart;
- m_iSweepEnd = SweepEnd;
-
- DbgLog((LOG_TRACE, 1, TEXT("put_SweepRange: %d %d"), SweepStart, SweepEnd));
-
- return NOERROR;
- }
-
- /******************************Public*Routine******************************\
- * exported entry points for registration and
- * unregistration (in this case they only call
- * through to default implmentations).
- *
- *
- *
- * History:
- *
- \**************************************************************************/
- HRESULT
- DllRegisterServer()
- {
- return AMovieDllRegisterServer();
- }
-
- HRESULT
- DllUnregisterServer()
- {
- return AMovieDllUnregisterServer();
- }
-
-