SYNTH.H

//==========================================================================; 
//
// 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 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// synth.h
//
// Audio Signal Generator

#ifndef __AUDIOSYNTH__
#define __AUDIOSYNTH__

//CLSID_SynthFilter
//{79A98DE0-BC00-11ce-AC2E-444553540000}
DEFINE_GUID(CLSID_SynthFilter,
0x79a98de0, 0xbc00, 0x11ce, 0xac, 0x2e, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);

//CLSID_SynthFilterPropertyPage
//{79A98DE1-BC00-11ce-AC2E-444553540000}
DEFINE_GUID(CLSID_SynthPropertyPage,
0x79a98de1, 0xbc00, 0x11ce, 0xac, 0x2e, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);

const double TWOPI = 6.283185308;
const int MaxFrequency = 20000;
const int MinFrequency = 0;
const int DefaultFrequency = 440; // A-440
const int MaxAmplitude = 100;
const int MinAmplitude = 0;
const int DefaultSweepStart = DefaultFrequency;
const int DefaultSweepEnd = 5000;
const int WaveBufferSize = 16*1024; // Size of each allocated buffer
// Originally used to be 2K, but at
// 44khz/16bit/stereo you would get
// audio breaks with a transform in the
// middle.

enum Waveforms {
WAVE_SINE = 0,
WAVE_SQUARE,
WAVE_SAWTOOTH,
WAVE_SINESWEEP,
WAVE_LAST // Always keep this guy last
};

#define WM_PROPERTYPAGE_ENABLE (WM_USER + 100)

// below stuff is implementation-only....
#ifdef _AUDIOSYNTH_IMPLEMENTATION_

class CSynthStream;

// -------------------------------------------------------------------------
// CAudioSynth
// -------------------------------------------------------------------------

class CAudioSynth {

public:

CAudioSynth(
int Frequency = DefaultFrequency,
int Waveform = WAVE_SINE,
int iBitsPerSample = 8,
int iChannels = 1,
int iSamplesPerSec = 11025,
int iAmplitude = 100
);

~CAudioSynth();

// Load the buffer with the current waveform
void FillAudioBuffer (BYTE pBuf[], int iSize, BOOL * fNewFormat);

// Set the "current" format and allocate temporary memory
void AllocWaveCache (void) ;

STDMETHODIMP get_Frequency(int *Frequency);
STDMETHODIMP put_Frequency(int Frequency);
STDMETHODIMP get_Waveform(int *Waveform);
STDMETHODIMP put_Waveform(int Waveform);
STDMETHODIMP get_Channels(int *Channels);
STDMETHODIMP get_BitsPerSample(int *BitsPerSample);
STDMETHODIMP get_SamplesPerSec(int *SamplesPerSec);
STDMETHODIMP put_SynthFormat(int Channels, int BitsPerSample, int SamplesPerSec);
STDMETHODIMP get_Amplitude(int *Amplitude);
STDMETHODIMP put_Amplitude(int Amplitude);
STDMETHODIMP get_SweepRange(int *SweepStart, int *SweepEnd);
STDMETHODIMP put_SweepRange(int SweepStart, int SweepEnd);

private:
CCritSec m_SynthLock;

WAVEFORMATEX wfex; // the current format
WAVEFORMATEX wfexLast; // last known waveformat

int m_iWaveform; // WAVE_SINE ...
int m_iFrequency; // if not using sweep, this is the frequency
int m_iAmplitude; // 0 to 100

int m_iWaveformLast; // keep track of the last known format
int m_iFrequencyLast; // so we can flush the cache if necessary
int m_iAmplitudeLast;

int m_iCurrentSample; // 0 to iSamplesPerSec-1
BYTE * m_bWaveCache; // Wave Cache as BYTEs
WORD * m_wWaveCache; // Wave Cache as WORDs
int m_iWaveCacheSize; // how big is the cache?
int m_iWaveCacheCycles; // how many cycles are in the cache
int m_iWaveCacheIndex;

int m_iSweepStart; // start of sweep
int m_iSweepEnd; // end of sweep
// double m_SweepDuration; // how long the sweep lasts

void CalcCacheSine (void) ;
void CalcCacheSquare (void) ;
void CalcCacheSawtooth (void) ;
void CalcCacheSweep (void) ;

};



