|
|
#include <windows.h>
#include "sverb.h"
#include "sverbp.h"
#include "clone.h"
STD_CREATE(WavesReverb)
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::NDQueryInterface
//
// Subclass can override if it wants to implement more interfaces.
//
STDMETHODIMP CDirectSoundWavesReverbDMO::NDQueryInterface(THIS_ REFIID riid, LPVOID *ppv) { IMP_DSDMO_QI(riid,ppv);
if (riid == IID_IPersist) { return GetInterface((IPersist*)this, ppv); } else if (riid == IID_IMediaObject) { return GetInterface((IMediaObject*)this, ppv); } else if (riid == IID_IDirectSoundFXWavesReverb) { return GetInterface((IDirectSoundFXWavesReverb*)this, ppv); } else if (riid == IID_ISpecifyPropertyPages) { return GetInterface((ISpecifyPropertyPages*)this, ppv); } else if (riid == IID_IMediaParams) { return GetInterface((IMediaParams*)this, ppv); } else if (riid == IID_IMediaParamInfo) { return GetInterface((IMediaParamInfo*)this, ppv); } else return CComBase::NDQueryInterface(riid, ppv); }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::Clone
//
STDMETHODIMP CDirectSoundWavesReverbDMO::Clone(IMediaObjectInPlace **pp) { return StandardDMOClone<CDirectSoundWavesReverbDMO, DSFXWavesReverb>(this, pp); }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::CDirectSoundWavesReverbDMO
//
CDirectSoundWavesReverbDMO::CDirectSoundWavesReverbDMO( IUnknown *pUnk, HRESULT *phr ) : CComBase( pUnk, phr ), m_fDirty(TRUE), m_pbCoeffs(NULL), m_plStates(NULL), m_fInitCPCMDMO(false), m_pfnSVerbProcess(NULL), m_fGain(DSFX_WAVESREVERB_INGAIN_DEFAULT), m_fMix(DSFX_WAVESREVERB_REVERBMIX_DEFAULT), m_fTime(DSFX_WAVESREVERB_REVERBTIME_DEFAULT), m_fRatio(DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT) { }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::~CDirectSoundWavesReverbDMO
//
CDirectSoundWavesReverbDMO::~CDirectSoundWavesReverbDMO() { delete[] m_pbCoeffs; delete[] m_plStates;
}
const MP_CAPS g_capsAll = MP_CAPS_CURVE_JUMP | MP_CAPS_CURVE_LINEAR | MP_CAPS_CURVE_SQUARE | MP_CAPS_CURVE_INVSQUARE | MP_CAPS_CURVE_SINE; static ParamInfo g_params[] = { // index type caps min, max, neutral, unit text, label, pwchText
SVP_Gain, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX, DSFX_WAVESREVERB_INGAIN_DEFAULT, L"dB", L"InGain", L"", SVP_Mix, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_REVERBMIX_MIN, DSFX_WAVESREVERB_REVERBMIX_MAX, DSFX_WAVESREVERB_REVERBMIX_DEFAULT, L"dB", L"ReverbMix", L"", SVP_ReverbTime, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_REVERBTIME_MIN, DSFX_WAVESREVERB_REVERBTIME_MAX, DSFX_WAVESREVERB_REVERBTIME_DEFAULT, L"ms", L"ReverbTime", L"", SVP_Ratio, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX, DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT, L"", L"HighFreqRTRatio", L"", };
HRESULT CDirectSoundWavesReverbDMO::InitOnCreation() { HRESULT hr = InitParams(1, &GUID_TIME_REFERENCE, 0, 0, sizeof(g_params)/sizeof(*g_params), g_params); return hr; }
HRESULT CDirectSoundWavesReverbDMO::Init() { HRESULT hr = S_OK;
DMO_MEDIA_TYPE *pmt = InputType(); if (pmt->majortype != MEDIATYPE_Audio || pmt->subtype != MEDIASUBTYPE_PCM || pmt->formattype != FORMAT_WaveFormatEx) { hr = E_INVALIDARG; TraceI(1,"ERROR: Invalid Format specified during SetInputType()\n"); }
WAVEFORMATEX *pwfex = (WAVEFORMATEX*)pmt->pbFormat;
if (SUCCEEDED(hr)) { if (pwfex->wFormatTag != WAVE_FORMAT_PCM || pwfex->wBitsPerSample != 16) { hr = E_INVALIDARG; TraceI(1,"ERROR: Invalid Format specified during SetInputType()\n"); } }
if (SUCCEEDED(hr)) { switch (pwfex->nChannels) { case 1: m_pfnSVerbProcess = SVerbMonoToMonoShort; break;
case 2: m_pfnSVerbProcess = SVerbStereoToStereoShort; break;
default: hr = E_FAIL; TraceI(1,"ERROR: Waves Reverb only supports mono or stereo\n"); } }
// Formats have been set. Initialize the reverb.
//
m_pbCoeffs = new BYTE[GetCoefsSize()]; m_plStates = new long[(GetStatesSize() + sizeof(long) - 1)/ sizeof(long)];
if (m_pbCoeffs == NULL || m_plStates == NULL) { hr = E_OUTOFMEMORY; TraceI(1,"ERROR: Out of memory\n"); }
if (SUCCEEDED(hr)) { memset(m_plStates, 0, GetStatesSize()); InitSVerb((float)m_ulSamplingRate, m_pbCoeffs); InitSVerbStates(m_plStates); m_fInitCPCMDMO = true; }
Discontinuity(); return hr; }
HRESULT CDirectSoundWavesReverbDMO::Discontinuity() { HRESULT hr; DSFXWavesReverb wavesreverb; if (m_pbCoeffs && m_plStates) { memset(m_plStates, 0, GetStatesSize()); InitSVerb((float)m_ulSamplingRate, m_pbCoeffs); InitSVerbStates(m_plStates); }
hr = GetAllParameters(&wavesreverb);
if (SUCCEEDED(hr)) { hr = SetAllParameters(&wavesreverb); }
if (SUCCEEDED(hr)) { UpdateCoefficients(); }
return hr; }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::FBRProcess
//
HRESULT CDirectSoundWavesReverbDMO::FBRProcess(DWORD cSamples, BYTE *pIn, BYTE *pOut) { assert(m_pfnSVerbProcess); (*m_pfnSVerbProcess)( cSamples, (short*)pIn, (short*)pOut, m_pbCoeffs, m_plStates);
return S_OK; }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::ProcessInPlace
//
HRESULT CDirectSoundWavesReverbDMO::ProcessInPlace(ULONG ulQuanta, LPBYTE pcbData, REFERENCE_TIME rtStart, DWORD dwFlags) { // Update parameter values from any curves that may be in effect.
if (this->GetActiveParamBits()) { this->UpdateActiveParams(rtStart, *this); this->UpdateCoefficients(); }
return FBRProcess(ulQuanta, pcbData, pcbData); }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::SetParam
//
STDMETHODIMP CDirectSoundWavesReverbDMO::SetParam(DWORD dwParamIndex,MP_DATA value) { HRESULT hr = SetParamInternal(dwParamIndex, value, false); if (SUCCEEDED(hr)) this->UpdateCoefficients(); return hr; }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::SetParamInternal
//
HRESULT CDirectSoundWavesReverbDMO::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager) { switch (dwParamIndex) { case SVP_Gain: CHECK_PARAM(DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX); m_fGain = value; break;
case SVP_Mix: CHECK_PARAM(DSFX_WAVESREVERB_REVERBMIX_MIN,DSFX_WAVESREVERB_REVERBMIX_MAX); m_fMix = value; break;
case SVP_ReverbTime: CHECK_PARAM(DSFX_WAVESREVERB_REVERBTIME_MIN,DSFX_WAVESREVERB_REVERBTIME_MAX); m_fTime = value; break; case SVP_Ratio: CHECK_PARAM(DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN,DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX); m_fRatio = value; break;
default: return E_FAIL; }
// Let base class set this so it can handle all the rest of the param calls
//
HRESULT hr = fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value); return hr; }
void CDirectSoundWavesReverbDMO::UpdateCoefficients() { // Waves Reverb has a single SetSVerb call that updates all parameters simultaneously instead of internal
// state variables that are updated incrementally by changes to individual parameters as the other DMOs do.
if (m_fInitCPCMDMO) { SetSVerb( m_fGain, m_fMix, m_fTime, m_fRatio, m_pbCoeffs); } }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::SetAllParameters
//
STDMETHODIMP CDirectSoundWavesReverbDMO::SetAllParameters(THIS_ LPCDSFXWavesReverb pwr) { HRESULT hr = S_OK; // Check that the pointer is not NULL
if (pwr == NULL) { TraceI(1,"ERROR: pwr is NULL\n"); hr = E_POINTER; }
// Set the parameters
if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Gain, pwr->fInGain, false); if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Mix, pwr->fReverbMix, false); if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_ReverbTime, pwr->fReverbTime, false); if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Ratio, pwr->fHighFreqRTRatio, false); this->UpdateCoefficients();
return hr; }
//////////////////////////////////////////////////////////////////////////////
//
// CDirectSoundWavesReverbDMO::GetAllParameters
//
HRESULT CDirectSoundWavesReverbDMO::GetAllParameters(THIS_ LPDSFXWavesReverb pwr) { HRESULT hr = S_OK; MP_DATA mpd;
if (pwr == NULL) return E_POINTER; #define GET_PARAM(x,y) \
if (SUCCEEDED(hr)) { \ hr = GetParam(x, &mpd); \ if (SUCCEEDED(hr)) pwr->y = mpd; \ }
#define GET_PARAM_LONG(x,y) \
if (SUCCEEDED(hr)) { \ hr = GetParam(x, &mpd); \ if (SUCCEEDED(hr)) pwr->y = (long)mpd; \ } GET_PARAM(SVP_Gain, fInGain); GET_PARAM(SVP_Mix, fReverbMix); GET_PARAM(SVP_ReverbTime, fReverbTime); GET_PARAM(SVP_Ratio, fHighFreqRTRatio);
return S_OK; }
HRESULT CDirectSoundWavesReverbDMO::CheckInputType(const DMO_MEDIA_TYPE *pmt) { if (NULL == pmt) { return E_POINTER; }
// Verify that this is PCM with a WAVEFORMATEX format specifier
if ((pmt->majortype != MEDIATYPE_Audio) || (pmt->subtype != MEDIASUBTYPE_PCM) || (pmt->formattype != FORMAT_WaveFormatEx) || (pmt->cbFormat < sizeof(WAVEFORMATEX)) || (pmt->pbFormat == NULL)) return DMO_E_TYPE_NOT_ACCEPTED;
// Verify the wave format
WAVEFORMATEX *pWave = (WAVEFORMATEX*)pmt->pbFormat; if (pWave->wFormatTag != WAVE_FORMAT_PCM || pWave->wBitsPerSample != 16 || pWave->nChannels != 1 && pWave->nChannels != 2) { return DMO_E_TYPE_NOT_ACCEPTED; } return NOERROR; }
// GetClassID
//
// Part of the persistent file support. We must supply our class id
// which can be saved in a graph file and used on loading a graph with
// this fx in it to instantiate this filter via CoCreateInstance.
//
HRESULT CDirectSoundWavesReverbDMO::GetClassID(CLSID *pClsid) { if (pClsid==NULL) { return E_POINTER; } *pClsid = GUID_DSFX_WAVES_REVERB; return NOERROR;
} // GetClassID
|