home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: $$CLASS_NAME$$.cpp
- //
- // Desc: Audio Effect DMO Wizard generated code - Implementation of $$CLASS_NAME$$
- //
- // Author: $$DSDMO_AUTHOR$$
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
- /////////////////////////////////////////////////////////////////////////////
- // TODO List:
- // - Implement DoProcess()
- // - Complete implementation of $$CLASS_NAME$$() and ~$$CLASS_NAME$$() if necessary
- // - Complete implementation of UpdateStatesInternal() if necessary
- // - Modify implementation of Process() if necessary
- // - Complete or modify implementation of InternalProcessInput() if necessary
- // - Complete or modify implementation of InternalProcessOutput() if necessary
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- // - Complete implementation of SetAllParameters()
- // - Complete implementation of GetAllParameters()
- // - Complete implementation of SetParamInternal()
- $$ENDIF
- // - Implement your custom member functions
- //
- // Optional to Implement or Complete Implementation of:
- // - InternalAllocateStreamingResources()
- // - InternalFreeStreamingResources()
- // - InternalAcceptingInput()
- // - InternalDiscontinuity()
- // - InternalFlush()
- // - InternalSetInputMaxLatency()
- // - InternalGetInputMaxLatency()
- // - GetLatency()
- //
- /////////////////////////////////////////////////////////////////////////////
-
-
- #include "stdafx.h"
-
- #define _ATL_FREE_THREADED
- #define _ATL_STATIC_REGISTRY
-
- #include <atlbase.h>
- //You may derive a class from CComModule and use it if you want to override
- //something, but do not change the name of _Module
- extern CComModule _Module;
- #include <atlcom.h>
- #include <atlctl.h>
- #include <statreg.h>
- #include <statreg.cpp>
- #include <atlimpl.cpp>
-
- #include "resource.h"
- #define FIX_LOCK_NAME
- #include <dmo.h>
- #include <dmoimpl.h>
- #include <initguid.h>
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- #include "param.h" // (param.h must come before uuids to avoid redefinitions)
- $$ENDIF
-
- #include "$$CLASS_NAME$$.h"
- #include <mmreg.h>
-
-
- /////////////////////////////////////////////////////////////////////////////
- // $$CLASS_NAME$$
-
- ///////////////////////
- //
- // $$CLASS_NAME$$::$$CLASS_NAME$$
- //
- // Constructor for $$CLASS_NAME$$.
- //
- $$CLASS_NAME$$::$$CLASS_NAME$$()
- {
- // Initialization
- m_fDirty = TRUE;
- m_fInitialized = FALSE;
-
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- // Initialize parameters in IMediaParam
- InitParams(1, &GUID_TIME_REFERENCE, 0, 0, sizeof(g_params)/sizeof(*g_params), g_params);
-
- $$ENDIF
- // These variables will get reintialized when input type is set
- m_nChannels = 0;
- m_wBitsPerSample = 0;
- m_nSamplesPerSec = 0;
-
- // TODO: Initialize member variables here if necessary.
- $$IF(EMPTY_DSDMO)
- // Example:
- m_dwParam1 = 0;
- // End of Example
- $$ELSE // Sample DMO
- m_fFreq = 6;
- m_fWidth = 0.85f;
-
- m_ulPeriod = 0;
- m_fSineTablePeriod = 0;
- m_ulPhase = 0;
- $$ENDIF
-
- };
-
-
- ///////////////////////
- //
- // $$CLASS_NAME$$::~$$CLASS_NAME$$
- //
- // Destructor for $$CLASS_NAME$$.
- //
- $$CLASS_NAME$$::~$$CLASS_NAME$$()
- {
- // Free streaming resources in case it hasn't been done by the client
- InternalFreeStreamingResources();
-
- // TODO: Add to the destructor if necessary
-
- };
-
-
- ///////////////////////
- //
- // $$CLASS_NAME$$::UpdateStatesInternal
- //
- // Update internal states
- //
- HRESULT $$CLASS_NAME$$::UpdateStatesInternal()
- {
- HRESULT hr = S_OK;
-
- // TODO: Update DMO states here
- $$IF(!EMPTY_DSDMO) // Sample DMO
- m_ulPeriod = (LONG)(m_nSamplesPerSec / m_fFreq);
- m_fSineTablePeriod = (float)( (m_ulPeriod / 4.0) / SINE_TABLE_SIZE );
- $$ENDIF
-
- return hr;
- }
-
-
- ///////////////////////////////
- //
- // IMediaObjectInPlace Methods
- //
-
- ///////////////////////
- //
- // IMediaObjectInPlace::Process
- //
- // The Process method processes a block of data. The application supplies a
- // pointer to a block of input data. The DMO processes the data in place.
- //
- // Parameters
- //
- // ulSize
- // [in] Size of the data, in bytes.
- //
- // pData
- // [in, out] Pointer to a buffer of size ulSize. On input, the buffer
- // holds the input data. If the method returns successfully, the
- // buffer contains the output data.
- //
- // refTimeStart
- // [in] Start time of the data.
- //
- // dwFlags
- // [in] Either DMO_INPLACE_NORMAL or DMO_INPLACE_ZERO. See Remarks
- // for more information.
- //
- // Return Value
- // S_FALSE Success. There is still data to process.
- // S_TRUE Success. There is no remaining data to process.
- // E_FAIL Failure.
- //
- // If the method fails, the buffer might contain garbage. The application
- // should not use the contents of the buffer.
- //
- // The DMO might produce output data beyond the length of the input data. This
- // is called an effect tail. For example, a reverb effect continues after the
- // input reaches silence. If the DMO has an effect tail, this method returns
- // S_FALSE.
- //
- // While the application has input data for processing, call the Process
- // method with the dwFlags parameter set to DMO_INPLACE_NORMAL. If the last
- // such call returns S_FALSE, call Process again, this time with a zeroed input
- // buffer and the DMO_INPLACE_ZERO flag. The DMO will now fill the zeroed buffer
- // with the effect tail. Continue calling Process in this way until the return
- // value is S_TRUE, indicating that the DMO has finished processing the effect
- // tail.
- //
- // If the DMO has no effect tail, this method always returns S_TRUE (or an error code).
- //
- HRESULT $$CLASS_NAME$$::Process(ULONG ulSize, BYTE *pData, REFERENCE_TIME refTimeStart, DWORD dwFlags)
- {
-
- // TODO: Modify implementation of Process() if necessary
-
- HRESULT hr = S_OK;
-
- if (!m_fInitialized)
- {
- hr = AllocateStreamingResources();
- }
-
- if (SUCCEEDED(hr))
- {
-
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- // Update parameter values from any curves that may be in effect.
- // We pick up the current values stored in the CParamsManager helper for time rtStart.
-
- // Note that we are using IMediaParams in a less than
- // perfect way. We update at the beginning of every time slice instead of smoothly over the curve.
- // This is okay for an effect like gargle as long as the time slice is consistently small (which
- // it conveniently is when hosted in DirectSound).
-
- // Here are some suggestions of how it can be done, with increasing degree of accuracy. Different
- // types of effects and effect parameters require different levels of accuracy, so no solution is the best
- // solution for all (especially if you are concerned about CPU cost.)
- // 1) Break the time slice up into mini pieces of some number of milliseconds
- // each and run through all the steps in Process for each sub slice. This guarantees the
- // stair stepping is small enough not to be noticable. This approach will work well for parameters
- // that don't create an audible stair stepping noise (or "zipper") noise when controled in this way.
- // Control over volume, for example, does not work well.
- // 2) Use the above mechanism, but pass the start and end values for each parameter to the
- // processing engine. It, in turn, applies linear interpolation to each parameter. This results
- // in a smooth approximation of the parameter curve and removes all but the most subtle aliasing noise.
- // 3) Pass the curves directly to the processing engine, which accurately calculates each sample
- // mathematically. This is obviously the best, but most complex and CPU intensive.
- this->UpdateActiveParams(refTimeStart, *this);
- $$ENDIF
-
- // Process the data
- hr = DoProcess(pData, pData, ulSize / WaveFormat()->nBlockAlign);
- }
- return hr;
- }
-
-
- /////////////////////
- //
- // IMediaObjectInPlace::Clone
- //
- // The Clone method creates a copy of the DMO in its current state.
- //
- // Parameters
- //
- // ppMediaObject
- // [out] Address of a pointer to receive the new DMO's
- // IMediaObjectInPlace interface.
- //
- // Return Value
- // Returns S_OK if successful. Otherwise, returns an HRESULT value
- // indicating the cause of the error.
- //
- // If the method succeeds, the IMediaObjectInPlace interface that it returns
- // has an outstanding reference count. Be sure to release the interface when
- // you are finished using it.
- //
- HRESULT $$CLASS_NAME$$::Clone(IMediaObjectInPlace **ppMediaObject)
- {
- // Check the input pointer
- if (!ppMediaObject)
- {
- return E_POINTER;
- }
-
- // This will be cleaned up when client releases the newly created object
- // or if there's some error along the way
- $$CLASS_NAME$$ * pNew$$DSDMOID_NAME$$ = new CComObject<$$CLASS_NAME$$>;
- if( !pNew$$DSDMOID_NAME$$ )
- {
- return E_OUTOFMEMORY;
- }
-
- HRESULT hr = S_OK;
-
- hr = pNew$$DSDMOID_NAME$$->UpdateStatesInternal();
-
- IMediaObject * pCloned = NULL;
- if( SUCCEEDED( hr ) )
- {
- IUnknown *pUnk;
- hr = pNew$$DSDMOID_NAME$$->QueryInterface( IID_IUnknown, (void **) &pUnk );
- if( SUCCEEDED( hr ) )
- {
- hr = pUnk->QueryInterface( IID_IMediaObject, (void **) &pCloned );
- pUnk->Release();
- }
- }
-
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- // Copy parameter control information
- if (SUCCEEDED(hr))
- {
- hr = pNew$$DSDMOID_NAME$$->CopyParamsFromSource((CParamsManager *) this);
- }
-
- // Copy current parameter values
- $$DSDMOID_NAME$$Params params;
- if (SUCCEEDED(hr))
- {
- hr = GetAllParameters(¶ms);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = pNew$$DSDMOID_NAME$$->SetAllParameters(¶ms);
- }
- $$ENDIF
-
- // Copy the input and output types
- if (SUCCEEDED(hr))
- {
- DMO_MEDIA_TYPE mt;
- DWORD cInputStreams = 0;
- DWORD cOutputStreams = 0;
- GetStreamCount(&cInputStreams, &cOutputStreams);
-
- for (DWORD i = 0; i < cInputStreams && SUCCEEDED(hr); ++i)
- {
- hr = GetInputCurrentType(i, &mt);
- if (hr == DMO_E_TYPE_NOT_SET)
- {
- hr = S_OK; // great, don't need to set the cloned DMO
- }
- else if (SUCCEEDED(hr))
- {
- hr = pCloned->SetInputType(i, &mt, 0);
- MoFreeMediaType( &mt );
- }
- }
-
- for (i = 0; i < cOutputStreams && SUCCEEDED(hr); ++i)
- {
- hr = GetOutputCurrentType(i, &mt);
- if (hr == DMO_E_TYPE_NOT_SET)
- {
- hr = S_OK; // great, don't need to set the cloned DMO
- }
- else if (SUCCEEDED(hr))
- {
- hr = pCloned->SetOutputType(i, &mt, 0);
- MoFreeMediaType( &mt );
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = pCloned->QueryInterface(IID_IMediaObjectInPlace, (void**)ppMediaObject);
- }
-
- // Release the object's original ref. If clone succeeded (made it through QI) then returned pointer
- // has one ref. If we failed, refs drop to zero, freeing the object.
- pCloned->Release();
- }
-
- // Something went wrong, clean up for client
- if (FAILED(hr))
- {
- delete pNew$$DSDMOID_NAME$$;
- }
-
- return hr;
- }
-
-
- ////////////////////////////
- //
- // IMediaObjectInPlace::GetLatency
- //
- // The GetLatency method retrieves the latency introduced by this DMO.
- //
- // Parameters
- //
- // pLatencyTime
- // [out] Pointer to a variable that receives the latency, in
- // 100-nanosecond units.
- //
- // Return Value
- // Returns S_OK if successful. Otherwise, returns an HRESULT value
- // indicating the cause of the error.
- //
- // This method returns the average time required to process each buffer.
- // This value usually depends on factors in the run-time environment, such
- // as the processor speed and the CPU load. One possible way to implement
- // this method is for the DMO to keep a running average based on historical
- // data.
- //
- HRESULT $$CLASS_NAME$$::GetLatency(REFERENCE_TIME *pLatencyTime)
- {
- // Check the input arguments;
- if (!pLatencyTime)
- {
- return E_POINTER;
- }
-
- // TODO: Calculate some reasonable average latency if this DMO is going to
- // be used with DirectShow. For now, 5 is used as the default latency.
-
- *pLatencyTime= static_cast<REFERENCE_TIME>(5);
-
- return S_OK;
- }
-
-
- ////////////////////////////////
- //
- // IMediaObjectImpl Methods
- //
-
- ///////////////////////////////
- //
- // IMediaObjectImpl::InternalAllocateStreamingResources
- //
- // *** Called by AllocateStreamingResources, description below ***
- //
- // The AllocateStreamingResources method allocates any resources needed by
- // the DMO. Calling this method is always optional.
- //
- // An application can call this method as a streaming optimization. It gives
- // the DMO an opportunity to perform any time-consuming initializations
- // before streaming begins. If you call this method, do so after you set
- // the media types on the DMO, but before you make the first calls to
- // ProcessInput or ProcessOutput.
- //
- // This method is optional in the following sense:
- //
- // * If the DMO does not support this method, the method returns S_OK.
- //
- // * If the application never calls this method, the DMO allocates resources
- // within a call to ProcessInput or ProcessOutput or Process.
- //
- // If the DMO supports this method, it should also support the
- // FreeStreamingResources method.
- //
- // Note:
- //
- // The template keeps a private flag that indicates whether this method has
- // been called. If the method is called when the flag is already TRUE, it
- // returns S_OK without calling the InternalAllocateStreamingResources
- // method. The FreeStreamingResources method resets the flag to FALSE.
- //
- HRESULT $$CLASS_NAME$$::InternalAllocateStreamingResources(void)
- {
- HRESULT hr = S_OK;
-
- // TODO: Our initialization should be done here.
- // TODO: If necessary, allocate resources needed to process the current input type
-
- if( SUCCEEDED(hr) )
- {
- hr = UpdateStatesInternal();
- m_fInitialized = TRUE;
- }
-
- return hr;
- }
-
-
- ////////////////////////////////
- //
- // IMediaObjectImpl::InternalDiscontinuity
- //
- // *** Called by Discontinuity, description below ***
- //
- // The Discontinuity method signals a discontinuity on the specified input
- // stream.
- //
- // Possible Return Values:
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid streamindex
- //
- // A discontinuity represents a break in the input. A discontinuity might
- // occur because no more data is expected, the format is changing, or there
- // is a gap in the data. After a discontinuity, the DMO does not accept further
- // input on that stream until all pending data has been processed. The
- // application should call the ProcessOutput method until none of the streams
- // returns the DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE flag.
- //
- HRESULT $$CLASS_NAME$$::InternalDiscontinuity(DWORD dwInputStreamIndex)
- {
-
- // TODO: Implement Discontinuity if necessary
-
- return S_OK;
- }
-
-
- /////////////////////////
- //
- // IMediaObjectImpl::InternalFlush
- //
- // *** Called by Flush, description below ***
- //
- // The Flush method flushes all internally buffered data.
- //
- // Return Value:
- // Returns S_OK if successful. Otherwise, returns an HRESULT value indicating
- // the cause of the error.
- //
- // The DMO performs the following actions when this method is called:
- // * Releases any IMediaBuffer references it holds.
- //
- // * Discards any values that specify the time stamp or sample length for a
- // media buffer.
- //
- // * Reinitializes any internal states that depend on the contents of a
- // media sample.
- //
- // Media types, maximum latency, and locked state do not change.
- //
- // When the method returns, every input stream accepts data. Output streams
- // cannot produce any data until the application calls the ProcessInput method
- // on at least one input stream.
- //
- // Note:
- //
- // The template keeps a private flag that indicates the object's flushed
- // state. The Flush method sets the flag to TRUE, and the ProcessInput method
- // resets it to FALSE. If Flush is called when the flag is already TRUE, the
- // method returns S_OK without calling the InternalFlush method.
- //
- HRESULT $$CLASS_NAME$$::InternalFlush(void)
- {
-
- // TODO: Change implementation if necessary
-
- // Right now, just clear out the buffer
- m_pBuffer = NULL;
-
- return S_OK;
- }
-
-
- ////////////////////
- //
- // IMediaObjectImpl::InternalFreeStreamingResources
- //
- // *** Called by FreeStreamingResources, description below ***
- //
- // The FreeStreamingResources method frees resources allocated by the DMO.
- // Calling this method is always optional.
- //
- // Return Value
- //
- // Returns S_OK if successful. Otherwise, returns an HRESULT value indicating
- // the cause of the error.
- //
- // This method releases any resources that the AllocateStreamingResources
- // method initializes.
- //
- // If the DMO does not support this method, the method returns S_OK. If you
- // call this method during streaming, the method fails and the DMO does not
- // release any resources.
- //
- // Regardless of whether the method fails or succeeds, the application can
- // continue to call other methods on the DMO. The DMO might need to
- // re-initialize resources that were previously freed.
- //
- HRESULT $$CLASS_NAME$$::InternalFreeStreamingResources(void)
- {
-
- // TODO: Implement this function if InternalAllocateStreamingResources() was implemented
-
- return S_OK;
- }
-
-
- ////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetInputMaxLatency
- //
- // *** Called by GetInputMaxLatency, description below ***
- //
- // The GetInputMaxLatency method retrieves the maximum latency on a specified
- // input stream.
- //
- // Parameters
- // dwInputStreamIndex: Zero-based index of an input stream on the DMO.
- // prtMaxLatency: [out] Pointer to a variable that receives the maximum latency.
- //
- // Return Value
- // Returns an HRESULT value. The following are possible return values.
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // E_FAIL Failure
- // E_NOTIMPL Not implemented. Assume zero latency
- //
- // The latency is the difference between a time stamp on the input stream and
- // the corresponding time stamp on the output stream. The maximum latency is
- // the largest possible difference in the time stamps. For a DMO, determine the
- // maximum latency as follows:
- //
- // * Process input buffers until the DMO can produce output.
- //
- // * Process as many output buffers as possible.
- //
- // * The maximum latency is the largest delta between input time stamps and
- // output time stamps (taken as an absolute value).
- //
- // Under this definition, latency does not include the time that it takes
- // to process samples. Nor does it include any latency introduced by the
- // size of the input buffer.
- //
- // For the special case where a DMO processes exactly one sample at a time,
- // the maximum latency is simply the difference in time stamps.
- //
- // Latency is defined only when samples have time stamps, and the time stamps
- // increase or decrease monotonically. Maximum latency might depend on the
- // media types for the input and output streams.
- //
-
- HRESULT $$CLASS_NAME$$::InternalGetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME *prtMaxLatency)
- {
-
- // TODO: Provide a good max latency if this DMO is going to be used with DirectShow.
- // For now, 30 is used as the default max latency.
-
- *prtMaxLatency = 30;
-
- return S_OK;
- }
-
-
- /////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalSetInputMaxLatency
- //
- // *** Called by SetInputMaxLatency, description below ***
- //
- // The SetInputMaxLatency method sets the maximum latency on a specified input
- // stream. For the definition of maximum latency, see GetInputMaxLatency.
- //
- // Parameters
- //
- // dwInputStreamIndex
- // Zero-based index of an input stream on the DMO.
- //
- // rtMaxLatency
- // Maximum latency.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // E_FAIL Failure
- // E_NOTIMPL Not implemented
- //
- HRESULT $$CLASS_NAME$$::InternalSetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME rtMaxLatency)
- {
- // Method not implemented
- return E_NOTIMPL;
- }
-
-
- ////////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetInputSizeInfo
- //
- // *** Called by GetInputSizeInfo, description below ***
- //
- // The GetInputSizeInfo method retrieves the buffer requirements for a
- // specified input stream.
- //
- // Parameters
- //
- // dwInputStreamIndex: Zero-based index of an input stream on the DMO.
- //
- // pcbSize: [out] Pointer to a variable that receives
- // the minimum size of an input buffer for this stream, in bytes.
- //
- // pulSizeMaxLookahead: [out] Pointer to a variable that receives the
- // maximum amount of data that the DMO will hold for lookahead, in bytes.
- // If the DMO does not perform lookahead on the stream, the value is zero.
- //
- // pulSizeAlignment [out] Pointer to a variable that receives the
- // required buffer alignment, in bytes. If the input stream has no
- // alignment requirement, the value is 1.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // DMO_E_TYPE_NOT_SET Media type was not set
- //
- // The buffer requirements may depend on the media types of the various
- // streams. Before calling this method, set the media type of each stream
- // by calling the SetInputType and SetOutputType methods. If the media types
- // have not been set, this method might return an error.
- //
- // If the DMO performs lookahead on the input stream, it returns the
- // DMO_INPUT_STREAMF_HOLDS_BUFFERS flag in the GetInputStreamInfo method.
- // During processing, the DMO holds up to the number of bytes indicated by the
- // pulSizeMaxLookahead parameter. The application must allocate enough buffers for
- // the DMO to hold this much data.
- //
- // A buffer is aligned if the buffer's start address is a multiple of
- // *pulSizeAlignment. The alignment must be a power of two. Depending on the
- // microprocessor, reads and writes to an aligned buffer might be faster than
- // to an unaligned buffer. Also, some microprocessors do not support unaligned
- // reads and writes.
- //
- // Note:
- //
- // GetInputSizeInfo returns DMO_E_TYPE_NOT_SET unless all of the non-optional
- // streams have media types. Therefore, in the derived class, the internal
- // methods can assume that all of the non-optional streams have media types.
- //
- HRESULT $$CLASS_NAME$$::InternalGetInputSizeInfo(DWORD dwInputStreamIndex, DWORD *pcbSize, DWORD *pulSizeMaxLookahead, DWORD *pulSizeAlignment)
- {
- // We don't have to do any validation, because it is all done in the base class
-
- HRESULT hr = S_OK;
- const DMO_MEDIA_TYPE* pmt;
- pmt = InputType(0);
- const WAVEFORMATEX* pwfx = reinterpret_cast<const WAVEFORMATEX*>(pmt->pbFormat);
- *pcbSize = pwfx->nChannels * pwfx->wBitsPerSample / 8;
- *pulSizeMaxLookahead = 0; // no look ahead
- *pulSizeAlignment = 1; // no alignment requirement
-
- return hr;
- }
-
-
- //////////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetOutputSizeInfo
- //
- // *** Called by GetOutputSizeInfo, description below ***
- //
- // The GetOutputSizeInfo method retrieves the buffer requirements for a
- // specified output stream.
- //
- // Parameters
- //
- // dwOutputStreamIndex
- // Zero-based index of an output stream on the DMO.
- //
- // pcbSize
- // [out] Pointer to a variable that receives the minimum size of an
- // output buffer for this stream, in bytes.
- //
- // pulSizeAlignment
- // [out] Pointer to a variable that receives the required buffer
- // alignment, in bytes. If the output stream has no alignment
- // requirement, the value is 1.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // DMO_E_TYPE_NOT_SET Media type was not set
- //
- // The buffer requirements may depend on the media types set for each of the
- // streams.
- //
- // Before calling this method, set the media type of each stream by calling
- // the SetInputType and SetOutputType methods. If the media types have not
- // been set, this method might return an error. However, if a stream is
- // optional, and the application will not use the stream, you do not have to
- // set the media type for the stream.
- //
- // A buffer is aligned if the buffer's start address is a multiple of
- // *pulSizeAlignment. Depending on the architecture of the microprocessor, it is
- // faster to read and write to an aligned buffer than to an unaligned buffer.
- // On some microprocessors, reading and writing to an unaligned buffer is not
- // supported and can cause the program to crash. Zero is not a valid alignment.
- //
- // Note:
- //
- // GetOutputSizeInfo returns DMO_E_TYPE_NOT_SET unless all of the non-optional
- // streams have media types. Therefore, in the derived class, the internal
- // methods can assume that all of the non-optional streams have media types.
- //
- HRESULT $$CLASS_NAME$$::InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, DWORD *pcbSize, DWORD *pulSizeAlignment)
- {
- // We don't have to do any validation, because it is all done in the base class
- HRESULT hr = S_OK;
- const DMO_MEDIA_TYPE* pmt;
- pmt = OutputType(0);
- const WAVEFORMATEX* pwfx = reinterpret_cast<const WAVEFORMATEX*>(pmt->pbFormat);
- *pcbSize = pwfx->nChannels * pwfx->wBitsPerSample / 8;
- *pulSizeAlignment = 1;
-
- return hr;
- }
-
-
- ////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetInputStreamInfo
- //
- // *** Called by GetInputStreamInfo, description below ***
- //
- // The GetInputStreamInfo method retrieves information about an input stream,
- // such as any restrictions on the number of samples per buffer, and whether
- // the stream performs lookahead on the input data. This information never
- // changes.
- //
- // Parameters
- // dwInputStreamIndex:
- // Zero-based index of an input stream on the DMO.
- //
- // pdwFlags:
- // [out] Pointer to a variable that receives a bitwise combination of
- // zero or more DMO_INPUT_STREAM_INFO_FLAGS flags.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // E_POINTER NULL pointer argument
- //
- // The DMO_INPUT_STREAMF_HOLDS_BUFFERS flag indicates that the DMO performs
- // lookahead on the incoming data.
- //
- // The application must be sure to allocate sufficient buffers for the DMO
- // to process the input. Call the GetInputSizeInfo method to determine the
- // buffer requirements.
- //
- HRESULT $$CLASS_NAME$$::InternalGetInputStreamInfo(DWORD dwInputStreamIndex, DWORD *pdwFlags)
- {
- *pdwFlags = DMO_OUTPUT_STREAMF_WHOLE_SAMPLES;
- *pdwFlags |= DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE;
-
- return S_OK;
- }
-
-
- //////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetOutputStreamInfo
- //
- // *** Called by GetOutputStreamInfo, description below ***
- //
- // The GetOutputStreamInfo method retrieves information about an output
- // stream; for example, whether the stream is discardable, and whether
- // it uses a fixed sample size. This information never changes.
- //
- // Parameters
- // dwOutputStreamIndex
- // Zero-based index of an output stream on the DMO.
- //
- // pdwFlags
- // [out] Pointer to a variable that receives a bitwise combination
- // of zero or more DMO_OUTPUT_STREAM_INFO_FLAGS flags.
- //
- // Return Value
- //
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // E_POINTER NULL pointer argument
- //
- HRESULT $$CLASS_NAME$$::InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex, DWORD *pdwFlags)
- {
- *pdwFlags = DMO_OUTPUT_STREAMF_WHOLE_SAMPLES;
- *pdwFlags |= DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE;
-
- return S_OK;
- }
-
-
- /////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetInputType
- //
- // *** Called by GetInputType, description below ***
- //
- // The GetInputType method retrieves a preferred media type for a specified
- // input stream.
- //
- // Parameters
- //
- // dwInputStreamIndex
- // Zero-based index of an input stream on the DMO.
- //
- // dwTypeIndex
- // Zero-based index on the set of acceptable media types.
- //
- // pmt
- // [out] Pointer to a DMO_MEDIA_TYPE structure allocated by the caller.
- // The method fills the structure with the media type. The format block
- // might be NULL, in which case the format type GUID is GUID_NULL.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // DMO_E_NO_MORE_ITEMS Type index is out of range
- // E_OUTOFMEMORY Insufficient memory
- // E_POINTER NULL pointer argument
- //
- // Call this method to enumerate an input stream's preferred media types. The
- // DMO assigns each media type an index value in order of preference. The most
- // preferred type has an index of zero. To enumerate all the types, make
- // successive calls while incrementing the type index until the method returns
- // DMO_E_NO_MORE_ITEMS.
- //
- // If the method succeeds, call MoFreeMediaType to free the format block.
- //
- // To set the media type, call the SetInputType method. Setting the media type
- // on one stream can change another stream's preferred types. In fact, a
- // stream might not have a preferred type until the type is set on another
- // stream. For example, a decoder might not have a preferred output type until
- // the input type is set. However, the DMO is not required to update its
- // preferred types dynamically in this fashion. Thus, the types returned by
- // this method are not guaranteed to be valid; they might fail when used in the
- // SetInputType method. Conversely, the DMO is not guaranteed to enumerate every
- // media type that it supports. To test whether a particular media type is
- // acceptable, call SetInputType with the DMO_SET_TYPEF_TEST_ONLY flag.
- //
- HRESULT $$CLASS_NAME$$::InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt)
- {
- // This function resembles InternalGetOutputType() since the input and output types must
- // be consistent for DirectSound
-
- HRESULT hr = S_OK;
-
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- if (dwTypeIndex > 1)
- $$ELSE
- if (dwTypeIndex > 0)
- $$ENDIF
- $$ELSE
- if (dwTypeIndex > 0)
- $$ENDIF
- {
- return DMO_E_NO_MORE_ITEMS;
- }
-
- // If pmt is NULL, and the type index is in range, we return S_OK
- if (pmt == NULL)
- {
- return S_OK;
- }
-
- // If the output type is set, we prefer to use that one
- if (OutputTypeSet(0))
- {
- return MoCopyMediaType(pmt, OutputType(0));
- }
-
- hr = MoInitMediaType(pmt, sizeof(WAVEFORMATEX));
-
- if (SUCCEEDED(hr))
- {
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- if (0 == dwTypeIndex)
- {
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_PCM; // We take PCM format!
- pmt->formattype = FORMAT_None;
- }
- else if (1 == dwTypeIndex)
- {
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_IEEE_FLOAT; // We take FLOAT format also!
- pmt->formattype = FORMAT_None;
- }
- $$ELSE
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_PCM; // We take PCM format!
- pmt->formattype = FORMAT_None;
- $$ENDIF
- $$ELSE
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_IEEE_FLOAT; // We take FLOAT format!
- pmt->formattype = FORMAT_None;
- $$ENDIF
- }
-
- return hr;
- }
-
-
- ///////////////////////////////////
- //
- // IMediaObjectImpl::InternalGetOutputType
- //
- // *** Called by GetOutputType, description below ***
- //
- // The GetOutputType method retrieves a preferred media type for a specified
- // output stream.
- //
- // Parameters
- //
- // dwOutputStreamIndex
- // Zero-based index of an output stream on the DMO.
- //
- // dwTypeIndex
- // Zero-based index on the set of acceptable media types.
- //
- // pmt
- // [out] Pointer to a DMO_MEDIA_TYPE structure allocated by the
- // caller. The method fills the structure with the media type. The
- // format block might be NULL, in which case the format type GUID is GUID_NULL.
- //
- // Return Value
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // DMO_E_NO_MORE_ITEMS Type index is out of range
- // E_OUTOFMEMORY Insufficient memory
- // E_POINTER NULL pointer argument
- //
- // Call this method to enumerate an output stream's preferred media types. The
- // DMO assigns each media type an index value, in order of preference. The
- // most preferred type has an index of zero. To enumerate all the types, make
- // successive calls while incrementing the type index, until the method returns
- // DMO_E_NO_MORE_ITEMS.
- //
- // If the method succeeds, call MoFreeMediaType to free the format block.
- //
- // To set the media type, call the SetOutputType method. Setting the media type
- // on one stream can change another stream's preferred types. In fact, a stream
- // might not have a preferred type until the type is set on another stream. For
- // example, a decoder might not have a preferred output type until the input
- // type is set. However, the DMO is not required to update its preferred types
- // dynamically in this fashion. Thus, the types returned by this method are not
- // guaranteed to be valid; they might fail when used in the SetOutputType method.
- // Conversely, the DMO is not guaranteed to enumerate every media type that it
- // supports. To test whether a particular media type is acceptable, call
- // SetOutputType with the DMO_SET_TYPEF_TEST_ONLY flag.
- //
- //
- HRESULT $$CLASS_NAME$$::InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt)
- {
- // This function resembles InternalGetInputType() since the input and output types must
- // be consistent for DirectSound
-
- HRESULT hr = S_OK;
-
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- if (dwTypeIndex > 1)
- $$ELSE
- if (dwTypeIndex > 0)
- $$ENDIF
- $$ELSE
- if (dwTypeIndex > 0)
- $$ENDIF
- {
- return DMO_E_NO_MORE_ITEMS;
- }
-
- // If pmt is NULL, and the type index is in range, we return S_OK
- if (pmt == NULL)
- {
- return S_OK;
- }
-
- // If the input type is set, we prefer to use that one
- if (InputTypeSet(0))
- {
- return MoCopyMediaType(pmt, InputType(0));
- }
-
- hr = MoInitMediaType(pmt, sizeof(WAVEFORMATEX));
-
- if (SUCCEEDED(hr))
- {
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- if (0 == dwTypeIndex)
- {
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_PCM; // We take PCM format!
- pmt->formattype = FORMAT_None;
- }
- else if (1 == dwTypeIndex)
- {
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_IEEE_FLOAT; // We take FLOAT format also!
- pmt->formattype = FORMAT_None;
- }
- $$ELSE
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_PCM; // We take PCM format!
- pmt->formattype = FORMAT_None;
- $$ENDIF
- $$ELSE
- pmt->majortype = MEDIATYPE_Audio;
- pmt->subtype = MEDIASUBTYPE_IEEE_FLOAT; // We take FLOAT format!
- pmt->formattype = FORMAT_None;
- $$ENDIF
- }
-
- return hr;
- }
-
-
- ///////////////////////////////////////
- //
- // IMediaObjectImpl::InternalProcessInput
- //
- // *** Called by ProcessInput, description below ***
- //
- // The ProcessInput method delivers a buffer to the specified input stream.
- //
- // Parameters
- // dwInputStreamIndex
- // Zero-based index of an input stream on the DMO.
- //
- // pBuffer
- // Pointer to the buffer's IMediaBuffer interface.
- //
- // dwFlags
- // Bitwise combination of zero or more flags from the
- // DMO_INPUT_DATA_BUFFER_FLAGS enumeration.
- //
- // rtTimestamp
- // Time stamp that specifies the start time of the data in the buffer.
- // If the buffer has a valid time stamp, set the
- // DMO_INPUT_DATA_BUFFERF_TIME flag in the dwFlags parameter.
- // Otherwise, the DMO ignores this value.
- //
- // rtTimelength
- // Reference time specifying the duration of the data in the buffer.
- // If this value is valid, set the DMO_INPUT_DATA_BUFFERF_TIMELENGTH
- // flag in the dwFlags parameter. Otherwise, the DMO ignores this value.
- //
- // Return Value
- // S_FALSE No output to process
- // S_OK Success
- // DMO_E_INVALIDSTREAMINDEX Invalid stream index
- // DMO_E_NOTACCEPTING Data cannot be accepted
- //
- // If the DMO does not process all the data in the buffer, it keeps a
- // reference count on the buffer. It releases the buffer once it has
- // generated all the output, unless it needs to perform lookahead on the data.
- // (To determine whether a DMO performs lookahead, call the GetInputStreamInfo
- // method.)
- //
- // If this method returns DMO_E_NOTACCEPTING, call the ProcessOutput method
- // until the input stream can accept more data. To determine whether the stream
- // can accept more data, call the GetInputStatus method.
- //
- // If the method returns S_FALSE, no output was generated from this input and the
- // application does not need to call ProcessOutput. However, a DMO is not required
- // to return S_FALSE in this situation; it might return S_OK.
- //
- // Note:
- //
- // Before this method calls InternalProcessInput, it calls
- // AllocateStreamingResources and InternalAcceptingInput. Therefore, the
- // implementation of InternalProcessInput can assume the following:
- //
- // * All resources have been allocated.
- // * The input stream can accept data.
- //
- HRESULT $$CLASS_NAME$$::InternalProcessInput(DWORD dwInputStreamIndex, IMediaBuffer *pBuffer, DWORD dwFlags, REFERENCE_TIME rtTimestamp, REFERENCE_TIME rtTimelength)
- {
-
- // TODO: Complete or modify implementation of InternalProcessInput() if necessary
-
- HRESULT hr = S_OK;
-
- if (!pBuffer)
- {
- return E_POINTER;
- }
-
- // Get the size of the input buffer
- hr = pBuffer->GetBufferAndLength(&m_pbInputData, &m_cbInputLength);
-
- if (SUCCEEDED(hr))
- {
- m_pBuffer = pBuffer;
-
- if (dwFlags & DMO_INPUT_DATA_BUFFERF_TIME)
- {
- m_bValidTime = true;
- m_rtTimestamp = rtTimestamp;
- }
- else
- {
- m_bValidTime = false;
- }
- }
-
- return hr;
- }
-
-
- ///////////////////////////////////
- //
- // IMediaObjectImpl::InternalProcessOutput
- //
- // *** Called by ProcessOutput, description below ***
- //
- // The ProcessOutput method generates output from the current input data.
- //
- // Parameters
- //
- // dwFlags
- // Bitwise combination of zero or more flags from the
- // DMO_PROCESS_OUTPUT_FLAGS enumeration.
- //
- // cOutputBufferCount
- // Number of output buffers.
- //
- // pOutputBuffers
- // [in, out] Pointer to an array of DMO_OUTPUT_DATA_BUFFER structures
- // containing the output buffers. Specify the size of the array in the
- // cOutputBufferCount parameter.
- //
- // pdwStatus
- // [out] Pointer to a variable that receives a reserved value (zero).
- // The application should ignore this value.
- //
- // Return Value
- // S_FALSE No output was generated
- // S_OK Success
- // E_FAIL Failure
- // E_INVALIDARG Invalid argument
- // E_POINTER NULL pointer argument
- //
- // The pOutputBuffers parameter points to an array of DMO_OUTPUT_DATA_BUFFER
- // structures. The application must allocate one structure for each output
- // stream. To determine the number of output streams, call the GetStreamCount
- // method. Set the cOutputBufferCount parameter to this number.
- //
- // Each DMO_OUTPUT_DATA_BUFFER structure contains a pointer to a buffer's
- // IMediaBuffer interface. The application allocates these buffers. The other
- // members of the structure are status fields. The DMO sets these fields if
- // the method succeeds. If the method fails, their values are undefined.
- //
- // When the application calls ProcessOutput, the DMO processes as much input
- // data as possible. It writes the output data to the output buffers, starting
- // from the end of the data in each buffer. (To find the end of the data, call
- // the IMediaBuffer::GetBufferAndLength method.) The DMO never holds a
- // reference count on an output buffer.
- //
- // If the DMO fills an entire output buffer and still has input data to
- // process, the DMO returns the DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE flag in the
- // DMO_OUTPUT_DATA_BUFFER structure. The application should check for this
- // flag by testing the dwStatus member of each structure.
- //
- // If the method returns S_FALSE, no output was generated. However, a DMO is
- // not required to return S_FALSE in this situation; it might return S_OK.
- //
- // Discarding data:
- //
- // You can discard data from a stream by setting the
- // DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER flag in the dwFlags parameter.
- // For each stream that you want to discard, set the pBuffer member of the
- // DMO_OUTPUT_DATA_BUFFER structure to NULL.
- //
- // For each stream in which pBuffer is NULL:
- //
- // If the DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER flag is set, and the
- // stream is discardable or optional, the DMO discards the data.
- //
- // If the flag is set but the stream is neither discardable nor optional, the
- // DMO discards the data if possible. It is not guaranteed to discard the
- // data.
- //
- // If the flag is not set, the DMO does not produce output data for that
- // stream, but does not discard the data.
- //
- // To check whether a stream is discardable or optional, call the
- // GetOutputStreamInfo method.
- //
- // Note:
- //
- // Before this method calls InternalProcessOutput, it calls
- // AllocateStreamingResources. Therefore, the implementation of
- // InternalProcessOutput can assume that all resources have been allocated.
- //
- HRESULT $$CLASS_NAME$$::InternalProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, DMO_OUTPUT_DATA_BUFFER *pOutputBuffers, DWORD *pdwStatus)
- {
-
- // TODO: Complete or modify implementation of InternalProcessOutput() if necessary
-
- HRESULT hr = S_OK;
- BYTE *pbData = NULL;
- DWORD cbData = 0;
- DWORD cbOutputLength = 0;
- DWORD cbBytesProcessed = 0;
- bool bComplete = false;
- const DWORD UNITS = 10000000; // 1 sec = 100 * UNITS ns
-
- CComPtr<IMediaBuffer> pOutputBuffer = pOutputBuffers[0].pBuffer;
-
- if (!m_pBuffer || !pOutputBuffer)
- {
- return S_FALSE; // Did not produce output
- }
-
- // Get the size of the output buffer
- hr = pOutputBuffer->GetBufferAndLength(&pbData, &cbData);
-
- if (SUCCEEDED(hr))
- {
- hr = pOutputBuffer->GetMaxLength(&cbOutputLength);
- }
-
- if (SUCCEEDED(hr))
- {
- // Skip past any valid data in the output buffer
- pbData += cbData;
- cbOutputLength -= cbData;
-
- // Calculate how many quanta we can process
- if (m_cbInputLength > cbOutputLength)
- {
- cbBytesProcessed = cbOutputLength;
- }
- else
- {
- cbBytesProcessed = m_cbInputLength;
- bComplete = true;
- }
-
- // Process the data
- hr = DoProcess(pbData, m_pbInputData, cbBytesProcessed / WaveFormat()->nBlockAlign);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = pOutputBuffer->SetLength(cbBytesProcessed + cbData);
- }
-
- if (SUCCEEDED(hr))
- {
- if (m_bValidTime)
- {
- pOutputBuffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_TIME;
- pOutputBuffers[0].rtTimestamp = m_rtTimestamp;
-
- // Estimate how far along we are
- pOutputBuffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH;
- double dTime = (double)(cbBytesProcessed) / WaveFormat()->nAvgBytesPerSec;
- pOutputBuffers[0].rtTimelength = (REFERENCE_TIME)(dTime * UNITS);
- }
-
- if (bComplete)
- {
- m_pBuffer = NULL; // Release input buffer
- }
- else
- {
- pOutputBuffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE;
- m_cbInputLength -= cbBytesProcessed;
- m_pbInputData += cbBytesProcessed;
- m_rtTimestamp += pOutputBuffers[0].rtTimelength;
- }
- }
- return hr;
- }
-
-
- ///////////////////////////////////
- //
- // DoProcess
- //
- // *** Called by Process and ProcessOutput ***
- //
- // The DoProcess method processes the sound data.
- //
- // Parameters
- //
- // pbData
- // Pointer to the output buffer
- //
- // pbInputData
- // Pointer to the input buffer
- //
- // dwQuanta
- // Number of quanta to process
- //
- // Return Value
- // S_OK Success
- //
- HRESULT $$CLASS_NAME$$::DoProcess(BYTE *pbData, const BYTE *pbInputData, DWORD dwQuanta)
- {
-
- $$IF(EMPTY_DSDMO)
- /////////////////////////////////////////////////////////////////////////////
- // TODO: Implement the sound processing code in this method
-
- $$IF(PROCESS_CHANNELS_MONO)
- if (1 == m_nChannels)
- {
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM)
- if (8 == m_wBitsPerSample)
- {
- // TODO: Process 8-Bit Mono PCM samples
-
- }
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM)
- else if (16 == m_wBitsPerSample)
- $$ELSE
- if (16 == m_wBitsPerSample)
- $$ENDIF
- {
- // TODO: Process 16-Bit Mono PCM samples
-
- }
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- else if (32 == m_wBitsPerSample)
- $$ELSE
- if (32 == m_wBitsPerSample)
- $$ENDIF
- {
- // TODO: Process 32-Bit Mono Float samples
-
- }
- $$ENDIF
- }
- $$ENDIF
- $$IF(PROCESS_CHANNELS_STEREO)
- $$IF(PROCESS_CHANNELS_MONO)
- else if (2 == m_nChannels)
- $$ELSE
- if (2 == m_nChannels)
- $$ENDIF
- {
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM)
- if (8 == m_wBitsPerSample)
- {
- // TODO: Process 8-Bit Stereo PCM samples
-
- }
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM)
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM)
- else if (16 == m_wBitsPerSample)
- $$ELSE
- if (16 == m_wBitsPerSample)
- $$ENDIF
- {
- // TODO: Process 16-Bit Stereo PCM samples
-
- }
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_FLOAT)
- $$IF(PROCESS_MEDIATYPE_16BIT_PCM || PROCESS_MEDIATYPE_8BIT_PCM)
- else if (32 == m_wBitsPerSample)
- $$ELSE
- if (32 == m_wBitsPerSample)
- $$ENDIF
- {
- // TODO: Process 32-Bit Stereo Float samples
-
- }
- $$ENDIF
- }
- $$ENDIF
- $$ELSE // ELSE for IF(PROCESS_CHANNELS_MONO) (a page up), below is for Sample DMO
- //
- // Start of Panner sample code
- //
- DWORD dwSample = 0;
-
- // Process each sample at a time
-
- if (1 == m_nChannels)
- {
- if (8 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- // 8-bit sound is 0 to 255 with 128 equal to silence
- // Normalize sample to -128 to 127
- int i = ((unsigned char*)pbInputData)[dwSample] - 128;
- int j = i;
-
- i *= 256;
- j *= 256;
-
- DoOneSample(&i, &j);
-
- i /= 256;
- j /= 256;
-
- ((unsigned char*)pbData)[dwSample] = (unsigned char)(i + 128);
- }
- }
- else if (16 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- int i = ((short*)pbInputData)[dwSample];
- int j = i;
-
- DoOneSample(&i, &j);
-
- ((short*)pbData)[dwSample] = (short)i;
- }
- }
- else if (32 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- float i = ((float*)pbInputData)[dwSample];
- float j = i;
-
- DoOneSample(&i, &j);
-
- ((float*)pbData)[dwSample] = (float)i;
- }
- }
- }
- else if (2 == m_nChannels)
- {
- if (8 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- // 8-bit sound is 0 to 255 with 128 equal to silence
- // Normalize sample to -128 to 127
- int i = ((unsigned char*)pbInputData)[dwSample * 2] - 128;
- int j = ((unsigned char*)pbInputData)[dwSample * 2 + 1] - 128;
-
- i *= 256;
- j *= 256;
-
- DoOneSample(&i, &j);
-
- i /= 256;
- j /= 256;
-
- ((unsigned char*)pbData)[dwSample * 2] = (unsigned char)(i + 128);
- ((unsigned char*)pbData)[dwSample * 2 + 1] = (unsigned char)(j + 128);
- }
- }
- else if (16 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- int i = ((short*)pbInputData)[dwSample * 2];
- int j = ((short*)pbInputData)[dwSample * 2 + 1];
-
- DoOneSample(&i, &j);
-
- ((short*)pbData)[dwSample * 2] = (short)i;
- ((short*)pbData)[dwSample * 2 + 1] = (short)j;
- }
- }
- else if (32 == m_wBitsPerSample)
- {
- for (dwSample = 0; dwSample < dwQuanta; ++dwSample)
- {
- float i = ((float*)pbInputData)[dwSample * 2];
- float j = ((float*)pbInputData)[dwSample * 2 + 1];
-
- DoOneSample(&i, &j);
-
- ((float*)pbData)[dwSample * 2] = (float)i;
- ((float*)pbData)[dwSample * 2 + 1] = (float)j;
- }
- }
- }
- //
- // End of Panner sample code
- //
- $$ENDIF
- return S_OK;
- }
-
-
- $$IF(!EMPTY_DSDMO)
- // Sample Panner DMO
- template<class SampleType> __forceinline void CPanner::DoOneSample(SampleType *l, SampleType *r)
- {
-
- // TODO: Add, change, remove as needed to implement your audio processing code
-
- // Increment current phase
- ++m_ulPhase;
-
- // Ignore the negative half cycle since we only interested in postive values
- if ( m_ulPhase > m_ulPeriod / 2 )
- {
- m_ulPhase = 0;
- }
-
- ULONG ulQuarterPhase = m_ulPhase;
- ULONG ulQuarterPeriod = m_ulPeriod / 4;
-
- // Wrap around at 1/4 of a cycle since the sine table contains only samples of a 1/4 cycle
- if( ulQuarterPhase > ulQuarterPeriod )
- {
- ulQuarterPhase = m_ulPeriod / 2 - ulQuarterPhase;
-
- // Eliminate duplicate samples at the wrap point
- if( ulQuarterPhase == ulQuarterPeriod )
- {
- ulQuarterPhase--;
- }
- }
-
- // Modulation rate for the left channel
- float fScaleLeft = SINE[(UINT)(ulQuarterPhase / m_fSineTablePeriod)];
-
- // Modulate amplitude of the left channel by fScaleLeft
- *l = (SampleType)( (*l) - (*l) * m_fWidth * fScaleLeft );
-
- // Modulate amplitude of the right channel by (1 - fScaleLeft)
- *r = (SampleType)( (*r) - (*r) * m_fWidth * (1 - fScaleLeft) );
- }
- $$ENDIF
-
-
- ////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalAcceptingInput
- //
- // Queries whether an input stream can accept more input. The derived class
- // must declare and implement this method.
- //
- // Parameters
- //
- // dwInputStreamIndex
- // Index of an input stream.
- //
- // Return Value
- //
- // Returns S_OK if the input stream can accept input, or S_FALSE otherwise.
- //
- // Note:
- //
- // Called by IMediaObject::GetInputStatus
- //
- HRESULT $$CLASS_NAME$$::InternalAcceptingInput(DWORD dwInputStreamIndex)
- {
-
- // TODO: Change implementation if necessary
-
- // Do not accept input if there is already input data to process
- return (m_pBuffer ? S_FALSE : S_OK);
- }
-
-
- ////////////////////////////////////
- //
- // IMediaObjectImpl::InternalCheckInputType
- //
- // Queries whether an input stream can accept a given media type.
- // The derived class must declare and implement this method.
- //
- // Parameters
- //
- // dwInputStreamIndex
- // Index of an input stream.
- //
- // pmt
- // Pointer to a DMO_MEDIA_TYPE structure that describes the media type.
- //
- // Return Value
- //
- // Returns S_OK if the media type is valid, or DMO_E_INVALIDTYPE otherwise.
- //
- // Note:
- //
- // Called by IMediaObject::SetInputType
- //
- HRESULT $$CLASS_NAME$$::InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt)
- {
- WAVEFORMATEX* pWave = (WAVEFORMATEX*)pmt->pbFormat;
-
- HRESULT hr = S_OK;
-
- // Check that we're PCM or float
- if ((NULL == pmt) ||
- (MEDIATYPE_Audio != pmt->majortype) ||
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM)
- $$IF(!PROCESS_MEDIATYPE_FLOAT)
- (MEDIASUBTYPE_PCM != pmt->subtype) ||
- $$ELSE
- (MEDIASUBTYPE_PCM != pmt->subtype &&
- MEDIASUBTYPE_IEEE_FLOAT != pmt->subtype) ||
- $$ENDIF
- $$ELIF(PROCESS_MEDIATYPE_FLOAT)
- (MEDIASUBTYPE_IEEE_FLOAT != pmt->subtype) ||
- $$ENDIF
- (FORMAT_WaveFormatEx != pmt->formattype &&
- FORMAT_None != pmt->formattype) ||
- (pmt->cbFormat < sizeof(WAVEFORMATEX)) ||
- (NULL == pmt->pbFormat))
- {
- hr = DMO_E_INVALIDTYPE;
- }
-
- // If other type set, accept only if identical to that. Otherwise accept
- // any standard PCM/float audio.
- if (SUCCEEDED(hr))
- {
- if (OutputTypeSet(0))
- {
- const DMO_MEDIA_TYPE* pmtOutput;
- pmtOutput = OutputType(0);
- if (memcmp(pmt->pbFormat, pmtOutput->pbFormat, sizeof(WAVEFORMATEX)))
- {
- hr = DMO_E_INVALIDTYPE;
- }
- }
- else
- {
- WAVEFORMATEX* pWave = (WAVEFORMATEX*)pmt->pbFormat;
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM) // Process PCM and maybe float
- $$IF(!PROCESS_MEDIATYPE_FLOAT) // Process PCM only
- if ((WAVE_FORMAT_PCM != pWave->wFormatTag) ||
- $$ELSE // Process PCM and float
- if ((WAVE_FORMAT_PCM != pWave->wFormatTag &&
- WAVE_FORMAT_IEEE_FLOAT != pWave->wFormatTag) ||
- $$ENDIF
- $$ELIF(PROCESS_MEDIATYPE_FLOAT) // Process float only
- if ((WAVE_FORMAT_IEEE_FLOAT != pWave->wFormatTag) ||
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit or 16-bit and maybe 32-bit
- $$IF(!PROCESS_MEDIATYPE_FLOAT) // Process 8-bit or 16-bit only
- $$IF(!PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit only
- (8 != pWave->wBitsPerSample) ||
- $$ELIF(!PROCESS_MEDIATYPE_8BIT_PCM) // Process 16-bit only
- (16 != pWave->wBitsPerSample) ||
- $$ELSE // Process 8-bit and 16-bit only
- ((8 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample)) ||
- $$ENDIF
- $$ELSE // Process 8-bit or 16-bit and 32-bit
- $$IF(!PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit and 32-bit only
- ((32 != pWave->wBitsPerSample) && (8 != pWave->wBitsPerSample)) ||
- $$ELIF(!PROCESS_MEDIATYPE_8BIT_PCM) // Process 16-bit and 32-bit only
- ((32 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample)) ||
- $$ELSE // Process 8-bit, 16-bit and 32-bit
- ((32 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample) && (8 != pWave->wBitsPerSample)) ||
- $$ENDIF
- $$ENDIF
- $$ELSE // Process maybe only 32-bit
- $$IF(PROCESS_MEDIATYPE_FLOAT) // Process only 32-bit
- (32 != pWave->wBitsPerSample) ||
- $$ENDIF
- $$ENDIF
- $$IF(PROCESS_CHANNELS_STEREO) // Process stereo and maybe mono as well
- $$IF(PROCESS_CHANNELS_MONO) // Process both stereo and mono
- ((1 != pWave->nChannels) && (2 != pWave->nChannels)) ||
- $$ELSE // Process stereo only
- (2 != pWave->nChannels) ||
- $$ENDIF
- $$ELSE // Process mono only
- (1 != pWave->nChannels) ||
- $$ENDIF
- ( // Supported sample rates:
- $$IF(PROCESS_SAMPLE_RATES_96000)
- (96000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_48000)
- (48000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_44100)
- (44100 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_32000)
- (32000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_22050)
- (22050 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_16000)
- (16000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_11025)
- (11025 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_8000)
- (8000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- TRUE // You may delete && TRUE
- ) ||
- (pWave->nBlockAlign != pWave->nChannels * pWave->wBitsPerSample / 8) ||
- (pWave->nAvgBytesPerSec != pWave->nSamplesPerSec * pWave->nBlockAlign))
- {
- hr = DMO_E_INVALIDTYPE;
- }
- }
- }
-
- if (SUCCEEDED(hr))
- {
- // We will remember the number of channels, bps, and sample rate of the input type
- m_nChannels = pWave->nChannels;
- m_wBitsPerSample = pWave->wBitsPerSample;
- m_nSamplesPerSec = pWave->nSamplesPerSec;
- }
-
- return hr;
- }
-
-
- ////////////////////////////////////////////
- //
- // IMediaObjectImpl::InternalCheckOutputType
- //
- // Queries whether an output stream can accept a given media type. The derived
- // class must declare and implement this method.
- //
- // Parameters
- //
- // dwOutputStreamIndex
- // Index of an output stream.
- //
- // pmt
- // Pointer to a DMO_MEDIA_TYPE structure that describes the media type.
- //
- // Return Value
- //
- // Returns S_OK if the media type is valid, or DMO_E_INVALIDTYPE otherwise.
- //
- // Note:
- //
- // Called by IMediaObject::SetOutputType
- //
- HRESULT $$CLASS_NAME$$::InternalCheckOutputType(DWORD dwOutputStreamIndex,const DMO_MEDIA_TYPE *pmt)
- {
- // Check that we're PCM or float
- HRESULT hr = S_OK;
-
- if ((NULL == pmt) ||
- (MEDIATYPE_Audio != pmt->majortype) ||
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM)
- $$IF(!PROCESS_MEDIATYPE_FLOAT)
- (MEDIASUBTYPE_PCM != pmt->subtype) ||
- $$ELSE
- (MEDIASUBTYPE_PCM != pmt->subtype &&
- MEDIASUBTYPE_IEEE_FLOAT != pmt->subtype) ||
- $$ENDIF
- $$ELIF(PROCESS_MEDIATYPE_FLOAT)
- (MEDIASUBTYPE_IEEE_FLOAT != pmt->subtype) ||
- $$ENDIF
- (FORMAT_WaveFormatEx != pmt->formattype &&
- FORMAT_None != pmt->formattype) ||
- (pmt->cbFormat < sizeof(WAVEFORMATEX)) ||
- (NULL == pmt->pbFormat))
- {
- hr = DMO_E_INVALIDTYPE;
- }
-
- // If other type set, accept only if identical to that. Otherwise accept
- // any standard PCM/float audio.
- if (SUCCEEDED(hr))
- {
- if (InputTypeSet(0))
- {
- const DMO_MEDIA_TYPE* pmtInput;
- pmtInput = InputType(0);
- if (memcmp(pmt->pbFormat, pmtInput->pbFormat, sizeof(WAVEFORMATEX)))
- {
- hr = DMO_E_INVALIDTYPE;
- }
- }
- else
- {
- WAVEFORMATEX* pWave = (WAVEFORMATEX*)pmt->pbFormat;
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM) // Process PCM and maybe float
- $$IF(!PROCESS_MEDIATYPE_FLOAT) // Process PCM only
- if ((WAVE_FORMAT_PCM != pWave->wFormatTag) ||
- $$ELSE // Process PCM and float
- if ((WAVE_FORMAT_PCM != pWave->wFormatTag &&
- WAVE_FORMAT_IEEE_FLOAT != pWave->wFormatTag) ||
- $$ENDIF
- $$ELIF(PROCESS_MEDIATYPE_FLOAT) // Process float only
- if ((WAVE_FORMAT_IEEE_FLOAT != pWave->wFormatTag) ||
- $$ENDIF
- $$IF(PROCESS_MEDIATYPE_8BIT_PCM || PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit or 16-bit and maybe 32-bit
- $$IF(!PROCESS_MEDIATYPE_FLOAT) // Process 8-bit or 16-bit only
- $$IF(!PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit only
- (8 != pWave->wBitsPerSample) ||
- $$ELIF(!PROCESS_MEDIATYPE_8BIT_PCM) // Process 16-bit only
- (16 != pWave->wBitsPerSample) ||
- $$ELSE // Process 8-bit and 16-bit only
- ((8 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample)) ||
- $$ENDIF
- $$ELSE // Process 8-bit or 16-bit and 32-bit
- $$IF(!PROCESS_MEDIATYPE_16BIT_PCM) // Process 8-bit and 32-bit only
- ((32 != pWave->wBitsPerSample) && (8 != pWave->wBitsPerSample)) ||
- $$ELIF(!PROCESS_MEDIATYPE_8BIT_PCM) // Process 16-bit and 32-bit only
- ((32 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample)) ||
- $$ELSE // Process 8-bit, 16-bit and 32-bit
- ((32 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample) && (8 != pWave->wBitsPerSample)) ||
- $$ENDIF
- $$ENDIF
- $$ELSE // Process maybe only 32-bit
- $$IF(PROCESS_MEDIATYPE_FLOAT) // Process only 32-bit
- (32 != pWave->wBitsPerSample) ||
- $$ENDIF
- $$ENDIF
- $$IF(PROCESS_CHANNELS_STEREO) // Process stereo and maybe mono as well
- $$IF(PROCESS_CHANNELS_MONO) // Process both stereo and mono
- ((1 != pWave->nChannels) && (2 != pWave->nChannels)) ||
- $$ELSE // Process stereo only
- (2 != pWave->nChannels) ||
- $$ENDIF
- $$ELSE // Process mono only
- (1 != pWave->nChannels) ||
- $$ENDIF
- ( // Supported sample rates:
- $$IF(PROCESS_SAMPLE_RATES_96000)
- (96000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_48000)
- (48000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_44100)
- (44100 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_32000)
- (32000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_22050)
- (22050 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_16000)
- (16000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_11025)
- (11025 != pWave->nSamplesPerSec) &&
- $$ENDIF
- $$IF(PROCESS_SAMPLE_RATES_8000)
- (8000 != pWave->nSamplesPerSec) &&
- $$ENDIF
- TRUE // You may delete && TRUE
- ) ||
- (pWave->nBlockAlign != pWave->nChannels * pWave->wBitsPerSample / 8) ||
- (pWave->nAvgBytesPerSec != pWave->nSamplesPerSec * pWave->nBlockAlign))
- {
- hr = DMO_E_INVALIDTYPE;
- }
- }
- }
-
- return hr;
- }
-
-
- ///////////////
- //
- // IMediaObjectImpl::Lock
- //
- // Locks the object. The derived class must declare and implement this method.
- //
- // If you implement your derived class using the Active Template Library (ATL),
- // you can use ATL's default implementation of this method.
- //
- void $$CLASS_NAME$$::Lock(void)
- {
- CComObjectRootEx<CComMultiThreadModel>::Lock();
- }
-
-
- ///////////////
- //
- // IMediaObjectImpl::Unlock
- //
- // Unlocks the object. The derived class must declare and implement this method.
- //
- // If you implement your derived class using the Active Template Library (ATL),
- // you can use ATL's default implementation of this method.
- //
- void $$CLASS_NAME$$::Unlock(void)
- {
- CComObjectRootEx<CComMultiThreadModel>::Unlock();
- }
-
-
- $$IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP)
- //////////////////////////////////////////////////////////////////////////////
- //
- // $$CLASS_NAME$$::SetParamInternal
- //
- HRESULT $$CLASS_NAME$$::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager)
- {
- switch (dwParamIndex)
- {
- $$IF(EMPTY_DSDMO)
- case $$DSDMO_DEFINE$$_PARAM1:
- m_dwParam1 = (DWORD)value;
- break;
- // TODO: Add cases for each of your parameters
- $$ELSE // Sample DMO
- case PANNER_FREQ:
- m_fFreq = (float)value;
- UpdateStatesInternal(); // To update m_ulPeriod
- break;
- case PANNER_WIDTH:
- m_fWidth = (float)value;
- break;
- $$ENDIF
- default:
- return E_INVALIDARG;
- }
-
- // Let base class set this so it can handle all the rest of the param calls.
- // Skip the base class if fSkipPasssingToParamManager. This indicates that we're calling the function
- // internally using values that came from the base class -- thus there's no need to tell it values it
- // already knows.
- return fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value);
- }
-
- //////////////////
- // Macros used by GetAllParameters() and SetAllParameters()
- //
- // GET_PARAM_DWORD()
- #define GET_PARAM_DWORD(x, y) \
- if (SUCCEEDED(hr)) \
- { \
- hr = GetParam(x, &var); \
- if (SUCCEEDED(hr)) \
- { \
- y = (DWORD)var; \
- } \
- }
-
- // GET_PARAM_FLOAT()
- #define GET_PARAM_FLOAT(x, y) \
- if (SUCCEEDED(hr)) \
- { \
- hr = GetParam(x, &var); \
- if (SUCCEEDED(hr)) \
- { \
- y = (float)var; \
- } \
- }
-
- // SET_PARAM()
- #define SET_PARAM(x, y) \
- if (SUCCEEDED(hr)) \
- { \
- hr = SetParam(x, static_cast<MP_DATA>(y)); \
- }
-
- ///////////////
- //
- // $$INTERFACE_NAME$$::SetAllParameters
- //
- STDMETHODIMP $$CLASS_NAME$$::SetAllParameters(THIS_ LPC$$DSDMOID_NAME$$Params pParm)
- {
- HRESULT hr = S_OK;
-
- // Check that the pointer is not NULL
- if (NULL == pParm)
- {
- hr = E_POINTER;
- }
-
- // Set the parameters
- if (SUCCEEDED(hr))
- {
- $$IF(EMPTY_DSDMO)
- // TODO: Set all parameters with values stored in pParm. Example:
- SET_PARAM($$DSDMO_DEFINE$$_PARAM1, pParm->dwParam1);
- // End of Example
- $$ELSE // Sample DMO
- SET_PARAM(PANNER_FREQ, pParm->fFreq);
- SET_PARAM(PANNER_WIDTH, pParm->fWidth);
- $$ENDIF
- }
-
- m_fDirty = TRUE;
- return hr;
- }
-
-
- ///////////////
- //
- // $$INTERFACE_NAME$$::GetAllParameters
- //
- STDMETHODIMP $$CLASS_NAME$$::GetAllParameters(THIS_ LP$$DSDMOID_NAME$$Params pParm)
- {
- HRESULT hr = S_OK;
- MP_DATA var;
-
- if (NULL == pParm)
- {
- return E_POINTER;
- }
-
- $$IF(EMPTY_DSDMO)
- // TODO: Get all parameter values into pParm.
- // Example:
- GET_PARAM_DWORD($$DSDMO_DEFINE$$_PARAM1, pParm->dwParam1);
- // End of Example
- $$ELSE // Sample DMO
- GET_PARAM_FLOAT(PANNER_FREQ, pParm->fFreq);
- GET_PARAM_FLOAT(PANNER_WIDTH, pParm->fWidth);
- $$ENDIF
-
- return hr;
- }
-
-
- ////////////////
- //
- // IPersist::GetClassID
- //
- // Get the class ID for this class
- //
- HRESULT $$CLASS_NAME$$::GetClassID(CLSID *pClsid)
- {
- // Check for valid pointer
- if( NULL == pClsid )
- {
- return E_POINTER;
- }
-
- *pClsid = CLSID_$$DSDMO_DEFINE$$;
- return S_OK;
-
- } // GetClassID
-
-
- ////////////////
- //
- // IPersistStream::IsDirty
- //
- // Checks the object for changes since it was last saved
- //
- HRESULT $$CLASS_NAME$$::IsDirty()
- {
- return m_fDirty ? S_OK : S_FALSE;
- }
-
- ////////////////
- //
- // IPersistStream::Load
- //
- // Initializes an object from the stream where it was previously saved
- //
- HRESULT $$CLASS_NAME$$::Load(IStream *pStm)
- {
- ULONG ulSizeRead = 0;
- HRESULT hr = S_OK;
-
- if (NULL == pStm)
- {
- return E_POINTER;
- }
-
- $$DSDMOID_NAME$$Params params;
- hr = pStm->Read((void *)¶ms, sizeof(params), &ulSizeRead);
- if (hr != S_OK || ulSizeRead < sizeof(params))
- {
- return E_FAIL;
- }
-
- hr = SetAllParameters(¶ms);
-
- m_fDirty = FALSE;
-
- return hr;
- }
-
-
- ////////////////
- //
- // IPersistStream::Save
- //
- // This method saves an object to the specified stream
- //
- HRESULT $$CLASS_NAME$$::Save(IStream *pStm, BOOL fClearDirty)
- {
- HRESULT hr = S_OK;
-
- if (NULL == pStm)
- {
- return E_POINTER;
- }
-
- $$DSDMOID_NAME$$Params params;
- hr = GetAllParameters(¶ms);
- if (FAILED(hr))
- {
- return hr;
- }
-
- ULONG ulSizeWritten = 0;
- hr = pStm->Write((void *)¶ms, sizeof(params), &ulSizeWritten);
- if (hr != S_OK || ulSizeWritten < sizeof(params))
- {
- return E_FAIL;
- }
-
- if (fClearDirty)
- {
- m_fDirty = FALSE;
- }
-
- return S_OK;
- }
-
-
- ////////////////
- //
- // IPersistStream::GetSizeMax
- //
- // This method returns the size in bytes of the stream needed to save the object
- //
- HRESULT $$CLASS_NAME$$::GetSizeMax(ULARGE_INTEGER *pcbSize)
- {
- if ( NULL == pcbSize )
- return E_POINTER;
-
- pcbSize->QuadPart = sizeof($$DSDMOID_NAME$$Params);
- return S_OK;
- }
-
- // ENDIF for IF(SUPPORT_DS_IMEDPARAM || SUPPORT_DS_DMP) (a few pages up)
- $$ENDIF
-
-
- $$IF(SUPPORT_DS_DMP)
- ////////////////
- //
- // _DERIVED_::GetPages
- //
- // Get the property pages GUIDs
- //
- HRESULT $$CLASS_NAME$$::GetPages(CAUUID *pPages)
- {
- // Only one property page is required for DMO
- pPages->cElems = 1;
- pPages->pElems = static_cast<GUID *>(CoTaskMemAlloc(sizeof(GUID)));
-
- // Make sure memory is allocated for pPages->pElems
- if (NULL == pPages->pElems)
- {
- return E_OUTOFMEMORY;
- }
-
- // Return the property page's class ID
- *(pPages->pElems) = CLSID_$$DSDMO_DEFINE$$PROP;
- return S_OK;
- }
-
- $$ENDIF
-