// -------------------------------------------------------------------------
// CSynthFilter
// -------------------------------------------------------------------------
// CSynthFilter manages filter level stuff

class CSynthFilter : public ISynth,
public CPersistStream,
public ISpecifyPropertyPages,
public CSource {

public:

static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
~CSynthFilter();

DECLARE_IUNKNOWN;

// override this to reveal our property interface
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);

// --- ISpecifyPropertyPages ---

// return our property pages
STDMETHODIMP GetPages(CAUUID * pPages);

// --- IPersistStream Interface

STDMETHODIMP GetClassID(CLSID *pClsid);
int SizeMax();
HRESULT WriteToStream(IStream *pStream);
HRESULT ReadFromStream(IStream *pStream);

//
// --- ISynth ---
//

STDMETHODIMP get_Frequency(int *Frequency);
STDMETHODIMP put_Frequency(int Frequency);
STDMETHODIMP get_Waveform(int *Waveform);
STDMETHODIMP put_Waveform(int Waveform);
STDMETHODIMP get_Channels(int *Channels);
STDMETHODIMP get_BitsPerSample(int *BitsPerSample);
STDMETHODIMP get_SamplesPerSec(int *SamplesPerSec);
STDMETHODIMP put_Channels(int Channels);
STDMETHODIMP put_BitsPerSample(int BitsPersample);
STDMETHODIMP put_SamplesPerSec(int SamplesPerSec);
STDMETHODIMP get_Amplitude(int *Amplitude);
STDMETHODIMP put_Amplitude(int Amplitude);
STDMETHODIMP get_SweepRange(int *SweepStart, int *SweepEnd);
STDMETHODIMP put_SweepRange(int SweepStart, int SweepEnd);

CAudioSynth *m_Synth; // the current synthesizer
intm_Channels;
intm_BitsPerSample;
intm_SamplesPerSec;

private:

// it is only allowed to to create these objects with CreateInstance
CSynthFilter(LPUNKNOWN lpunk, HRESULT *phr);

// When the format changes, reconnect...
void CSynthFilter::ReconnectWithNewFormat(void);

};


// -------------------------------------------------------------------------
// CSynthStream
// -------------------------------------------------------------------------
// CSynthStream manages the data flow from the output pin.

class CSynthStream : public CSourceStream {

public:

CSynthStream(HRESULT *phr, CSynthFilter *pParent, LPCWSTR pPinName);
~CSynthStream();

BOOL ReadyToStop(void) {return FALSE;}

// stuff an audio buffer with the current format
HRESULT FillBuffer(IMediaSample *pms);

// ask for buffers of the size appropriate to the agreed media type.
HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc,
ALLOCATOR_PROPERTIES *pProperties);

// verify we can handle this format
HRESULT CheckMediaType(const CMediaType *pMediaType);

// set the agreed media type
HRESULT SetMediaType(const CMediaType *pMediaType);

HRESULT GetMediaType(CMediaType *pmt);

// resets the stream time to zero.
HRESULT OnThreadCreate(void);

HRESULT Active (void);
HRESULT Inactive (void);

private:

// Access to this state information should be serialized with the filters
// critical section (m_pFilter->pStateLock())

CCritSec m_cSharedState; // use this to lock access to m_rtSampleTime and m_Synth
// which are shared with the worker thread.

CRefTime m_rtSampleTime; // The time to be stamped on each sample
CAudioSynth *m_Synth; // the current synthesizer

CSynthFilter *m_pParent;
};



#endif // _AUDIOSYNTH_IMPLEMENTATION_ implementation only....

#endif /* __AUDIOSYNTH__ */