aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/DSP/dsp_sps/dxi
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/DSP/dsp_sps/dxi
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/DSP/dsp_sps/dxi')
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.cpp283
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.def7
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dep69
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsp271
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsw29
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.h47
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.mak312
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.rc202
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.cpp326
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.h68
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/Filter.cpp1139
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/Filter.h176
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/MediaParams.cpp465
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/MediaParams.h99
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.cpp403
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.h124
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/Parameters.h47
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.cpp192
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.h8
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/PlugInGUIDs.h5
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/ReadMe.txt68
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/StdAfx.cpp9
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/StdAfx.h43
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/dmoguids.libbin0 -> 22810 bytes
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam.h461
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam_i.c53
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/include/DXi.h121
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/include/DeferZeroFill.h33
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/res/AudioPlugIn.rc213
-rw-r--r--Src/Plugins/DSP/dsp_sps/dxi/resource.h59
30 files changed, 5132 insertions, 0 deletions
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.cpp b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.cpp
new file mode 100644
index 00000000..f2ebc687
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.cpp
@@ -0,0 +1,283 @@
+// AudioPlugIn.cpp: implementation of the CAudioPlugIn class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "AudioPlugIn.h"
+
+// Note: see AudioPlugIn.h to redefine PROCESS_IN_PLACE
+#if PROCESS_IN_PLACE
+#pragma message("***** Compiling an IN-PLACE audio plug-in *****")
+#else
+#pragma message("***** Compiling an NON-IN-PLACE audio plug-in *****")
+#endif
+
+#include "resource.h"
+#include <commctrl.h>
+
+char g_path[MAX_PATH];
+
+#define SPS_CONFIGDLG_IMPL
+#define SPS_CONFIGDLG_ON_WM_CLOSE { ShowWindow(hwndDlg,SW_HIDE); /*g_config.visible=0;*/ }
+//#define SPS_CONFIGDLG_HIDEABLE_EDITOR 0
+#include "../sps_common.h"
+#include "../sps_configdlg.h"
+
+//////////////////////////////////////////////////////////////////////
+// Ctors
+
+CAudioPlugIn::CAudioPlugIn( HRESULT* phr )
+{
+ // TODO: put all initialization code in Initialize(), below.
+}
+
+CAudioPlugIn::~CAudioPlugIn()
+{
+ SPS_quitapp();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::Initialize()
+{
+ SPS_initapp();
+ strcpy(g_path,"c:\\progra~1\\winamp\\plugins\\dsp_sps"); //FUCKO
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::IsValidInputFormat( const WAVEFORMATEX* pwfx ) const
+{
+ // The plug-in base class will have already validated pwfx to ensure that
+ // it is 16-bit PCM or 32-bit float, 1 or 2 channels.
+
+ // TODO: Add any additional checks here, such as sample rate, etc.
+
+ // By default, only 32-bit float buffers are supported.
+ if (WAVE_FORMAT_IEEE_FLOAT != pwfx->wFormatTag)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::IsValidOutputFormat( const WAVEFORMATEX* pwfx ) const
+{
+ // The plug-in base class will have already validated pwfx to ensure that
+ // it is 16-bit PCM or 32-bit float, 1 or 2 channels.
+
+ // TODO: Add any additional checks here, such as sample rate, etc.
+
+ // By default, only 32-bit float buffers are supported.
+ if (WAVE_FORMAT_IEEE_FLOAT != pwfx->wFormatTag)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::IsValidTransform( const WAVEFORMATEX* pwfxIn, const WAVEFORMATEX* pwfxOut ) const
+{
+ // The plug-in base class will have already validated pwfxIn/pwfxOut to ensure that
+ // it is 16-bit PCM or 32-bit float, 1 or 2 channels, and that both have the same
+ // sample rate.
+
+ // TODO: Add any additional checks here, such as sample rate, etc.
+
+ // By default, only 32-bit float buffers are supported.
+ if (WAVE_FORMAT_IEEE_FLOAT != pwfxIn->wFormatTag)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ if (WAVE_FORMAT_IEEE_FLOAT != pwfxOut->wFormatTag)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::SuggestOutputFormat( WAVEFORMATEX* pwfx ) const
+{
+ // The plug-in base class will have already validated pwfx to ensure that
+ // it is 16-bit PCM or 32-bit float, 1 or 2 channels, and that both have the same
+ // sample rate.
+ // TODO: Add any additional checks here, such as sample rate, etc.
+
+ // pwfx is initially set to the input format. If your plug-in doesn't need
+ // to change the output format, simply return S_OK.
+ // TODO: change pwfx if necessary.
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::Process( LONGLONG llSampAudioTimestamp,
+ AudioBuffer* pbufIn,
+ AudioBuffer* pbufOut )
+{
+ BOOL const bGenerateTail = (NULL == pbufIn);
+ BOOL const bIsInPlace = (pbufIn == pbufOut);
+
+ // Note about deferred zero filling:
+ //
+ // AudioBuffer will automatically take advantage of IDeferZeroFill,
+ // if the host app supports it. To avoid unnecessary and wasteful buffer
+ // fills, always check the 'bZero' flag in AudioBuffer before calling
+ // the GetPointer() method. This is because calling GetPointer() will
+ // trigger a zero-fill if the underlying data buffer was marked as "defer
+ // zero fill."
+ //
+ // Similarly, to allow downstream filters to benefit from deferred
+ // zero filling, be sure to set the 'bZero' flag in an AudioBuffer, if
+ // your DSP code is producing a completely silent buffer.
+
+ if (bGenerateTail)
+ {
+ // TODO: Add code to generate a tail if required by your plug-in.
+ // Return S_OK if more effect tail data remains. Return S_FALSE
+ // if no more tail data remains.
+
+ // Default implementation generates no tail
+ return S_FALSE;
+ }
+
+ // TODO: Put your DSP code here
+ float *in=pbufIn->GetPointer();
+ float *out=pbufOut->GetPointer();
+ int of=(int)pbufIn->lOffset;
+ int size=(int)pbufIn->pms->GetSize();
+ int nbsamp=size/sizeof(float);
+
+/* // If we're bypassed, copy input to output without processing
+ float fEnabled = GetParamValue( PARAM_ENABLE );
+ if (fEnabled < 0.5f)
+ {
+ memcpy (out, in, pbufIn->cSamp * m_wfxIn.nBlockAlign );
+ return S_OK;
+ }*/
+
+
+ const WAVEFORMATEX *inpformat=GetInputFormat();
+ int nch=inpformat->nChannels;
+ int srate=inpformat->nSamplesPerSec;
+
+ if(0)
+ {
+ char tmp[512];
+ int size2=(int)pbufOut->pms->GetSize();
+ wsprintf(tmp,"%d %d %d %d %d %d\n",of,size,size2,nbsamp,nch,srate);
+ OutputDebugString(tmp);
+ }
+
+ memcpy(out,in,size);
+ extern SPSEffectContext *g_fucko_ctx;
+ SPS_process_samples(g_fucko_ctx,
+ (void *)out, nbsamp/nch, 1, 32, nch, srate,
+ nbsamp, nbsamp);
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::AllocateResources()
+{
+ // TODO: add code to here to prepare the for the start of streaming
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::FreeResources()
+{
+ // TODO: add code to here to clean up after streaming
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+int CAudioPlugIn::PersistGetSize() const
+{
+ int const cb
+ = sizeof(DWORD) // # of persisted parameters
+ + NUM_PARAMS * (sizeof(DWORD) + sizeof(float)); // (index,value), for each parameter
+
+ return cb;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::PersistLoad( IStream* pStream )
+{
+ ULONG cb = 0;
+ HRESULT hr = S_OK;
+
+ // Get the number of persisted parameters
+ DWORD cParams = 0;
+ hr = pStream->Read( &cParams, sizeof(cParams), &cb );
+ if (FAILED( hr ) || cb != sizeof(cParams))
+ return E_FAIL;
+
+ // Restore each parameter
+ for (DWORD ix = 0; ix < cParams; ix++)
+ {
+ // Get the parameter index
+ DWORD dwParam = 0;
+ hr = pStream->Read( &dwParam, sizeof(dwParam), &cb );
+ if (FAILED( hr ) || cb != sizeof(dwParam))
+ return E_FAIL;
+
+ // Get the parameter value
+ float fValue = 0;
+ hr = pStream->Read( &fValue, sizeof(fValue), &cb );
+ if (FAILED( hr ) || cb != sizeof(fValue))
+ return E_FAIL;
+
+ // Set the parameter value
+ if (m_pMediaParams)
+ m_pMediaParams->SetParam( dwParam, fValue );
+ }
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugIn::PersistSave( IStream* pStream )
+{
+ ULONG cb = 0;
+ HRESULT hr = S_OK;
+
+ // Put the number of persisted parameters
+ DWORD cParams = NUM_PARAMS;
+ hr = pStream->Write( &cParams, sizeof(cParams), &cb );
+ if (FAILED( hr ) || cb != sizeof(cParams))
+ return E_FAIL;
+
+ // Save each parameter
+ for (DWORD dwParam = 0; dwParam < cParams; dwParam++)
+ {
+ float fValue = 0;
+
+ // Get the parameter value
+ if (m_pMediaParams)
+ m_pMediaParams->GetParam( dwParam, &fValue );
+
+ // Write the parameter index
+ hr = pStream->Write( &dwParam, sizeof(dwParam), &cb );
+ if (FAILED( hr ) || cb != sizeof(dwParam))
+ return E_FAIL;
+
+ // Write the parameter value
+ hr = pStream->Write( &fValue, sizeof(fValue), &cb );
+ if (FAILED( hr ) || cb != sizeof(fValue))
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.def b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.def
new file mode 100644
index 00000000..aa233f15
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.def
@@ -0,0 +1,7 @@
+LIBRARY AudioPlugIn.dll
+DESCRIPTION 'AudioPlugIn DXi'
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dep b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dep
new file mode 100644
index 00000000..50ef98b0
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dep
@@ -0,0 +1,69 @@
+# Microsoft Developer Studio Generated Dependency File, included by AudioPlugIn.mak
+
+.\AudioPlugIn.cpp : \
+ ".\AudioPlugIn.h"\
+ ".\include\CakeMedParam.h"\
+ ".\include\DeferZeroFill.h"\
+ ".\include\DXi.h"\
+ ".\MediaParams.h"\
+ ".\ParamEnvelope.h"\
+ ".\Parameters.h"\
+ ".\StdAfx.h"\
+
+
+.\AudioPlugIn.rc : \
+ ".\res\AudioPlugIn.rc2"\
+
+
+.\AudioPlugInPropPage.cpp : \
+ ".\AudioPlugInPropPage.h"\
+ ".\include\CakeMedParam.h"\
+ ".\Parameters.h"\
+ ".\StdAfx.h"\
+
+
+.\Filter.cpp : \
+ ".\AudioPlugIn.h"\
+ ".\AudioPlugInPropPage.h"\
+ ".\Filter.h"\
+ ".\include\CakeMedParam.h"\
+ ".\include\DeferZeroFill.h"\
+ ".\include\DXi.h"\
+ ".\MediaParams.h"\
+ ".\ParamEnvelope.h"\
+ ".\Parameters.h"\
+ ".\PlugInGUIDs.h"\
+ ".\StdAfx.h"\
+
+
+.\MediaParams.cpp : \
+ ".\AudioPlugIn.h"\
+ ".\include\CakeMedParam.h"\
+ ".\include\CakeMedParam_i.c"\
+ ".\include\DeferZeroFill.h"\
+ ".\include\DXi.h"\
+ ".\MediaParams.h"\
+ ".\ParamEnvelope.h"\
+ ".\Parameters.h"\
+ ".\StdAfx.h"\
+
+
+.\ParamEnvelope.cpp : \
+ ".\AudioPlugIn.h"\
+ ".\include\CakeMedParam.h"\
+ ".\include\DeferZeroFill.h"\
+ ".\include\DXi.h"\
+ ".\MediaParams.h"\
+ ".\ParamEnvelope.h"\
+ ".\Parameters.h"\
+ ".\StdAfx.h"\
+
+
+.\PlugInApp.cpp : \
+ ".\PlugInApp.h"\
+ ".\StdAfx.h"\
+
+
+.\StdAfx.cpp : \
+ ".\StdAfx.h"\
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsp b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsp
new file mode 100644
index 00000000..e35a6a76
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsp
@@ -0,0 +1,271 @@
+# Microsoft Developer Studio Project File - Name="AudioPlugIn" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=AudioPlugIn - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "AudioPlugIn.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "AudioPlugIn.mak" CFG="AudioPlugIn - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "AudioPlugIn - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "AudioPlugIn - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "AudioPlugIn - Win32 Release"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "include" /I "..\..\dshow\include" /I "..\..\dshow\dshow" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib ole32.lib oleaut32.lib DMOGUIDS.LIB winmm.lib comdlg32.lib /nologo /entry:"DllEntryPoint@12" /subsystem:windows /dll /machine:I386 /nodefaultlib:"libcmt" /nodefaultlib:"libcmtd" /libpath:"../../dshow" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none
+# Begin Custom Build - Custom Build Steps
+OutDir=.\Release
+TargetName=AudioPlugIn
+InputPath=.\Release\AudioPlugIn.dll
+SOURCE="$(InputPath)"
+
+"custom.bld" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32.exe /s $(OutDir)\$(TargetName).DLL
+ echo >custom.bld
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "AudioPlugIn - Win32 Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "include" /I "..\..\dshow\include" /I "..\..\dshow\dshow" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib ole32.lib oleaut32.lib DMOGUIDS.LIB winmm.lib comdlg32.lib /nologo /entry:"DllEntryPoint@12" /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"libcmt" /nodefaultlib:"libcmtd" /pdbtype:sept /libpath:"../../dshow"
+# Begin Custom Build - Custom Build Steps
+OutDir=.\Debug
+TargetName=AudioPlugIn
+InputPath=.\Debug\AudioPlugIn.dll
+SOURCE="$(InputPath)"
+
+"custom.bld" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ regsvr32.exe /s $(OutDir)\$(TargetName).DLL
+ echo >custom.bld
+
+# End Custom Build
+
+!ENDIF
+
+# Begin Target
+
+# Name "AudioPlugIn - Win32 Release"
+# Name "AudioPlugIn - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Group "dx shit"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\AudioPlugIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AudioPlugIn.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\AudioPlugIn.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\AudioPlugInPropPage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Filter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MediaParams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ParamEnvelope.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PlugInApp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# End Group
+# Begin Group "ns-eel"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\ns-eel\megabuf.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\ns-eel-addfuncs.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\ns-eel-int.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\ns-eel.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-caltab.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-cfunc.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-compiler.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-eval.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-lextab.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ns-eel\nseel-yylex.c"
+# End Source File
+# End Group
+# Begin Group "sps"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\sps_common.cpp
+# End Source File
+# End Group
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\AudioPlugIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\AudioPlugInPropPage.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\DXi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Filter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MediaParams.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ParamEnvelope.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Parameters.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PlugInApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PlugInGUIDs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\AudioPlugIn.rc2
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsw b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsw
new file mode 100644
index 00000000..c697ed2e
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "AudioPlugIn"=.\AudioPlugIn.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.h b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.h
new file mode 100644
index 00000000..14446d14
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.h
@@ -0,0 +1,47 @@
+// AudioPlugIn.h: interface for the CAudioPlugIn class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_AUDIOPLUGIN_H__D9177ACC_DFF4_4C13_8FB9_F949C35BFEF0__INCLUDED_)
+#define AFX_AUDIOPLUGIN_H__D9177ACC_DFF4_4C13_8FB9_F949C35BFEF0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+struct DXiEvent;
+struct MfxEvent;
+
+#include "DXi.h"
+
+// TODO: #define PROCESS_IN_PLACE to FALSE if necessary, i.e., for plug-ins
+// which convert mono to stereo.
+#define PROCESS_IN_PLACE (TRUE)
+
+class CAudioPlugIn :
+ public CDXi
+{
+public:
+ CAudioPlugIn( HRESULT* phr );
+ virtual ~CAudioPlugIn();
+
+ HRESULT Initialize();
+
+ HRESULT IsValidInputFormat( const WAVEFORMATEX* pwfx ) const;
+ HRESULT IsValidOutputFormat( const WAVEFORMATEX* pwfx ) const;
+ HRESULT IsValidTransform( const WAVEFORMATEX* pwfxIn, const WAVEFORMATEX* pwfxOut ) const;
+ HRESULT SuggestOutputFormat( WAVEFORMATEX* pwfx ) const;
+
+ HRESULT Process( LONGLONG llSampAudioTimestamp,
+ AudioBuffer* pbufIn,
+ AudioBuffer* pbufOut );
+
+ HRESULT AllocateResources();
+ HRESULT FreeResources();
+
+ int PersistGetSize() const;
+ HRESULT PersistLoad( IStream* pStream );
+ HRESULT PersistSave( IStream* pStream );
+};
+
+#endif // !defined(AFX_AUDIOPLUGIN_H__D9177ACC_DFF4_4C13_8FB9_F949C35BFEF0__INCLUDED_)
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.mak b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.mak
new file mode 100644
index 00000000..09d2403e
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.mak
@@ -0,0 +1,312 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on AudioPlugIn.dsp
+!IF "$(CFG)" == ""
+CFG=AudioPlugIn - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to AudioPlugIn - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "AudioPlugIn - Win32 Release" && "$(CFG)" != "AudioPlugIn - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "AudioPlugIn.mak" CFG="AudioPlugIn - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "AudioPlugIn - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "AudioPlugIn - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "AudioPlugIn - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\AudioPlugIn.dll" ".\custom.bld"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AudioPlugIn.obj"
+ -@erase "$(INTDIR)\AudioPlugIn.pch"
+ -@erase "$(INTDIR)\AudioPlugIn.res"
+ -@erase "$(INTDIR)\AudioPlugInPropPage.obj"
+ -@erase "$(INTDIR)\Filter.obj"
+ -@erase "$(INTDIR)\MediaParams.obj"
+ -@erase "$(INTDIR)\ParamEnvelope.obj"
+ -@erase "$(INTDIR)\PlugInApp.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(OUTDIR)\AudioPlugIn.dll"
+ -@erase "$(OUTDIR)\AudioPlugIn.exp"
+ -@erase "$(OUTDIR)\AudioPlugIn.lib"
+ -@erase "custom.bld"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I "include" /I "$(MSSDK)\include" /I "$(MSSDK)\Samples\Multimedia\DirectShow\BaseClasses" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\AudioPlugIn.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\AudioPlugIn.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\AudioPlugIn.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib ole32.lib oleaut32.lib \build\sdks\dxmedia\lib\DMOGUIDS.LIB winmm.lib /nologo /entry:"DllEntryPoint@12" /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\AudioPlugIn.pdb" /machine:I386 /nodefaultlib:"libcmt" /nodefaultlib:"libcmtd" /def:".\AudioPlugIn.def" /out:"$(OUTDIR)\AudioPlugIn.dll" /implib:"$(OUTDIR)\AudioPlugIn.lib"
+DEF_FILE= \
+ ".\AudioPlugIn.def"
+LINK32_OBJS= \
+ "$(INTDIR)\AudioPlugIn.obj" \
+ "$(INTDIR)\AudioPlugInPropPage.obj" \
+ "$(INTDIR)\Filter.obj" \
+ "$(INTDIR)\MediaParams.obj" \
+ "$(INTDIR)\ParamEnvelope.obj" \
+ "$(INTDIR)\PlugInApp.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\AudioPlugIn.res"
+
+"$(OUTDIR)\AudioPlugIn.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+OutDir=.\Release
+TargetName=AudioPlugIn
+InputPath=.\Release\AudioPlugIn.dll
+SOURCE="$(InputPath)"
+
+".\custom.bld" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ regsvr32.exe /s $(OutDir)\$(TargetName).DLL
+ echo >custom.bld
+<<
+
+
+!ELSEIF "$(CFG)" == "AudioPlugIn - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\AudioPlugIn.dll" ".\custom.bld"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AudioPlugIn.obj"
+ -@erase "$(INTDIR)\AudioPlugIn.pch"
+ -@erase "$(INTDIR)\AudioPlugIn.res"
+ -@erase "$(INTDIR)\AudioPlugInPropPage.obj"
+ -@erase "$(INTDIR)\Filter.obj"
+ -@erase "$(INTDIR)\MediaParams.obj"
+ -@erase "$(INTDIR)\ParamEnvelope.obj"
+ -@erase "$(INTDIR)\PlugInApp.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\AudioPlugIn.dll"
+ -@erase "$(OUTDIR)\AudioPlugIn.exp"
+ -@erase "$(OUTDIR)\AudioPlugIn.ilk"
+ -@erase "$(OUTDIR)\AudioPlugIn.lib"
+ -@erase "$(OUTDIR)\AudioPlugIn.pdb"
+ -@erase "custom.bld"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "include" /I "$(MSSDK)\include" /I "$(MSSDK)\Samples\Multimedia\DirectShow\BaseClasses" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\AudioPlugIn.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\AudioPlugIn.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\AudioPlugIn.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib ole32.lib oleaut32.lib \build\sdks\dxmedia\lib\DMOGUIDS.LIB winmm.lib /nologo /entry:"DllEntryPoint@12" /subsystem:windows /dll /incremental:yes /pdb:"$(OUTDIR)\AudioPlugIn.pdb" /debug /machine:I386 /nodefaultlib:"libcmt" /nodefaultlib:"libcmtd" /def:".\AudioPlugIn.def" /out:"$(OUTDIR)\AudioPlugIn.dll" /implib:"$(OUTDIR)\AudioPlugIn.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\AudioPlugIn.def"
+LINK32_OBJS= \
+ "$(INTDIR)\AudioPlugIn.obj" \
+ "$(INTDIR)\AudioPlugInPropPage.obj" \
+ "$(INTDIR)\Filter.obj" \
+ "$(INTDIR)\MediaParams.obj" \
+ "$(INTDIR)\ParamEnvelope.obj" \
+ "$(INTDIR)\PlugInApp.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\AudioPlugIn.res"
+
+"$(OUTDIR)\AudioPlugIn.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+OutDir=.\Debug
+TargetName=AudioPlugIn
+InputPath=.\Debug\AudioPlugIn.dll
+SOURCE="$(InputPath)"
+
+".\custom.bld" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ regsvr32.exe /s $(OutDir)\$(TargetName).DLL
+ echo >custom.bld
+<<
+
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("AudioPlugIn.dep")
+!INCLUDE "AudioPlugIn.dep"
+!ELSE
+!MESSAGE Warning: cannot find "AudioPlugIn.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "AudioPlugIn - Win32 Release" || "$(CFG)" == "AudioPlugIn - Win32 Debug"
+SOURCE=.\AudioPlugIn.cpp
+
+"$(INTDIR)\AudioPlugIn.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\AudioPlugIn.rc
+
+"$(INTDIR)\AudioPlugIn.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+SOURCE=.\AudioPlugInPropPage.cpp
+
+"$(INTDIR)\AudioPlugInPropPage.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\Filter.cpp
+
+"$(INTDIR)\Filter.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\MediaParams.cpp
+
+"$(INTDIR)\MediaParams.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\ParamEnvelope.cpp
+
+"$(INTDIR)\ParamEnvelope.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\PlugInApp.cpp
+
+"$(INTDIR)\PlugInApp.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\AudioPlugIn.pch"
+
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "AudioPlugIn - Win32 Release"
+
+CPP_SWITCHES=/nologo /MD /W3 /GX /O2 /I "." /I "include" /I "$(MSSDK)\include" /I "$(MSSDK)\Samples\Multimedia\DirectShow\BaseClasses" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\AudioPlugIn.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\AudioPlugIn.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "AudioPlugIn - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "include" /I "$(MSSDK)\include" /I "$(MSSDK)\Samples\Multimedia\DirectShow\BaseClasses" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\AudioPlugIn.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\AudioPlugIn.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.rc b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.rc
new file mode 100644
index 00000000..38ba0bd7
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugIn.rc
@@ -0,0 +1,202 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include <windows.h>\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\AudioPlugIn.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "AudioPlugIn DLL\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "AudioPlugIn\0"
+ VALUE "LegalCopyright", "Copyright © 1997\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "AudioPlugIn.DLL\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "AudioPlugIn Dynamic Link Library\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOGEX 0, 0, 343, 222
+STYLE DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_TOOLWINDOW
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_AUTOTICKS |
+ TBS_VERT | WS_TABSTOP,11,70,11,116
+ CONTROL "Slider1",IDC_SLIDER2,"msctls_trackbar32",TBS_AUTOTICKS |
+ TBS_VERT | WS_TABSTOP,51,70,11,116
+ CONTROL "Slider1",IDC_SLIDER3,"msctls_trackbar32",TBS_AUTOTICKS |
+ TBS_VERT | WS_TABSTOP,91,70,11,116
+ EDITTEXT IDC_SLIDER1_LABEL2,24,74,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER1_LABEL3,24,170,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER1_LABEL1,12,189,38,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER2_LABEL2,64,74,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER2_LABEL3,64,170,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER2_LABEL1,52,189,38,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER3_LABEL2,104,74,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER3_LABEL3,104,170,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER3_LABEL1,92,189,38,13,ES_AUTOHSCROLL
+ PUSHBUTTON "Save",IDC_SAVE,185,4,50,14
+ PUSHBUTTON "Help",IDC_SHOWHELP,289,4,50,14
+ EDITTEXT IDC_INIT,183,32,155,43,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
+ EDITTEXT IDC_ONSLIDERCHANGE,183,87,155,41,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN |
+ WS_VSCROLL
+ EDITTEXT IDC_PERSAMPLE,183,141,155,80,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN |
+ WS_VSCROLL
+ GROUPBOX "Signal Processing Controls",IDC_STATIC,3,61,176,159
+ LTEXT "Initialization/format change:",IDC_STATIC,183,22,88,8
+ LTEXT "Per sample (or sample-pair):",IDC_STATIC,183,131,87,8
+ LTEXT "Slider change/initialization:",IDC_STATIC,183,77,85,8
+ LTEXT "",IDC_PRESET,3,32,175,10,SS_SUNKEN
+ LTEXT "Current preset:",IDC_STATIC,3,21,47,8
+ PUSHBUTTON "Load",IDC_LOAD,3,4,41,14
+ PUSHBUTTON "New",IDC_NEW,50,4,41,14
+ PUSHBUTTON "",IDC_EDIT,133,4,46,14
+ CONTROL "Enable processing",IDC_BYPASS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,3,47,74,10
+ CONTROL "Slider1",IDC_SLIDER4,"msctls_trackbar32",TBS_AUTOTICKS |
+ TBS_VERT | WS_TABSTOP,130,70,11,116
+ EDITTEXT IDC_SLIDER4_LABEL2,144,74,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER4_LABEL3,144,170,26,13,ES_AUTOHSCROLL
+ EDITTEXT IDC_SLIDER4_LABEL1,132,189,38,13,ES_AUTOHSCROLL
+ PUSHBUTTON "Trigger 1",IDC_TRIGGER1,12,204,38,11
+ PUSHBUTTON "Trigger 2",IDC_TRIGGER2,52,204,38,11
+ PUSHBUTTON "Trigger 3",IDC_TRIGGER3,92,204,38,11
+ PUSHBUTTON "Trigger 4",IDC_TRIGGER4,132,204,38,11
+END
+
+IDD_EVAL_HELP DIALOG DISCARDABLE 0, 0, 311, 231
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "SPS Expression Help"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Close",IDOK,7,210,50,14
+ EDITTEXT IDC_EDIT1,12,25,286,177,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL
+ CONTROL "Tab1",IDC_TAB1,"SysTabControl32",0x0,7,7,297,200
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_NAME_PLUGIN "Nullsoft SPS DX plugin"
+ IDS_DESC_PLUGIN "SPS"
+ IDS_SETTINGS "Settings"
+ IDS_HELPFILE_PLUGIN "AudioPlugIn.hlp"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "res\AudioPlugIn.rc2" // non-Microsoft Visual C++ edited resources
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.cpp b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.cpp
new file mode 100644
index 00000000..5fbf0bd8
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.cpp
@@ -0,0 +1,326 @@
+// AudioPlugInPropPage.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "resource.h"
+#include "AudioPlugInPropPage.h"
+
+#include <MedParam.h>
+#include "CakeMedParam.h"
+#include "Parameters.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CAudioPlugInPropPage property page
+
+extern HMODULE g_hInst;
+
+SPSEffectContext *g_fucko_ctx;
+
+CAudioPlugInPropPage::CAudioPlugInPropPage( IUnknown* pUnk, HRESULT* phr ) :
+ CUnknown( "AudioPlugInPropPage", pUnk ),
+ m_hWnd( NULL ),
+ m_pMediaParams( NULL ),
+ m_pUICallback( NULL ),
+ m_pPageSite( NULL ),
+ m_bDirty( FALSE )
+{
+ SPS_initcontext(&m_ctx); //FUCKO
+ g_fucko_ctx=&m_ctx;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+CUnknown * WINAPI CAudioPlugInPropPage::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
+{
+ return new CAudioPlugInPropPage( lpunk, phr );
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+CAudioPlugInPropPage::~CAudioPlugInPropPage()
+{
+ if (m_pMediaParams)
+ m_pMediaParams->Release();
+ m_pMediaParams = NULL;
+
+ if (m_pUICallback)
+ m_pUICallback->Release();
+ m_pUICallback = NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CUnknown
+
+HRESULT CAudioPlugInPropPage::NonDelegatingQueryInterface( REFIID riid, void** ppv )
+{
+ if (IID_IUnknown == riid)
+ return GetInterface( (IUnknown*)this, ppv );
+ else if (IID_IPropertyPage == riid)
+ return GetInterface( (IPropertyPage*)this, ppv );
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// IPropertyPage
+
+HRESULT CAudioPlugInPropPage::GetPageInfo( LPPROPPAGEINFO pPageInfo )
+{
+ IMalloc* pIMalloc;
+ if (FAILED( CoGetMalloc( MEMCTX_TASK, &pIMalloc ) ))
+ return E_FAIL;
+
+ pPageInfo->pszTitle = (LPOLESTR)pIMalloc->Alloc( 256 );
+
+ pIMalloc->Release();
+
+ if (!pPageInfo->pszTitle)
+ return E_OUTOFMEMORY;
+
+ static const char szTitle[] = "AudioPlugIn";
+ mbstowcs( pPageInfo->pszTitle, szTitle, strlen( szTitle ) );
+
+ pPageInfo->size.cx = 100;
+ pPageInfo->size.cy = 100;
+ pPageInfo->pszDocString = NULL;
+ pPageInfo->pszHelpFile = NULL;
+ pPageInfo->dwHelpContext= 0;
+
+ // Create the property page in order to determine its size
+ HWND const hWnd = ::CreateDialogParam( g_hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), GetDesktopWindow(), (DLGPROC)StaticDialogProc, 0 );
+ if (hWnd)
+ {
+ // Get the dialog size and destroy the window
+ RECT rc;
+ GetWindowRect( hWnd, &rc );
+ pPageInfo->size.cx = rc.right - rc.left;
+ pPageInfo->size.cy = rc.bottom - rc.top;
+ DestroyWindow( hWnd );
+ }
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::SetObjects( ULONG cObjects, LPUNKNOWN* ppUnk )
+{
+ // Release old interfaces
+ if (m_pMediaParams)
+ m_pMediaParams->Release();
+ m_pMediaParams = NULL;
+ if (m_pUICallback)
+ m_pUICallback->Release();
+ m_pUICallback = NULL;
+
+ // Look for a new IFilter
+ ULONG cObj = 0;
+ for (ULONG i = 0; i < cObjects; ++i)
+ {
+ if (S_OK == ppUnk[i]->QueryInterface( IID_IMediaParams, (void**)&m_pMediaParams ))
+ {
+ ppUnk[i]->QueryInterface( IID_IMediaParamsUICallback, (void**)&m_pUICallback );
+ break;
+ }
+ }
+
+ // Update controls if we've got a new object and we're activated
+ if (m_pMediaParams && ::IsWindow( m_hWnd ))
+ UpdateControls();
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+extern BOOL CALLBACK SPS_configWindowProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
+
+BOOL CALLBACK CAudioPlugInPropPage::StaticDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+#if 0
+ CAudioPlugInPropPage* pPage;
+
+ if (WM_INITDIALOG == uMsg)
+ {
+ SetWindowLong( hwnd, DWL_USER, lParam );
+ pPage = reinterpret_cast<CAudioPlugInPropPage*>(lParam);
+ if (!pPage)
+ return TRUE;
+ }
+
+ pPage = reinterpret_cast<CAudioPlugInPropPage*>(GetWindowLong( hwnd, DWL_USER ));
+ if (!pPage)
+ return TRUE;
+
+ return pPage->DialogProc( hwnd, uMsg, wParam, lParam );
+#endif
+ return SPS_configWindowProc(hwnd, uMsg, wParam,lParam);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+BOOL CAudioPlugInPropPage::DialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ //return SPS_configWindowProc(hwnd, uMsg, wParam,lParam);
+ return 0;
+
+/* switch( uMsg )
+ {
+ case WM_INITDIALOG:
+ m_hWnd = hwnd;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;*/
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void CAudioPlugInPropPage::UpdateControls()
+{
+ // TODO: update all UI elements to reflect new control state
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Activate( HWND hwndParent, LPCRECT pRect, BOOL fModal )
+{
+ if (!pRect)
+ return E_POINTER;
+ if (NULL != m_hWnd)
+ return E_UNEXPECTED; // already active!
+
+ m_hWnd = CreateDialogParam( g_hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), hwndParent, (DLGPROC)StaticDialogProc, (LPARAM)&m_ctx );
+ if (!m_hWnd)
+ return E_OUTOFMEMORY;
+
+ // Refresh the property page controls
+ UpdateControls();
+
+ // Move page into position and show it
+ Move( pRect );
+ Show( SW_SHOWNORMAL );
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Move( LPCRECT pRect )
+{
+ if (!pRect)
+ return E_POINTER;
+ if (NULL == m_hWnd)
+ E_UNEXPECTED;
+
+ MoveWindow( m_hWnd, pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top, TRUE );
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Show( UINT nCmdShow )
+{
+ if (NULL == m_hWnd)
+ E_UNEXPECTED;
+ // Ignore wrong show flags
+ if (nCmdShow != SW_SHOW && nCmdShow != SW_SHOWNORMAL && nCmdShow != SW_HIDE)
+ return E_INVALIDARG;
+
+ ShowWindow( m_hWnd, nCmdShow );
+
+ if (SW_SHOWNORMAL == nCmdShow || SW_SHOW == nCmdShow)
+ {
+ // TODO: set the focus to which control needs it
+ }
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Deactivate()
+{
+ if (NULL == m_hWnd)
+ return E_UNEXPECTED;
+
+ DestroyWindow( m_hWnd );
+ m_hWnd = NULL;
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::SetPageSite( LPPROPERTYPAGESITE pPageSite )
+{
+ if (pPageSite)
+ {
+ if (m_pPageSite)
+ return E_UNEXPECTED;
+ m_pPageSite = pPageSite;
+ m_pPageSite->AddRef();
+ }
+ else
+ {
+ if (m_pPageSite == NULL)
+ return E_UNEXPECTED;
+ m_pPageSite->Release();
+ m_pPageSite = NULL;
+ }
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Apply()
+{
+ // Take no action except clearing the dirty flag.
+ // So that the property page may be used in realtime, all user interface
+ // changes are immediately passed to the filter. I.e. there is no Cancel.
+ m_bDirty = FALSE;
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::IsPageDirty( void )
+{
+ return m_bDirty ? S_OK : S_FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::Help( LPCWSTR lpszHelpDir )
+{
+ // Get location of DLL
+ char szDLL[ _MAX_PATH ];
+ if (0 == ::GetModuleFileName( g_hInst, szDLL, sizeof szDLL ))
+ return E_FAIL;
+
+ // Convert to location of .HLP file
+ char szHelp[ _MAX_PATH ];
+ ::strncpy( szHelp, szDLL, ::strlen( szDLL ) - 3 );
+ ::strcat( szHelp, "HLP" );
+
+ // Call help
+ if (::WinHelp( m_hWnd, szHelp, HELP_CONTENTS, NULL ))
+ return S_OK;
+
+ return E_FAIL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT CAudioPlugInPropPage::TranslateAccelerator( LPMSG lpMsg )
+{
+ return E_NOTIMPL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.h b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.h
new file mode 100644
index 00000000..10485990
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/AudioPlugInPropPage.h
@@ -0,0 +1,68 @@
+#ifndef _PLUGIN_PROP_PAGE_H_
+#define _PLUGIN_PROP_PAGE_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "../sps_common.h"
+
+struct IMediaParams;
+struct IMediaParamsUICallback;
+
+/////////////////////////////////////////////////////////////////////////////
+// CAudioPlugInPropPage dialog
+
+class CAudioPlugInPropPage :
+ public CUnknown,
+ public IPropertyPage
+{
+// Construction
+public:
+ CAudioPlugInPropPage( IUnknown* pUnk, HRESULT* phr );
+ virtual ~CAudioPlugInPropPage();
+
+ // CUnknown
+ DECLARE_IUNKNOWN;
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv);
+
+ // *** IPropertyPage methods ***
+ STDMETHODIMP_(HRESULT) SetPageSite(LPPROPERTYPAGESITE pPageSite);
+ STDMETHODIMP_(HRESULT) Activate(HWND hwndParent, LPCRECT prect, BOOL fModal);
+ STDMETHODIMP_(HRESULT) Deactivate(void);
+ STDMETHODIMP_(HRESULT) GetPageInfo(LPPROPPAGEINFO pPageInfo);
+ STDMETHODIMP_(HRESULT) SetObjects(ULONG cObjects, LPUNKNOWN *ppUnk);
+ STDMETHODIMP_(HRESULT) Show(UINT nCmdShow);
+ STDMETHODIMP_(HRESULT) Move(LPCRECT prect);
+ STDMETHODIMP_(HRESULT) IsPageDirty(void);
+ STDMETHODIMP_(HRESULT) Apply(void);
+ STDMETHODIMP_(HRESULT) Help(LPCWSTR lpszHelpDir);
+ STDMETHODIMP_(HRESULT) TranslateAccelerator(LPMSG lpMsg);
+
+public:
+
+ static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
+
+// Implementation
+protected:
+
+ void UpdateControls();
+ BOOL DialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+ static BOOL CALLBACK StaticDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+private:
+
+ HWND m_hWnd;
+ BOOL m_bDirty;
+ IPropertyPageSite* m_pPageSite;
+ IMediaParams* m_pMediaParams;
+ IMediaParamsUICallback* m_pUICallback;
+
+ SPSEffectContext m_ctx;
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // _PLUGIN_PROP_PAGE_H_
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/Filter.cpp b/Src/Plugins/DSP/dsp_sps/dxi/Filter.cpp
new file mode 100644
index 00000000..35fef3a7
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/Filter.cpp
@@ -0,0 +1,1139 @@
+// Filter.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "resource.h"
+#include <mediaerr.h>
+#include <initguid.h>
+#include <DeferZeroFill.h>
+#include <malloc.h>
+#include "Filter.h"
+#include "AudioPlugInPropPage.h"
+
+#ifdef _DEBUG
+#pragma comment(lib, "strmbasd.lib")
+#pragma comment(lib, "asynbased.lib")
+#else
+#pragma comment(lib, "strmbase.lib")
+#endif
+
+#include "PlugInGUIDs.h"
+
+#define PLUGTITLE L"Nullsoft SPS Plug-In"
+
+/////////////////////////////////////////////////////////////////////////////
+// Setup data
+
+static AMOVIESETUP_MEDIATYPE sudPinTypes =
+{
+ &MEDIATYPE_Audio, // Major CLSID
+ &MEDIASUBTYPE_NULL // Minor type
+};
+
+static AMOVIESETUP_PIN psudPins[] =
+{
+ { L"Input", // Pin's string name
+ FALSE, // Is it rendered
+ FALSE, // Is it an output
+ FALSE, // Allowed none
+ FALSE, // Allowed many
+ &CLSID_NULL, // Connects to filter
+ L"Output", // Connects to pin
+ 1, // Number of types
+ &sudPinTypes }, // Pin information
+ { L"Output", // Pin's string name
+ FALSE, // Is it rendered
+ TRUE, // Is it an output
+ FALSE, // Allowed none
+ FALSE, // Allowed many
+ &CLSID_NULL, // Connects to filter
+ L"Input", // Connects to pin
+ 1, // Number of types
+ &sudPinTypes } // Pin information
+};
+
+static AMOVIESETUP_FILTER sudFilter =
+{
+ &CLSID_Filter, // CLSID of filter
+ PLUGTITLE, // Filter's name
+ MERIT_DO_NOT_USE, // Filter merit
+ 2, // Number of pins
+ psudPins // Pin information
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+CFactoryTemplate g_Templates[ 2 ] =
+{
+ { PLUGTITLE
+ , &CLSID_Filter
+ , CFilter::CreateInstance
+ , NULL
+ , &sudFilter }
+ ,
+ { L"AudioPlugIn Properties"
+ , &CLSID_FilterPropPage
+ , CAudioPlugInPropPage::CreateInstance
+ , NULL
+ , NULL }
+};
+
+int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
+
+//--------------------------------------------------------------------------------
+// Helper function to notify the graph about pin changes
+
+static void notifyGraphChanged( IFilterGraph* pGraph )
+{
+ if (pGraph)
+ {
+ IMediaEventSink* pSink = NULL;
+ if (S_OK == pGraph->QueryInterface( IID_IMediaEventSink, (void**)&pSink ))
+ {
+ pSink->Notify( EC_GRAPH_CHANGED, 0, 0 );
+ pSink->Release();
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// CFilter
+////////////////////////////////////////////////////////////////////////////////
+
+//--------------------------------------------------------------------------------
+// Ctor
+
+CFilter::CFilter( TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr ) :
+ CBaseFilter( pName, pUnk, this, CLSID_Filter, phr ),
+ CPersistStream( pUnk, phr ),
+ CAudioPlugIn( phr ),
+ m_pinInput( NAME("Input"), this, phr, L"Input" ),
+ m_pinOutput( NAME("Output"), this, phr, L"Output" ),
+ m_llSamplePosition( 0 )
+{
+ if (SUCCEEDED( *phr ))
+ {
+ // Create our DirectX automation helper object
+ *phr = CMediaParams::Create( &m_pMediaParams, (IUnknown*)(IBaseFilter*)this );
+ }
+
+ if (SUCCEEDED( *phr ))
+ {
+ // Initialize the plug-in
+ *phr = Initialize();
+ }
+}
+
+
+//------------------------------------------------------------------------------
+// Factory-style construction
+
+CUnknown * WINAPI CFilter::CreateInstance( LPUNKNOWN pUnk, HRESULT* phr )
+{
+ return new CFilter( NAME("Filter"), pUnk, phr );
+}
+
+
+//--------------------------------------------------------------------------------
+// Expose setup data for registration
+
+LPAMOVIESETUP_FILTER CFilter::GetSetupData()
+{
+ return &sudFilter;
+}
+
+
+//--------------------------------------------------------------------------------
+// Expose other interfaces to the world
+
+STDMETHODIMP CFilter::NonDelegatingQueryInterface( REFIID riid, void** ppv )
+{
+ if (riid == IID_IDispatch)
+ return GetInterface((IDispatch*)this, ppv);
+ else if (riid == IID_ISpecifyPropertyPages)
+ return GetInterface((ISpecifyPropertyPages*)this, ppv);
+ else if (riid == IID_IPersistStream)
+ return GetInterface((IPersistStream*)this, ppv);
+ else if (NULL != m_pMediaParams)
+ {
+ if (riid == IID_IMediaParams)
+ return GetInterface((IMediaParams*)m_pMediaParams, ppv);
+ else if (riid == IID_IMediaParamInfo)
+ return GetInterface((IMediaParamInfo*)m_pMediaParams, ppv);
+ else if (riid == IID_IMediaParamsSetUICallback)
+ return GetInterface((IMediaParamsSetUICallback*)m_pMediaParams, ppv);
+ else if (riid == IID_IMediaParamsUICallback)
+ return GetInterface((IMediaParamsUICallback*)m_pMediaParams, ppv);
+ }
+
+ return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
+}
+
+
+//--------------------------------------------------------------------------------
+// CFilter dtor
+
+CFilter::~CFilter()
+{
+ if (m_pMediaParams)
+ m_pMediaParams->Release(), m_pMediaParams = NULL;
+}
+
+
+//--------------------------------------------------------------------------------
+// Get the total number of pins in our filter
+
+int CFilter::GetPinCount()
+{
+ return 2;
+}
+
+
+//--------------------------------------------------------------------------------
+// Get the Nth pin from our filter (CBaseFilter pure virtual override)
+// Pin 0 is the input pin and all others are output pins
+
+CBasePin* CFilter::GetPin( int n )
+{
+ if (0 == n)
+ return &m_pinInput;
+ else if (1 == n)
+ return &m_pinOutput;
+ else
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------
+// Helper for checking media types
+
+HRESULT CFilter::CheckMediaType( PIN_DIRECTION pinDir, const CMediaType* pmt )
+{
+ if (NULL == pmt)
+ return E_POINTER;
+
+ // Must be audio
+ if (pmt->majortype != MEDIATYPE_Audio)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ // Must not be compressed
+ if (pmt->bTemporalCompression)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ // Must be WAVEFORMATEX
+ if (pmt->cbFormat < sizeof(WAVEFORMATEX))
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ WAVEFORMATEX* pwfx = reinterpret_cast<WAVEFORMATEX*>( pmt->Format() );
+
+ // Must be 16-bit PCM or 32-bit float
+ BOOL const bInt16 =
+ (WAVE_FORMAT_PCM == pwfx->wFormatTag && 16 == pwfx->wBitsPerSample) ||
+ (WAVE_FORMAT_EXTENSIBLE == pwfx->wFormatTag && 16 == pwfx->wBitsPerSample);
+ BOOL const bFloat32 =
+ (WAVE_FORMAT_IEEE_FLOAT == pwfx->wFormatTag && 32 == pwfx->wBitsPerSample);
+ if (!bInt16 && !bFloat32)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ // Must be mono or stereo
+ if (1 != pwfx->nChannels && 2 != pwfx->nChannels)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ // Let the plug-in decide the rest
+ if (PINDIR_INPUT == pinDir)
+ return IsValidInputFormat( pwfx );
+ else
+ return IsValidOutputFormat( pwfx );
+}
+
+
+//--------------------------------------------------------------------------------
+// CheckTransform
+
+HRESULT CFilter::CheckTransform( const CMediaType* pmtIn, const CMediaType* pmtOut )
+{
+ if (NULL == pmtIn)
+ return E_POINTER;
+ if (NULL == pmtOut)
+ return E_POINTER;
+
+ // Make sure input/output types are valid
+ HRESULT hr = S_OK;
+ hr = CheckMediaType( PINDIR_INPUT, pmtIn );
+ if (FAILED( hr ))
+ return hr;
+ hr = CheckMediaType( PINDIR_OUTPUT, pmtOut );
+ if (FAILED( hr ))
+ return hr;
+
+ // Make sure sample rates are the same
+ WAVEFORMATEX* pwfxIn = reinterpret_cast<WAVEFORMATEX*>( pmtIn->Format() );
+ WAVEFORMATEX* pwfxOut = reinterpret_cast<WAVEFORMATEX*>( pmtOut->Format() );
+ if (pwfxIn->nSamplesPerSec != pwfxOut->nSamplesPerSec)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ // Let the plug-in decide for sure
+ return IsValidTransform( pwfxIn, pwfxOut );
+}
+
+
+//--------------------------------------------------------------------------------
+// GetMediaType
+
+HRESULT CFilter::GetMediaType( int iPosition, CMediaType* pmt )
+{
+ if (!m_pinInput.IsConnected())
+ return E_UNEXPECTED;
+
+ if (iPosition < 0)
+ return E_INVALIDARG;
+
+ if (iPosition > 0)
+ return VFW_S_NO_MORE_ITEMS;
+
+ // Get pointers to input/ouput formats
+ WAVEFORMATEX* pwfxIn = reinterpret_cast<WAVEFORMATEX*>( m_pinInput.CurrentMediaType().Format() );
+ if (NULL == pwfxIn)
+ return E_FAIL;
+ WAVEFORMATEX* pwfxOut = reinterpret_cast<WAVEFORMATEX*>( pmt->Format() );
+ if (NULL == pwfxOut)
+ return E_FAIL;
+
+ // Assume output format is the same as input format
+ *pwfxOut = *pwfxIn;
+
+ // let the plug-in suggest something different
+ return SuggestOutputFormat( pwfxOut );
+}
+
+
+//--------------------------------------------------------------------------------
+// SetMediaType
+
+HRESULT CFilter::SetMediaType( PIN_DIRECTION pindir, const CMediaType* pmt )
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ // Make sure it's a valid audio type
+ hr = CheckMediaType( pindir, pmt );
+ if (S_OK != hr)
+ return hr;
+
+ if (PINDIR_INPUT == pindir)
+ m_wfxIn = *reinterpret_cast<WAVEFORMATEX*>( pmt->Format() );
+ else if (PINDIR_OUTPUT == pindir)
+ m_wfxOut = *reinterpret_cast<WAVEFORMATEX*>( pmt->Format() );
+
+ m_pMediaParams->SetSampleRate( m_wfxIn.nSamplesPerSec );
+
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// Run: Overriden to handle no input connections, and to notify the plug-in
+
+STDMETHODIMP CFilter::Run( REFERENCE_TIME tStart )
+{
+ CAutoLock cObjectLock(m_pLock);
+
+ CBaseFilter::Run( tStart );
+ if (!m_pinInput.IsConnected())
+ m_pinInput.EndOfStream();
+
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// Pause: Overriden to handle no input connections, and to notify the plug-in
+
+STDMETHODIMP CFilter::Pause()
+{
+ CAutoLock cObjectLock(m_pLock);
+
+ if (State_Paused == m_State)
+ return S_OK; // nothing to do
+
+ BOOL const bPreRoll = (State_Stopped == m_State);
+
+ // Set this to something in case we never see a media sample timestamp
+ m_llSamplePosition = 0;
+
+ // Let the base-class do the real pausing
+ HRESULT hr = CBaseFilter::Pause();
+
+ // Deal with unexpected disconnect
+ if (!m_pinInput.IsConnected())
+ m_pinInput.EndOfStream();
+
+ if (bPreRoll && SUCCEEDED( hr ))
+ hr = AllocateResources();
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// Stop: Overriden to handle no input connections, and to notify the plug-in
+
+STDMETHODIMP CFilter::Stop()
+{
+ CAutoLock cObjectLock(m_pLock);
+
+ if (State_Stopped == m_State)
+ return S_OK; // nothing to do
+
+ // Let the base-class do the real stopping
+ HRESULT hr = CBaseFilter::Stop();
+ if (SUCCEEDED( hr ))
+ hr = FreeResources();
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// Initialize an AudioBuffer and IMediaSample for an output pin.
+
+HRESULT CFilter::getOutputBuffer( CFilterOutputPin* pOutputPin,
+ AudioBuffer* pbufOut,
+ REFERENCE_TIME* prtStart,
+ BOOL bSyncPoint, BOOL bDiscontinuity, BOOL bPreroll )
+{
+ if (NULL == pOutputPin)
+ return E_POINTER;
+ if (NULL == pbufOut)
+ return E_POINTER;
+ if (!pOutputPin->IsConnected())
+ return E_UNEXPECTED;
+
+ // Ask our output pin to allocate an output media sample
+ HRESULT hr = pOutputPin->GetDeliveryBuffer( &pbufOut->pms, NULL, NULL, 0 );
+ if (FAILED( hr ))
+ return hr;
+
+ // Set media sample properties
+ pbufOut->pms->SetTime( prtStart, NULL );
+ pbufOut->pms->SetSyncPoint( bSyncPoint );
+ pbufOut->pms->SetDiscontinuity( bDiscontinuity );
+ pbufOut->pms->SetPreroll( bPreroll );
+
+ // Set the output size
+ pbufOut->cSamp = pbufOut->pms->GetSize() / m_wfxOut.nBlockAlign;
+ pbufOut->lOffset = 0;
+
+ // Tag the output buffer as being all zeros
+ pbufOut->SetZerofill( TRUE );
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------
+// Deliver results and cleanup
+
+HRESULT CFilter::deliverOutputBuffer( CFilterOutputPin* pOutputPin,
+ AudioBuffer* pbufOut,
+ HRESULT hrProcess, BOOL bCleanup )
+{
+ if (NULL == pbufOut)
+ return E_POINTER;
+ if (NULL == pbufOut->pms)
+ return E_POINTER;
+ if (!pOutputPin->IsConnected())
+ return E_UNEXPECTED;
+
+ HRESULT hr = S_OK;
+
+ // Deliver only if we need to
+ if (S_OK == hrProcess)
+ {
+ if (pbufOut->GetZerofill())
+ {
+ // If the output buffer support IDeferZeroFill, there is nothing more
+ // that we need to do to zerofill it: the zerofill will occur when some
+ // downstream filter attempts to get the media sample's buffer pointer.
+ // buffer fill if possible.
+ IDeferZeroFill* pdzf = NULL;
+ if (S_OK == pbufOut->pms->QueryInterface( IID_IDeferZeroFill, (void**)&pdzf ))
+ {
+ pdzf->Release();
+ }
+ else
+ {
+ // AudioBuffer::GetPointer will handle any zerofill for us.
+ pbufOut->GetPointer();
+ }
+ }
+
+ // Set the final output sample size
+ hr = pbufOut->pms->SetActualDataLength( pbufOut->cSamp * m_wfxOut.nBlockAlign );
+ if (SUCCEEDED( hr ))
+ {
+ // Tell the current output pin to deliver this sample
+ hr = pOutputPin->Deliver( pbufOut->pms );
+ }
+ }
+ else if (S_FALSE == hrProcess)
+ {
+ hr = pOutputPin->DeliverEndOfStream();
+ }
+
+ // Release the media sample once we're done with it
+ if (bCleanup)
+ {
+ pbufOut->pms->Release();
+ pbufOut->pms = NULL;
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// ISpecifyPropertyPages
+
+STDMETHODIMP CFilter::GetPages(CAUUID *pPages)
+{
+ if (NULL == pPages)
+ return E_POINTER;
+
+ pPages->cElems = 1;
+ pPages->pElems= (GUID*) CoTaskMemAlloc( sizeof(GUID) );
+
+ if (pPages->pElems==NULL)
+ return E_OUTOFMEMORY;
+
+ pPages->pElems[0] = CLSID_FilterPropPage;
+
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// CPersistStream
+
+STDMETHODIMP CFilter::GetClassID(CLSID* pClsid)
+{
+ if (NULL == pClsid)
+ return E_POINTER;
+ *pClsid = CLSID_Filter;
+ return NOERROR;
+}
+
+int CFilter::SizeMax()
+{
+ return PersistGetSize();
+}
+
+HRESULT CFilter::WriteToStream(IStream* pStream)
+{
+ CAutoLock cObjectLock(m_pLock);
+
+ return PersistSave( pStream );
+}
+
+HRESULT CFilter::ReadFromStream(IStream* pStream)
+{
+ CAutoLock cObjectLock(m_pLock);
+
+ return PersistLoad( pStream );
+}
+
+
+//--------------------------------------------------------------------------------
+// IDispatch is exposed only so MFC's COlePropertyPage can connect; ever single
+// method is not implemented.
+
+HRESULT CFilter::GetTypeInfoCount( UINT* )
+{
+ return E_NOTIMPL;
+}
+
+HRESULT CFilter::GetTypeInfo( UINT, LCID, ITypeInfo** )
+{
+ return E_NOTIMPL;
+}
+
+HRESULT CFilter::GetIDsOfNames( REFIID, OLECHAR**, UINT, LCID, DISPID* )
+{
+ return E_NOTIMPL;
+}
+
+HRESULT CFilter::Invoke( DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT* )
+{
+ return E_NOTIMPL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// CFilterInputPin
+//////////////////////////////////////////////////////////////////////////////////
+
+//--------------------------------------------------------------------------------
+// Ctor
+
+CFilterInputPin::CFilterInputPin( TCHAR* pObjDesc, CFilter* pFilter, HRESULT* phr, LPCWSTR pPinName ) :
+ CBaseInputPin( pObjDesc, pFilter, pFilter, phr, pPinName ),
+ m_pFilter( pFilter ),
+ m_bInsideCheckMediaType( FALSE )
+{
+ ASSERT( pFilter );
+}
+
+
+//--------------------------------------------------------------------------------
+// CheckMediaType
+
+HRESULT CFilterInputPin::CheckMediaType( const CMediaType* pmt )
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ // If we are already inside checkmedia type for this pin, return NOERROR.
+ // It is possble to hookup two of the these filters and some other filter
+ // like the video effects sample to get into this situation. If we don't
+ // detect this situation, we will carry on looping till we blow the stack.
+
+ if (m_bInsideCheckMediaType)
+ return NOERROR;
+
+ m_bInsideCheckMediaType = TRUE;
+
+ // See if the wave format is supported
+ hr = m_pFilter->CheckMediaType( PINDIR_INPUT, pmt );
+ if (S_OK != hr)
+ {
+ m_bInsideCheckMediaType = FALSE;
+ return hr;
+ }
+
+ // Make sure the output pin agrees on the type
+ if (m_pFilter->m_pinOutput.IsConnected())
+ {
+ // See if we can transform from input to the current output type
+ const CMediaType& mtOut = m_pFilter->m_pinOutput.CurrentMediaType();
+ hr = m_pFilter->CheckTransform( pmt, &mtOut );
+ if (FAILED( hr ))
+ {
+ m_bInsideCheckMediaType = FALSE;
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
+ }
+
+ // Either all the downstream pins have accepted or there are none.
+ m_bInsideCheckMediaType = FALSE;
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// Set the media type for this connection
+
+HRESULT CFilterInputPin::SetMediaType( const CMediaType* pmtIn )
+{
+ // Set the base class media type (should always succeed)
+ HRESULT hr = CBaseInputPin::SetMediaType( pmtIn );
+ ASSERT( SUCCEEDED( hr ) );
+
+ // Check the transform can be done (should always succeed)
+ hr = m_pFilter->CheckMediaType( PINDIR_INPUT, pmtIn );
+ ASSERT( SUCCEEDED( hr ) );
+
+ return m_pFilter->SetMediaType( PINDIR_INPUT, pmtIn );
+}
+
+
+//--------------------------------------------------------------------------------
+// CompleteConnect: Negotiate possible reconnection if types don't match
+
+HRESULT CFilterInputPin::CompleteConnect( IPin* pRecievePin )
+{
+ HRESULT hr = S_OK;
+
+ const CMediaType& mtIn = m_pFilter->m_pinInput.CurrentMediaType();
+
+ if (m_pFilter->m_pinOutput.IsConnected())
+ {
+ const CMediaType& mtOut = m_pFilter->m_pinOutput.CurrentMediaType();
+ hr = m_pFilter->CheckTransform( &mtIn, &mtOut );
+ if (FAILED( hr ))
+ {
+ if (NULL == m_pFilter->m_pGraph)
+ hr = VFW_E_NOT_IN_GRAPH;
+ else
+ hr = m_pFilter->m_pGraph->Reconnect( &m_pFilter->m_pinOutput );
+ }
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// Receive: override to send message to all downstream pins
+
+HRESULT CFilterInputPin::Receive( IMediaSample* pms )
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ ASSERT( pms );
+
+ // Grab the time stamp on discontinuity samples. We'll synthesize
+ // time stamps for all the rest.
+ REFERENCE_TIME rtStart = 0;
+ REFERENCE_TIME* prtStart = NULL;
+ if (S_OK == pms->IsDiscontinuity())
+ {
+ REFERENCE_TIME rtEnd;
+ HRESULT hrGetTime = pms->GetTime( &rtStart, &rtEnd );
+ if (S_OK == hrGetTime || VFW_S_NO_STOP_TIME == hrGetTime)
+ {
+ m_pFilter->m_llSamplePosition = (rtStart * m_pFilter->m_wfxIn.nSamplesPerSec) / UNITS;
+ prtStart = &rtStart;
+ }
+ }
+
+ // Determine the total number of samples to be processed
+ long const cSampTotal = pms->GetActualDataLength() / m_pFilter->m_wfxIn.nBlockAlign;
+
+ // Set up an input AudioBuffer
+ AudioBuffer bufIn;
+ bufIn.cSamp = cSampTotal;
+ bufIn.pms = pms;
+
+ // Check to see if the input buffer is defer zero fill
+ IDeferZeroFill* pdzf = NULL;
+ if (S_OK == pms->QueryInterface( IID_IDeferZeroFill, (void**)&pdzf ))
+ {
+ bufIn.SetZerofill( pdzf->get_NeedsZerofill() );
+ pdzf->Release();
+ }
+ else
+ bufIn.SetZerofill( FALSE );
+
+ // Determine the set of decimation points for processing
+ long const lFs = m_pFilter->m_wfxIn.nSamplesPerSec;
+ int const cbSampIn = m_pFilter->m_wfxIn.nBlockAlign;
+ int const cbSampOut = m_pFilter->m_wfxOut.nBlockAlign;
+ std::vector<LONGLONG> samplePos;
+ hr = m_pFilter->m_pMediaParams->GetDecimationTimes( m_pFilter->m_llSamplePosition, m_pFilter->m_llSamplePosition + bufIn.cSamp, &samplePos );
+ if (FAILED( hr ))
+ return hr;
+
+ AudioBuffer* pbufOut;
+
+#if PROCESS_IN_PLACE
+
+ // Make sure we don't double-release the shared media sample
+ bufIn.pms->AddRef();
+
+ // Point to the same input buffer
+ pbufOut = &bufIn;
+
+#else // !PROCESS_IN_PLACE
+
+ AudioBuffer bufOut;
+
+ // Get a brand new output buffer
+ hr = m_pFilter->getOutputBuffer( &m_pFilter->m_pinOutput, &bufOut, prtStart,
+ S_OK == pms->IsSyncPoint(),
+ S_OK == pms->IsDiscontinuity(),
+ S_OK == pms->IsPreroll() );
+ if (FAILED( hr ))
+ return hr;
+
+ // Set output buffer size = input buffer size
+ bufOut.cSamp = cSampTotal;
+
+ // Point to this brand new output buffer
+ pbufOut = &bufOut;
+
+#endif // PROCESS_IN_PLACE
+
+ HRESULT hrProcess = S_OK;
+ LONGLONG llPrevPos = m_pFilter->m_llSamplePosition;
+ LONGLONG llCurrPos = llPrevPos;
+ long cSampDone = 0;
+ for (std::vector<LONGLONG>::iterator it = samplePos.begin(); it != samplePos.end(); it++)
+ {
+ // Get the next "landmark", i.e., the next point in time where either a
+ // shape starts or ends, or where we periodically decimate.
+ llCurrPos = *it;
+
+ // Position all automation parameters
+ hr = m_pFilter->m_pMediaParams->UpdateValuesForSample( llPrevPos );
+ if (FAILED( hr ))
+ return hr;
+
+ // Don't process if we haven't changed position
+ if (llCurrPos == llPrevPos)
+ continue;
+
+ // Determine the number of samples processed in this iteration
+ long const cSampIter = long( min( llCurrPos - llPrevPos, cSampTotal - cSampDone ) );
+ if (0 == cSampIter)
+ continue; // nothing to do this iteration
+
+ // Set the buffer sizes and offsets
+ bufIn.cSamp = cSampIter;
+
+#if !PROCESS_IN_PLACE
+ pbufOut->cSamp = bufIn.cSamp;
+#endif
+
+ // Process the audio
+ hrProcess = m_pFilter->Process( llPrevPos, &bufIn, pbufOut );
+ if (FAILED( hrProcess ))
+ break;
+
+ // Update buffer offsets
+ bufIn.lOffset += (cSampIter * cbSampIn);
+ ASSERT( bufIn.lOffset <= (cSampTotal * cbSampIn) );
+
+#if !PROCESS_IN_PLACE
+ pbufOut->lOffset += (cSampIter * cbSampOut);
+ ASSERT( pbufOut->lOffset <= (cSampTotal * cbSampOut) );
+#endif
+
+ // On to the next...
+ llPrevPos = llCurrPos;
+ cSampDone += cSampIter;
+ }
+
+ // Process the final buffer
+ if (SUCCEEDED( hrProcess ) && cSampDone < cSampTotal)
+ {
+ // Position all automation parameters
+ hr = m_pFilter->m_pMediaParams->UpdateValuesForSample( llPrevPos );
+ if (FAILED( hr ))
+ return hr;
+
+ // Set the final buffer size
+ bufIn.cSamp = cSampTotal - cSampDone;
+
+#if !PROCESS_IN_PLACE
+ pbufOut->cSamp = bufIn.cSamp;
+#endif
+
+ // Process the audio
+ hrProcess = m_pFilter->Process( llPrevPos, &bufIn, pbufOut );
+ }
+
+ // Deliver results and cleanup
+ pbufOut->lOffset = 0;
+ pbufOut->cSamp = cSampTotal;
+ hr = m_pFilter->deliverOutputBuffer( &m_pFilter->m_pinOutput, pbufOut, hrProcess, TRUE );
+
+ // Propagate any failures in processing
+ if (FAILED( hrProcess ))
+ hr = hrProcess;
+
+ // Update our position
+ m_pFilter->m_llSamplePosition += cSampTotal;
+
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// EndOfStream: override to send message to all downstream pins
+
+HRESULT CFilterInputPin::EndOfStream()
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ // Get an output buffer
+ AudioBuffer bufOut;
+ hr = m_pFilter->getOutputBuffer( &m_pFilter->m_pinOutput, &bufOut,
+ NULL, FALSE, FALSE, FALSE );
+ if (FAILED( hr ))
+ return hr;
+
+ int const cSamp = bufOut.cSamp;
+
+ // Deliver buffers until the entire flush is complete
+ for (;;)
+ {
+ // Process the audio
+ HRESULT hrProcess = m_pFilter->Process( m_pFilter->m_llSamplePosition, NULL, &bufOut );
+
+ // Deliver results, but don't cleanup yet
+ hr = m_pFilter->deliverOutputBuffer( &m_pFilter->m_pinOutput, &bufOut, hrProcess, FALSE );
+
+ // Propagate any failures in processing
+ if (FAILED( hrProcess ))
+ hr = hrProcess;
+
+ // Stop at end-of-stream or failure
+ if (S_FALSE == hrProcess || FAILED( hr ))
+ break;
+
+ // Update our position
+ m_pFilter->m_llSamplePosition += cSamp;
+ }
+
+ // Clean up output buffer memory
+ m_pFilter->deliverOutputBuffer( &m_pFilter->m_pinOutput, &bufOut, S_FALSE, TRUE );
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// BeginFlush: override to send message to all downstream pins
+
+HRESULT CFilterInputPin::BeginFlush()
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ if (m_pFilter->m_pinOutput.IsConnected())
+ {
+ hr = m_pFilter->m_pinOutput.DeliverBeginFlush();
+ if (FAILED( hr ))
+ return hr;
+ }
+
+ return CBaseInputPin::BeginFlush();
+}
+
+
+//--------------------------------------------------------------------------------
+// EndFlush: override to send message to all downstream pins
+
+HRESULT CFilterInputPin::EndFlush()
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ if (m_pFilter->m_pinOutput.IsConnected())
+ {
+ hr = m_pFilter->m_pinOutput.DeliverEndFlush();
+ if (FAILED( hr ))
+ return hr;
+ }
+
+ return CBaseInputPin::EndFlush();
+}
+
+
+//--------------------------------------------------------------------------------
+// NewSegment: override to send message to all downstream pins
+
+HRESULT CFilterInputPin::NewSegment( REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate )
+{
+ CAutoLock autoLock(m_pLock);
+ HRESULT hr = NOERROR;
+
+ if (m_pFilter->m_pinOutput.IsConnected())
+ {
+ hr = m_pFilter->m_pinOutput.DeliverNewSegment( tStart, tStop, dRate );
+ if (FAILED( hr ))
+ return hr;
+ }
+
+ return CBaseInputPin::NewSegment( tStart, tStop, dRate );
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// CFilterOutputPin
+//////////////////////////////////////////////////////////////////////////////////
+
+DWORD CFilterOutputPin::m_idNext = 1;
+
+//--------------------------------------------------------------------------------
+// Ctor
+
+CFilterOutputPin::CFilterOutputPin( TCHAR* pObjDesc,
+ CFilter* pFilter,
+ HRESULT* phr,
+ LPCWSTR pPinName ) :
+ CBaseOutputPin( pObjDesc, pFilter, pFilter, phr, pPinName ),
+ m_pFilter( pFilter ),
+ m_bInsideCheckMediaType( FALSE ),
+ m_id( 0 ),
+ m_pPosition( NULL )
+{
+ m_id = m_idNext;
+ m_idNext++;
+}
+
+CFilterOutputPin::~CFilterOutputPin()
+{
+ if (m_pPosition)
+ m_pPosition->Release();
+ m_pPosition = NULL;
+}
+
+
+//--------------------------------------------------------------------------------
+// NonDelegatingQueryInterface - Overriden to expose IMediaPosition and
+// IMediaSeeking control interfaces
+
+STDMETHODIMP CFilterOutputPin::NonDelegatingQueryInterface( REFIID riid, void**ppv )
+{
+ CheckPointer( ppv, E_POINTER );
+ ValidateReadWritePtr( ppv, sizeof(PVOID) );
+ *ppv = NULL;
+
+ if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking)
+ {
+ // Create the interface now if we haven't yet
+ if (m_pPosition == NULL)
+ {
+ HRESULT hr = CreatePosPassThru( GetOwner(), FALSE, &m_pFilter->m_pinInput, &m_pPosition );
+ if (FAILED( hr ))
+ return hr;
+ }
+ return m_pPosition->QueryInterface( riid, ppv );
+ }
+ else
+ return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
+}
+
+
+//--------------------------------------------------------------------------------
+// DecideBufferSize
+//
+// Determine allocator properties for our output pin.
+// This has to be present to override the PURE virtual class base function
+
+HRESULT CFilterOutputPin::DecideBufferSize( IMemAllocator* pAllocator,
+ ALLOCATOR_PROPERTIES* pProp )
+{
+ HRESULT hr = S_OK;
+
+ // Get properties from the input pin, if possible
+ if (m_pFilter->m_pinInput.IsConnected())
+ {
+ IMemAllocator* pAlloc = NULL;
+ if (SUCCEEDED( m_pFilter->m_pinInput.GetAllocator( &pAlloc ) ))
+ {
+ pAlloc->GetProperties( pProp );
+ pAlloc->Release();
+ }
+
+ // Ask for a larger buffer size if necessary
+ if (1 == m_pFilter->m_wfxIn.nChannels && 2 == m_pFilter->m_wfxOut.nChannels)
+ pProp->cbBuffer *= 2;
+ }
+
+ // Set the allocator's properties
+ ALLOCATOR_PROPERTIES propActual;
+ hr = pAllocator->SetProperties( pProp, &propActual );
+ if (SUCCEEDED( hr ))
+ *pProp = propActual;
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------
+// EnumMediaTypes
+
+STDMETHODIMP CFilterOutputPin::EnumMediaTypes( IEnumMediaTypes** ppEnum )
+{
+ CAutoLock autoLock(m_pLock);
+ ASSERT( ppEnum );
+
+ // Make sure that we are connected
+ if (!m_pFilter->m_pinInput.IsConnected())
+ return VFW_E_NOT_CONNECTED;
+
+ // We will simply return the enumerator of our input pin's peer
+ return m_pFilter->m_pinInput.m_Connected->EnumMediaTypes(ppEnum);
+}
+
+
+//--------------------------------------------------------------------------------
+// CheckMediaType
+
+HRESULT CFilterOutputPin::CheckMediaType( const CMediaType* pmt )
+{
+ CAutoLock autoLock(m_pLock);
+
+ // If we are already inside checkmedia type for this pin, return NOERROR
+ // It is possble to hookup two of these filters and some other filter
+ // like the video effects sample to get into this situation. If we
+ // do not detect this, we will loop till we blow the stack
+
+ if (m_bInsideCheckMediaType)
+ return NOERROR;
+
+ m_bInsideCheckMediaType = TRUE;
+
+ HRESULT hr = NOERROR;
+
+ // See if the wave format is supported
+ hr = m_pFilter->CheckMediaType( PINDIR_OUTPUT, pmt );
+ if (S_OK != hr)
+ {
+ m_bInsideCheckMediaType = FALSE;
+ return hr;
+ }
+
+ // The input needs to have been connected first
+ if (!m_pFilter->m_pinInput.IsConnected())
+ {
+ m_bInsideCheckMediaType = FALSE;
+ return VFW_E_NOT_CONNECTED;
+ }
+
+ // Make sure we can transform from one type to the other
+ const CMediaType& mtIn = m_pFilter->m_pinInput.CurrentMediaType();
+ hr = m_pFilter->CheckTransform( &mtIn, pmt );
+ if (FAILED( hr ))
+ {
+ m_bInsideCheckMediaType = FALSE;
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
+
+ m_bInsideCheckMediaType = FALSE;
+ return NOERROR;
+}
+
+
+//--------------------------------------------------------------------------------
+// GetMediaType - get the media type supported by this pin
+
+HRESULT CFilterOutputPin::GetMediaType( int iPosition, CMediaType* pmt )
+{
+ // We don't have any media types if our input is not connected
+ if (m_pFilter->m_pinInput.IsConnected())
+ {
+ return m_pFilter->GetMediaType( iPosition, pmt );
+ }
+ else
+ {
+ return VFW_S_NO_MORE_ITEMS;
+ }
+}
+
+
+//--------------------------------------------------------------------------------
+// SetMediaType
+
+HRESULT CFilterOutputPin::SetMediaType( const CMediaType* pmt )
+{
+ CAutoLock autoLock(m_pLock);
+
+ // Make sure that we have an input connected
+ if (!m_pFilter->m_pinInput.IsConnected())
+ return VFW_E_NOT_CONNECTED;
+
+ // Make sure that the base class likes it
+ HRESULT hr = CBaseOutputPin::SetMediaType( pmt );
+ if (FAILED( hr ))
+ return hr;
+
+ // Make sure the plug-in likes it
+ return m_pFilter->SetMediaType( PINDIR_OUTPUT, pmt );
+}
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/Filter.h b/Src/Plugins/DSP/dsp_sps/dxi/Filter.h
new file mode 100644
index 00000000..a101742b
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/Filter.h
@@ -0,0 +1,176 @@
+#ifndef _FILTER_H_
+#define _FILTER_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "DXi.h"
+#include "AudioPlugIn.h"
+
+class CFilter;
+class CFilterOutputPin;
+class CFilterInputPin;
+
+//--------------------------------------------------------------------------------
+
+class CFilterInputPin : public CBaseInputPin
+{
+ friend class CFilter;
+ friend class CFilterOutputPin;
+
+public:
+ // Ctor
+ CFilterInputPin( TCHAR* pObjDesc, CFilter* pFilter, HRESULT* phr, LPCWSTR pPinName );
+
+ // Check that we can support this output type
+ HRESULT CheckMediaType( const CMediaType* pmtIn );
+
+ // Set the connection media type
+ HRESULT SetMediaType( const CMediaType* pmt );
+
+ // Negotiate possible reconnection if types don't match
+ HRESULT CompleteConnect( IPin* pRecievePin );
+
+ // What is our media type?
+ CMediaType& CurrentMediaType() { return m_mt; };
+
+ // Pass through calls downstream
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+ STDMETHODIMP NewSegment( REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate );
+
+ // Handles the next block of data from the stream
+ STDMETHODIMP Receive( IMediaSample *pms );
+
+// Implementation
+private:
+ CFilter* m_pFilter; // the filter which owns us
+ BOOL m_bInsideCheckMediaType; // re-entrancy control
+};
+
+//--------------------------------------------------------------------------------
+
+class CFilterOutputPin : public CBaseOutputPin
+{
+ friend class CFilter;
+ friend class CFilterInputPin;
+
+public:
+
+ // Ctors
+ CFilterOutputPin( TCHAR* pObjDesc, CFilter* pFilter, HRESULT* phr, LPCWSTR pPinName );
+ virtual ~CFilterOutputPin();
+
+ DECLARE_IUNKNOWN;
+
+ // Override to expose IMediaPosition
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
+
+ // Override to enumerate media types
+ STDMETHODIMP EnumMediaTypes( IEnumMediaTypes** ppEnum );
+
+ // Check that we can support an output type
+ HRESULT CheckMediaType( const CMediaType* pmt );
+ HRESULT SetMediaType( const CMediaType* pmt );
+ HRESULT GetMediaType( int iPosition, CMediaType* pmt );
+
+ // What is our media type?
+ CMediaType& CurrentMediaType() { return m_mt; };
+
+ // Negotiation to use our input pins allocator
+ HRESULT DecideBufferSize( IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProp );
+
+ // Get the unique identifier for this output pin
+ DWORD GetId() const { return m_id; }
+
+// Implementation
+private:
+ CFilter* m_pFilter; // the filter which owns us
+ BOOL m_bInsideCheckMediaType; // re-entrancy control
+ DWORD m_id; // unique identifier
+ IUnknown* m_pPosition;
+
+ static DWORD m_idNext;
+};
+
+//--------------------------------------------------------------------------------
+
+class CFilter :
+ public CAudioPlugIn,
+
+ public CBaseFilter,
+ public ISpecifyPropertyPages,
+ public IDispatch,
+ public CPersistStream
+{
+ friend class CFilterInputPin;
+ friend class CFilterOutputPin;
+
+public:
+
+ // Ctors
+ CFilter( TCHAR *pName, LPUNKNOWN pUnk, HRESULT* phr );
+ ~CFilter();
+
+ // Function needed for the class factory
+ static CUnknown * WINAPI CreateInstance( LPUNKNOWN pUnk, HRESULT* phr );
+
+ DECLARE_IUNKNOWN;
+
+ STDMETHODIMP NonDelegatingQueryInterface( REFIID riid, void** ppv );
+
+ LPAMOVIESETUP_FILTER GetSetupData();
+
+ // CBaseFilter pure virtual overrides
+ CBasePin* GetPin( int n );
+ int GetPinCount();
+
+ // Overrides to deal with not having input connections
+ STDMETHODIMP Run( REFERENCE_TIME tStart );
+ STDMETHODIMP Pause();
+ STDMETHODIMP Stop();
+
+ // Helpers for media type checking
+ HRESULT CheckMediaType( PIN_DIRECTION direction, const CMediaType* pmt );
+ HRESULT CheckTransform( const CMediaType* pmtIn, const CMediaType* pmtOut );
+ HRESULT GetMediaType( int iPosition, CMediaType* pmt );
+ HRESULT SetMediaType( PIN_DIRECTION direction, const CMediaType* pmt );
+
+ // ISpecifyPropertyPages
+ STDMETHODIMP GetPages( CAUUID* pPages );
+
+ // CPersistStream
+ STDMETHODIMP GetClassID(CLSID* pClsid);
+ int SizeMax();
+ HRESULT WriteToStream(IStream* pStream);
+ HRESULT ReadFromStream(IStream* pStream);
+
+ // IDispatch
+ STDMETHODIMP GetTypeInfoCount( UINT* );
+ STDMETHODIMP GetTypeInfo( UINT, LCID, ITypeInfo** );
+ STDMETHODIMP GetIDsOfNames( REFIID, OLECHAR**, UINT, LCID, DISPID* );
+ STDMETHODIMP Invoke( DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT* );
+
+// Implementation
+private:
+
+ HRESULT getOutputBuffer( CFilterOutputPin* pPin,
+ AudioBuffer* pbufOut,
+ REFERENCE_TIME* prtStart,
+ BOOL bSyncPoint, BOOL bDiscontuity, BOOL bPreroll );
+ HRESULT deliverOutputBuffer( CFilterOutputPin* pPin,
+ AudioBuffer* abufOut,
+ HRESULT hrProcess, BOOL bCleanup );
+
+ HRESULT audioPortsChangeBegin( int nNewPinCount );
+ HRESULT audioPortsChangeEnd( int nNewPinCount );
+
+ CFilterInputPin m_pinInput;
+ CFilterOutputPin m_pinOutput;
+ IMemAllocator* m_pAllocator;
+ LONGLONG m_llSamplePosition;
+};
+
+#endif // _FILTER_H_
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.cpp b/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.cpp
new file mode 100644
index 00000000..43fc4743
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.cpp
@@ -0,0 +1,465 @@
+// MediaParams.cpp: implementation of the CMediaParams class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "AudioPlugIn.h"
+#include "MediaParams.h"
+#include "ParamEnvelope.h"
+
+#include "CakeMedParam_i.c"
+
+#define DEFINE_PARAM_INFO
+#include "Parameters.h"
+
+//////////////////////////////////////////////////////////////////////
+// Ctors
+
+CMediaParams::CMediaParams( IUnknown* pUnkOuter ) : m_pUnkOuter(pUnkOuter)
+{
+ m_pCallback = NULL;
+ m_cRef = 0;
+ m_aEnv = NULL;
+ m_dDecimationInterval = 20.0 / 1000.0; // 20 msec
+ m_lFs = 44100;
+}
+
+CMediaParams::~CMediaParams()
+{
+ ASSERT( 0 == m_cRef );
+ if (m_pCallback)
+ m_pCallback->Release();
+ m_pCallback = NULL;
+ m_pUnkOuter = NULL;
+
+ delete [] m_aEnv;
+ m_aEnv = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Factory-style construction
+
+HRESULT CMediaParams::Create( CMediaParams** ppObj, IUnknown* pUnkOuter )
+{
+ if (NULL == ppObj)
+ return E_POINTER;
+ if (NULL == pUnkOuter)
+ return E_POINTER;
+
+ // Construct the CMediaParams object
+ CMediaParams* pNew = new CMediaParams( pUnkOuter );
+ if (NULL == pNew)
+ return E_OUTOFMEMORY;
+
+ // Construct and initialize its parameters
+ pNew->m_aEnv = new CParamEnvelope [ NUM_PARAMS ];
+ if (NULL == pNew->m_aEnv)
+ return E_OUTOFMEMORY;
+ for (ULONG ix = 0; ix < NUM_PARAMS; ++ix)
+ pNew->m_aEnv[ ix ].SetParamInfo( m_aParamInfo[ ix ] );
+
+ pNew->AddRef();
+ *ppObj = pNew;
+ return S_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Given a sample range, fills pTimes with sample positions where we need
+// to recompute one or more automated parameter values. Positions are always
+// added periodically at the decimation interval; positions are also added
+// for every segment boundary among all of the parameters.
+
+HRESULT CMediaParams::GetDecimationTimes( LONGLONG llSampStart,
+ LONGLONG llSampEnd,
+ std::vector<LONGLONG>* pTimes )
+{
+ LONGLONG const llInterval = static_cast<LONGLONG>( GetDecimationInterval() * GetSampleRate() );
+ double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
+ REFERENCE_TIME const rtStart = REFERENCE_TIME( llSampStart / dSamplesPerRefTime + 0.5 );
+
+ // Make an worst-case guess at how many decimation points we'll need
+ ULONG uPoints = 0;
+ for (DWORD dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
+ {
+ const CParamEnvelope& env = m_aEnv[ dwParam ];
+ uPoints += env.GetCount() * 2;
+ }
+
+ // If there is no automation, then there is no need to decimate
+ if (0 == uPoints)
+ return S_OK;
+
+ // Account for points that are added due to periodic decimation
+ uPoints += ULONG( ((llSampEnd - llSampStart) / llInterval) + 1 );
+
+ // Reserve some memory for landmark points
+ pTimes->reserve( uPoints );
+
+ // Add periodic landmarks at the decimation interval
+ LONGLONG llSamp = (llSampStart / llInterval) * llInterval;
+ if (llSamp < llSampStart)
+ llSamp += llInterval;
+ while (llSamp < llSampEnd)
+ {
+ pTimes->push_back( llSamp );
+ llSamp += llInterval;
+ }
+
+ // Add landmarks for each shape boundary
+ for (dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
+ {
+ const CParamEnvelope& env = m_aEnv[ dwParam ];
+ unsigned const nCount = env.GetCount();
+
+ // Add each shape endpoint that falls in our time range
+ for (unsigned ix = 0; ix < nCount; ix++)
+ {
+ const MP_ENVELOPE_SEGMENT& seg = env.GetAt( ix );
+ LONGLONG const llEnvStart = static_cast<LONGLONG>( seg.rtStart * dSamplesPerRefTime + 0.5 );
+ LONGLONG const llEnvEnd = static_cast<LONGLONG>( seg.rtEnd * dSamplesPerRefTime + 0.5 );
+ if (llSampStart <= llEnvStart && llEnvStart < llSampEnd)
+ pTimes->push_back( llEnvStart );
+ if (llSampStart <= llEnvEnd && llEnvEnd < llSampEnd)
+ pTimes->push_back( llEnvEnd );
+ }
+ }
+
+ // Sort result
+ std::sort( pTimes->begin(), pTimes->end() );
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Set the current position among all parameters, updating current envelope
+// value and deltas. This method is called repeatedly by the streaming code,
+// to update parameter values as they evolve along the duration of the envelope.
+
+HRESULT CMediaParams::UpdateValuesForSample( LONGLONG llSamp )
+{
+ double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
+ REFERENCE_TIME const rt = REFERENCE_TIME( llSamp / dSamplesPerRefTime + 0.5 );
+
+ HRESULT hr = S_OK;
+ for (DWORD dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
+ {
+ hr = m_aEnv[ dwParam ].UpdateValuesForRefTime( rt, GetSampleRate() );
+ if (FAILED( hr ))
+ break;
+ }
+
+ return hr;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IUnknown
+
+HRESULT CMediaParams::QueryInterface( REFIID riid, void** ppv )
+{
+ if (NULL == ppv)
+ return E_POINTER;
+
+ if (riid == IID_IUnknown)
+ {
+ *ppv = static_cast<IUnknown*>( static_cast<IMediaParams*>( this ) );
+ m_pUnkOuter->AddRef();
+ return S_OK;
+ }
+ else
+ {
+ return m_pUnkOuter->QueryInterface( riid, ppv );
+ }
+}
+
+ULONG CMediaParams::AddRef()
+{
+ return InterlockedIncrement( &m_cRef );
+}
+
+ULONG CMediaParams::Release()
+{
+ ASSERT( m_cRef > 0 );
+ ULONG ul = InterlockedDecrement( &m_cRef );
+ if (0 == ul)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return ul;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IMediaParams
+
+HRESULT CMediaParams::GetParam(ULONG dwParamIndex, FLOAT* pValue)
+{
+ if (dwParamIndex >= NUM_PARAMS)
+ return E_INVALIDARG;
+ if (NULL == pValue)
+ return E_POINTER;
+
+ return m_aEnv[ dwParamIndex ].GetParam( pValue );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::SetParam(ULONG dwParamIndex, FLOAT value)
+{
+ if (dwParamIndex >= NUM_PARAMS)
+ return E_INVALIDARG;
+
+ return m_aEnv[ dwParamIndex ].SetParam( value );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::AddEnvelope(ULONG dwParamIndex, ULONG cSegments, MP_ENVELOPE_SEGMENT* pmpes)
+{
+ if (dwParamIndex >= NUM_AUTOMATED_PARAMS && dwParamIndex != DWORD_ALLPARAMS)
+ return E_INVALIDARG;
+ if (0 == cSegments)
+ return S_OK;
+ if (IsBadReadPtr( pmpes, cSegments * sizeof(MP_ENVELOPE_SEGMENT) ))
+ return E_POINTER;
+
+ double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
+
+ if (dwParamIndex == DWORD_ALLPARAMS)
+ {
+ for (ULONG ix = 0; ix < NUM_AUTOMATED_PARAMS; ix++)
+ {
+ HRESULT hr = m_aEnv[ ix ].AddEnvelope( cSegments, pmpes, dSamplesPerRefTime );
+ if (FAILED( hr ))
+ return hr;
+ }
+ return S_OK;
+ }
+ else
+ {
+ return m_aEnv[ dwParamIndex ].AddEnvelope( cSegments, pmpes, dSamplesPerRefTime );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::FlushEnvelope(ULONG dwParamIndex, REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd)
+{
+ if (dwParamIndex >= NUM_AUTOMATED_PARAMS && dwParamIndex != DWORD_ALLPARAMS)
+ return E_INVALIDARG;
+ if (rtStart > rtEnd)
+ return E_INVALIDARG;
+
+ double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
+
+ if (dwParamIndex == DWORD_ALLPARAMS)
+ {
+ for (ULONG ix = 0; ix < NUM_AUTOMATED_PARAMS; ix++)
+ {
+ HRESULT hr = m_aEnv[ ix ].FlushEnvelope( rtStart, rtEnd, dSamplesPerRefTime );
+ if (FAILED( hr ))
+ return hr;
+ }
+ return S_OK;
+ }
+ else
+ {
+ HRESULT hr = m_aEnv[ dwParamIndex ].FlushEnvelope( rtStart, rtEnd, dSamplesPerRefTime );
+ if (FAILED( hr ))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::SetTimeFormat(GUID guidTimeFormat, ULONG mpTimeData)
+{
+ if (guidTimeFormat != GUID_TIME_REFERENCE)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IMediaParamInfo
+
+HRESULT CMediaParams::GetParamCount(ULONG* pdwParams)
+{
+ if (NULL == pdwParams)
+ return E_POINTER;
+
+ *pdwParams = NUM_AUTOMATED_PARAMS;
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::GetParamInfo(ULONG dwParamIndex, MP_PARAMINFO* pInfo)
+{
+ if (dwParamIndex >= NUM_AUTOMATED_PARAMS)
+ return E_INVALIDARG;
+ if (IsBadWritePtr( pInfo, sizeof(MP_PARAMINFO) ))
+ return E_POINTER;
+
+ *pInfo = m_aParamInfo[ dwParamIndex ].mppi;
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::GetParamText(ULONG dwParamIndex, WCHAR** ppwchText)
+{
+ if (dwParamIndex >= NUM_AUTOMATED_PARAMS)
+ return E_INVALIDARG;
+ if (NULL == ppwchText)
+ return E_POINTER;
+
+ const ParamInfo& info = m_aParamInfo[ dwParamIndex ];
+ const MP_PARAMINFO& mppi = info.mppi;
+
+ // Count up lengths of label and unit strings, plus null terminators
+ int cch = wcslen(mppi.szLabel) + wcslen(mppi.szUnitText) + 3;
+
+ // Add in length of the enum. text if any was supplied
+ if (NULL != info.pwszEnumText)
+ cch += wcslen(info.pwszEnumText) + 1;
+
+ // Allocate memory for the returned string
+ *ppwchText = (WCHAR*)CoTaskMemAlloc( sizeof(WCHAR) * cch );
+ if (NULL == *ppwchText)
+ return E_OUTOFMEMORY;
+
+ // Text format is "Name\0Units\0Enum1\0Enum2\0...EnumN\0\0"
+ WCHAR* pwsz = *ppwchText;
+
+ // [1] Copy in the name
+ wcscpy( pwsz, mppi.szLabel );
+ pwsz += wcslen(mppi.szLabel) + 1;
+
+ // [2] Copy in the units
+ wcscpy( pwsz, mppi.szUnitText );
+ pwsz += wcslen(mppi.szUnitText) + 1;
+
+ // [3] Copy in the enum. text, if any was supplied
+ if (NULL != info.pwszEnumText)
+ {
+ wcscpy( pwsz, info.pwszEnumText );
+
+ // Replace commas with nulls, to conform to DX8 string format spec
+ while (*pwsz)
+ {
+ if (*pwsz == L',')
+ *pwsz = 0;
+ pwsz++;
+ }
+ }
+
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::GetNumTimeFormats(ULONG* pdwNumTimeFormats)
+{
+ if (NULL == pdwNumTimeFormats)
+ return E_POINTER;
+ *pdwNumTimeFormats = 1;
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::GetSupportedTimeFormat(ULONG dwFormatIndex, GUID* pguidTimeFormat)
+{
+ if (NULL == pguidTimeFormat)
+ return E_POINTER;
+ if (0 != dwFormatIndex)
+ return E_INVALIDARG;
+ *pguidTimeFormat = GUID_TIME_REFERENCE;
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+HRESULT CMediaParams::GetCurrentTimeFormat(GUID* pguidTimeFormat, ULONG*)
+{
+ if (NULL == pguidTimeFormat)
+ return E_POINTER;
+ *pguidTimeFormat = GUID_TIME_REFERENCE;
+ return S_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IMediaParamsSetUICallback
+
+HRESULT CMediaParams::SetUICallback(IMediaParamsUICallback* pICallback)
+{
+ if (pICallback)
+ pICallback->AddRef();
+ if (m_pCallback)
+ m_pCallback->Release();
+ m_pCallback = pICallback;
+ return S_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// IMediaParamsUICallback
+
+HRESULT CMediaParams::ParamsBeginCapture(DWORD *aIndex, DWORD cPoints)
+{
+ HRESULT hr = S_OK;
+
+ // Inform each parameter that capture has begun
+ for (DWORD ix = 0; ix < cPoints; ix++)
+ m_aEnv[ aIndex[ ix ] ].BeginCapture();
+
+ if (m_pCallback)
+ hr = m_pCallback->ParamsBeginCapture( aIndex, cPoints );
+
+ return hr;
+}
+
+HRESULT CMediaParams::ParamsChanged(DWORD *aIndex, DWORD cPoints, MP_DATA *paData)
+{
+ HRESULT hr = S_OK;
+
+ // Send the parameter change to each parameter
+ for (DWORD ix = 0; ix < cPoints; ix++)
+ {
+ hr = SetParam( aIndex[ ix ], paData[ ix ] );
+ if (FAILED( hr ))
+ return hr;
+ }
+
+ // Send the parameter change to our callback
+ if (m_pCallback)
+ hr = m_pCallback->ParamsChanged( aIndex, cPoints, paData );
+
+ return hr;
+}
+
+HRESULT CMediaParams::ParamsEndCapture(DWORD *aIndex, DWORD cPoints)
+{
+ HRESULT hr = S_OK;
+
+ // Inform each parameter that capture has ended
+ for (DWORD ix = 0; ix < cPoints; ix++)
+ m_aEnv[ aIndex[ ix ] ].EndCapture();
+
+ if (m_pCallback)
+ hr = m_pCallback->ParamsEndCapture( aIndex, cPoints );
+
+ return hr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.h b/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.h
new file mode 100644
index 00000000..947399f6
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/MediaParams.h
@@ -0,0 +1,99 @@
+// MediaParams.h: interface for the CMediaParams class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MEDIAPARAMS_H__3DB99F00_3887_4C35_BBA8_C47835777A69__INCLUDED_)
+#define AFX_MEDIAPARAMS_H__3DB99F00_3887_4C35_BBA8_C47835777A69__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <MedParam.h> // DX8 automation
+#include "CakeMedParam.h" // DX8 automation
+
+#include "ParamEnvelope.h"
+#include "Parameters.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CMediaParams :
+ public IMediaParams,
+ public IMediaParamInfo,
+ public IMediaParamsSetUICallback,
+ public IMediaParamsUICallback
+{
+public:
+
+ static HRESULT Create( CMediaParams** ppObj, IUnknown* pUnkOuter );
+
+public:
+
+ // IUnknown
+ STDMETHOD(QueryInterface)( REFIID riid, void** ppv );
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IMediaParams
+ STDMETHOD(GetParam)(ULONG dwParamIndex, FLOAT* pValue);
+ STDMETHOD(SetParam)(ULONG dwParamIndex, FLOAT value);
+ STDMETHOD(AddEnvelope)(ULONG dwParamIndex, ULONG cSegments, MP_ENVELOPE_SEGMENT* pEnvelopeSegments);
+ STDMETHOD(FlushEnvelope)(ULONG dwParamIndex, REFERENCE_TIME refTimeStart, REFERENCE_TIME refTimeEnd);
+ STDMETHOD(SetTimeFormat)(GUID guidTimeFormat, ULONG mpTimeData);
+
+ // IMediaParamInfo
+ STDMETHOD(GetParamCount)(ULONG* pdwParams);
+ STDMETHOD(GetParamInfo)(ULONG dwParamIndex, MP_PARAMINFO* pInfo);
+ STDMETHOD(GetParamText)(ULONG dwParamIndex, WCHAR** ppwchText);
+ STDMETHOD(GetNumTimeFormats)(ULONG* pdwNumTimeFormats);
+ STDMETHOD(GetSupportedTimeFormat)(ULONG dwFormatIndex, GUID* pguidTimeFormat);
+ STDMETHOD(GetCurrentTimeFormat)(GUID* pguidTimeFormat, ULONG* pTimeData);
+
+ // IMediaParamsSetUICallback
+ STDMETHOD(SetUICallback)(IMediaParamsUICallback* pICallback);
+
+ // IMediaParamsUICallback
+ STDMETHOD(ParamsBeginCapture)(DWORD *aIndex, DWORD cPoints);
+ STDMETHOD(ParamsChanged)(DWORD *aIndex, DWORD cPoints, MP_DATA *paData);
+ STDMETHOD(ParamsEndCapture)(DWORD *aIndex, DWORD cPoints);
+
+ // Helpers for setting the current sample rate
+ void SetSampleRate( long lFs ) { m_lFs = lFs; }
+ long GetSampleRate() const { return m_lFs; }
+
+ // Helpers to decimate shapes into smaller chunks
+ HRESULT GetDecimationTimes( LONGLONG llSampStart, LONGLONG llSampEnd, std::vector<LONGLONG>* pTimes );
+ void SetDecimationInterval( double d ) { m_dDecimationInterval = d; }
+ double GetDecimationInterval() const { return m_dDecimationInterval; }
+
+ // Set our position among all parameter segments, updating current values, and
+ // flushing any out-of-date segments.
+ HRESULT UpdateValuesForSample( LONGLONG llSamp );
+
+ // Get the envelope for a given parameter
+ const CParamEnvelope& GetParamEnvelope( DWORD ix )
+ {
+ ASSERT( ix >= 0 && ix < NUM_PARAMS );
+ return m_aEnv[ ix ];
+ }
+
+private:
+
+ IUnknown* m_pUnkOuter;
+ IMediaParamsUICallback* m_pCallback;
+ LONG m_cRef;
+ CParamEnvelope* m_aEnv;
+ double m_dDecimationInterval;
+ long m_lFs;
+
+private:
+
+ static const ParamInfo m_aParamInfo[ NUM_PARAMS ];
+
+private:
+
+ CMediaParams( IUnknown* pUnkOuter );
+ virtual ~CMediaParams();
+};
+
+#endif // !defined(AFX_MEDIAPARAMS_H__3DB99F00_3887_4C35_BBA8_C47835777A69__INCLUDED_)
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.cpp b/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.cpp
new file mode 100644
index 00000000..923496bb
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.cpp
@@ -0,0 +1,403 @@
+// ParamEnvelope.cpp: implementation of the CParamEnvelope class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "AudioPlugIn.h"
+#include "ParamEnvelope.h"
+
+#include <math.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// ParamInfo
+////////////////////////////////////////////////////////////////////////////////
+
+float ParamInfo::MapToInternal( float fValue ) const
+{
+ // Convert a user-supplied parameter value to one that is for internal
+ // use by the plug-in's processing code.
+
+ if (MPT_FLOAT == mppi.mpType)
+ {
+ // Map floats to the internal range, using a linear mapping
+ double dDelta = (fValue - mppi.mpdMinValue) / (mppi.mpdMaxValue - mppi.mpdMinValue);
+ return float( fInternalMin + dDelta * (fInternalMax - fInternalMin) );
+ }
+ else if (MPT_BOOL == mppi.mpType)
+ {
+ // Map booleans to 0.0 or 1.0
+ return float( (fValue < 0.5) ? MPBOOL_FALSE : MPBOOL_TRUE );
+ }
+ else // (MPT_ENUM == mppi.mpType || MPT_INT == mppi.mpType)
+ {
+ // Map integers to the internal range, using a linear mapping, and then
+ // round to the nearest value.
+ double dDelta = (fValue - mppi.mpdMinValue) / (mppi.mpdMaxValue - mppi.mpdMinValue);
+ double dMapped = fInternalMin + dDelta * (fInternalMax - fInternalMin);
+ return static_cast<float>( floor( dMapped + 0.5 ) );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+float ParamInfo::MapToExternal( float fValue ) const
+{
+ // Convert an internal processing value to value in the user's input range
+
+ if (MPT_FLOAT == mppi.mpType)
+ {
+ // Map floats to the external range, using a linear mapping
+ double dDelta = (fValue - fInternalMin) / (fInternalMax - fInternalMin);
+ return float( mppi.mpdMinValue + dDelta * (mppi.mpdMaxValue - mppi.mpdMinValue) );
+ }
+ else if (MPT_BOOL == mppi.mpType)
+ {
+ // Booleans are already in a suitable range; no mapping required.
+ return fValue;
+ }
+ else // (MPT_ENUM == mppi.mpType || MPT_INT == mppi.mpType)
+ {
+ // Map integers to the external range, using a linear mapping
+ double dDelta = (fValue - fInternalMin) / (fInternalMax - fInternalMin);
+ return float( mppi.mpdMinValue + dDelta * (mppi.mpdMaxValue - mppi.mpdMinValue) );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CParamEnvelope
+////////////////////////////////////////////////////////////////////////////////
+
+//------------------------------------------------------------------------------
+// Ctors
+
+CParamEnvelope::CParamEnvelope() :
+ m_bOverride( FALSE ),
+ m_bCaptured( FALSE ),
+ m_fOverrideValue( 0 ),
+ m_fEnvelopeValue( 0 ),
+ m_dEnvelopeDelta1( 0 ),
+ m_dEnvelopeDelta2( 0 ),
+ m_bValidDeltas( TRUE ),
+ m_rtRendered( 0 )
+{
+}
+
+CParamEnvelope::~CParamEnvelope()
+{
+}
+
+
+//----------------------------------------------------------------------------
+// Phase 2 of construction
+
+void CParamEnvelope::SetParamInfo( const ParamInfo& info )
+{
+ m_info = info;
+ m_fEnvelopeValue = m_info.MapToInternal( m_info.mppi.mpdNeutralValue );
+ cleanup();
+}
+
+
+//----------------------------------------------------------------------------
+// Find the index for data on or after rt
+
+int CParamEnvelope::IndexForRefTime( REFERENCE_TIME rt ) const
+{
+ CAutoLock lock( const_cast<CParamEnvelope*>( this ) );
+
+ int const nLength = GetCount();
+
+ // Fail gracefully if the list is empty
+ if (0 == nLength)
+ return -1;
+
+ // Special case for position after the last segment
+ if (rt >= m_envSegs[ nLength - 1 ].rtEnd)
+ return nLength - 1;
+
+ int ixMin = 0;
+ int ixMax = nLength;
+ int ix = ( ixMin + ixMax ) / 2;
+
+ // Binary search for the shape which starts on or before the given time
+ do
+ {
+ REFERENCE_TIME rtShape = m_envSegs[ ix ].rtStart;
+
+ // We've made an exact match
+ if (rtShape == rt)
+ return ix;
+
+ // No match was found, so update search indices
+ else if (rt < rtShape)
+ ixMax = ix;
+ else if (rt > rtShape)
+ ixMin = ix;
+ ix = (ixMin + ixMax) / 2;
+ }
+ while (ix != ixMin);
+
+ // The search may have left us at a shape after the desired time, so
+ // scan back if necessary
+ while (ix >= 0 && m_envSegs[ ix ].rtStart > rt)
+ --ix;
+
+ return ix;
+}
+
+
+//------------------------------------------------------------------------------
+// Set the current position, updating current envelope value and deltas. This
+// method is called repeatedly by the streaming code, to update parameter values
+// as they evolve along the duration of the envelope.
+
+HRESULT CParamEnvelope::UpdateValuesForRefTime( REFERENCE_TIME rt, long lSampleRate )
+{
+ CAutoLock lock( this );
+
+ int const nLength = GetCount();
+ if (0 == nLength)
+ return S_OK; // nothing to do
+
+ int const ix = IndexForRefTime( rt );
+ const MP_ENVELOPE_SEGMENT* pmpseg = (ix < 0 || ix >= nLength) ? NULL : &m_envSegs[ ix ];
+
+ // Assume deltas are valid. We'll make them invalid if we encounter a SIN curve.
+ m_bValidDeltas = TRUE;
+
+ if (NULL == pmpseg || rt < pmpseg->rtStart || rt > pmpseg->rtEnd)
+ {
+ // The seek position is between 2 segments, so do not modify the current envelope
+ // value. The envelope will either latch the previous value, or continue to obey
+ // any intervening override value, until we hit the next segment boundary.
+ if (NULL != pmpseg)
+ m_fEnvelopeValue = m_info.MapToInternal( pmpseg->valEnd );
+ m_dEnvelopeDelta1 = m_dEnvelopeDelta2 = 0;
+ }
+ else
+ {
+ // We're dealing with point directly over a shape. Stop any override value.
+ stopOverride();
+
+ // Compute the time delta between this vector and the next, as value
+ // between 0..1. We use to interpolate between points.
+ double dx = double(pmpseg->rtEnd - pmpseg->rtStart) / UNITS;
+ double y0 = m_info.MapToInternal( pmpseg->valStart );
+ double y1 = m_info.MapToInternal( pmpseg->valEnd );
+ double dy = y1 - y0;
+ double x = (double(rt - pmpseg->rtStart) / UNITS) / dx;
+
+ // Convert dx to units per sample, before computing deltas
+ dx = dx * lSampleRate;
+
+ // Interpolate between times
+ if (MP_CURVE_JUMP == pmpseg->iCurve)
+ {
+ m_dEnvelopeDelta2 = 0;
+ m_dEnvelopeDelta1 = 0;
+ m_fEnvelopeValue = static_cast<float>( y0 );
+ }
+ else if (MP_CURVE_LINEAR == pmpseg->iCurve)
+ {
+ m_dEnvelopeDelta2 = 0;
+ m_dEnvelopeDelta1 = dy / dx;
+ m_fEnvelopeValue = static_cast<float>( y0 + dy * x );
+ }
+ else if (MP_CURVE_SQUARE == pmpseg->iCurve || MP_CURVE_INVSQUARE == pmpseg->iCurve)
+ {
+ double A;
+ double B;
+ if (MP_CURVE_SQUARE == pmpseg->iCurve)
+ {
+ A = y0;
+ B = dy;
+ }
+ else
+ {
+ x = x - 1;
+ A = y1;
+ B = -dy;
+ }
+
+ m_dEnvelopeDelta2 = 2.0 * B / (dx * dx);
+ m_dEnvelopeDelta1 = (B / dx) * (2.0 * x + (1.0 / dx));
+ m_fEnvelopeValue = static_cast<float>( A + B * x * x );
+ }
+ else if (MP_CURVE_SINE)
+ {
+ static const double dPI = 3.14159265358979323846264338327950288419716939937510;
+ double dTheta = dPI * (x - 0.5);
+ m_bValidDeltas = FALSE;
+ m_fEnvelopeValue = float( dy * ( sin( dTheta ) + 0.5 ) );
+ }
+ }
+
+ // Keep track of the latest time rendered so far
+ m_rtRendered = max( m_rtRendered, rt );
+
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+// If the list is empty, make sure we get an override value.
+
+void CParamEnvelope::cleanup()
+{
+ if (0 == GetCount() && !IsOverrideActive())
+ {
+ m_fOverrideValue = m_fEnvelopeValue;
+ m_bOverride = TRUE;
+ }
+}
+
+
+//---------------------------------------------------------------------------
+// Set the value of our parameter, overriding any segment in effect.
+
+HRESULT CParamEnvelope::SetParam( float fValue )
+{
+ m_bOverride = TRUE;
+ m_fOverrideValue = m_info.MapToInternal( fValue );
+ m_fEnvelopeValue = m_fOverrideValue;
+ m_dEnvelopeDelta1 = m_dEnvelopeDelta2 = 0;
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+// Get the value of the parameter, either overriden on an a segment
+
+HRESULT CParamEnvelope::GetParam( float* pfValue )
+{
+ if (NULL == pfValue)
+ return E_POINTER;
+ *pfValue = m_info.MapToExternal( GetCurrentValue() );
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+// Add segments to this envelope
+
+static bool compareEnvSeg( const MP_ENVELOPE_SEGMENT& a, const MP_ENVELOPE_SEGMENT& b )
+{
+ return a.rtStart < b.rtStart;
+}
+
+static bool operator==( const MP_ENVELOPE_SEGMENT& a, const MP_ENVELOPE_SEGMENT& b )
+{
+ return 0 == memicmp( &a, &b, sizeof(MP_ENVELOPE_SEGMENT) );
+}
+
+HRESULT CParamEnvelope::AddEnvelope( DWORD cSegments, MP_ENVELOPE_SEGMENT* pmpes, double dSamplesPerRefTime )
+{
+ CAutoLock lock( this );
+
+ // Make room for what we are going to add
+ m_envSegs.reserve( m_envSegs.size() + cSegments );
+
+ // Add each segment, noting which one is earliest in time
+ REFERENCE_TIME rtMin = _I64_MAX;
+ for (int ix = 0; ix < cSegments; ix++)
+ {
+ // Round reference times to sample boundaries
+ MP_ENVELOPE_SEGMENT mpes = pmpes[ ix ];
+ mpes.rtStart = REFERENCE_TIME(mpes.rtStart * dSamplesPerRefTime) / dSamplesPerRefTime + 0.5;
+ mpes.rtEnd = REFERENCE_TIME(mpes.rtEnd * dSamplesPerRefTime) / dSamplesPerRefTime + 0.5;
+ m_envSegs.push_back( pmpes[ ix ] );
+ if (mpes.rtStart < rtMin)
+ rtMin = mpes.rtStart;
+ }
+
+ // Flush all segments prior to the first newly added one
+ ix = IndexForRefTime( rtMin );
+ if (ix > 0 && rtMin < m_rtRendered)
+ m_envSegs.erase( m_envSegs.begin(), m_envSegs.begin() + ix );
+
+ // Sort them
+ std::sort( m_envSegs.begin(), m_envSegs.end(), compareEnvSeg );
+
+ // Remove duplicates
+ EnvelopeSegs::iterator it = m_envSegs.begin();
+ while (it != m_envSegs.end())
+ {
+ EnvelopeSegs::iterator itBegin = it + 1;
+ EnvelopeSegs::iterator itEnd = itBegin;
+ while (itEnd != m_envSegs.end() && *itEnd == *it)
+ itEnd++;
+ if (itEnd != itBegin)
+ it = m_envSegs.erase( itBegin, itEnd );
+ else
+ it++;
+
+ }
+
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+// Flush segments within the specified time range. The rules for flushing are
+// described as follows in the documentation for IMediaParams:
+//
+// If the time span specified by refTimeStart and refTimeEnd overlaps an envelope
+// segment, the entire segment is flushed. On the other hand, if it falls on
+// the boundary of an envelope segment, the entire segment is retained. Thus:
+//
+// [] If the start time falls inside an envelope segment, the segment is flushed.
+// [] If the end time falls inside an envelope segment, the segment is flushed.
+// [] If the start time equals the end time of an envelope segment, the segment is retained.
+// [] If the end time equals the start time of an envelope segment, the segment is retained.
+
+HRESULT CParamEnvelope::FlushEnvelope( REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, double dSamplesPerRefTime )
+{
+ CAutoLock lock( this );
+
+ // Round reference times to sample boundaries
+ if (rtStart != _I64_MIN && rtStart != _I64_MAX)
+ rtStart = REFERENCE_TIME( REFERENCE_TIME(rtStart / dSamplesPerRefTime) * dSamplesPerRefTime + 0.5 );
+ if (rtEnd != _I64_MIN && rtEnd != _I64_MAX)
+ rtEnd = REFERENCE_TIME( REFERENCE_TIME(rtEnd / dSamplesPerRefTime) * dSamplesPerRefTime + 0.5 );
+
+ EnvelopeSegs::iterator it = m_envSegs.begin();
+ while (it != m_envSegs.end())
+ {
+ if (!(rtStart >= it->rtEnd || rtEnd <= it->rtStart))
+ it = m_envSegs.erase( it );
+ else
+ it++;
+ }
+
+ // Once envelopes get thrown away, we need to redetermine our max render time
+ m_rtRendered = 0;
+
+ cleanup();
+
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+// The parameter pcSegments passes values both ways. The caller needs to pass in the
+// size of the segment array. GetEnvelope() then uses pcSegments to return the number
+// of segments it has placed in the array.
+
+HRESULT CParamEnvelope::GetEnvelope( DWORD *pcSegments, MP_ENVELOPE_SEGMENT *pmpes )
+{
+ CAutoLock lock( this );
+
+ ASSERT( pcSegments );
+
+ DWORD ix = 0;
+ for (EnvelopeSegs::iterator it = m_envSegs.begin();
+ it != m_envSegs.end() && ix < *pcSegments;
+ it++, ix++)
+ {
+ pmpes[ ix ] = *it;
+ }
+
+ *pcSegments = ix;
+
+ return S_OK;
+}
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.h b/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.h
new file mode 100644
index 00000000..56bff5d5
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/ParamEnvelope.h
@@ -0,0 +1,124 @@
+// ParamEnvelope.h: interface for the CParamEnvelope class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PARAMENVELOPE_H__F04D0178_4674_45AF_9F7A_5C8206DE4CF6__INCLUDED_)
+#define AFX_PARAMENVELOPE_H__F04D0178_4674_45AF_9F7A_5C8206DE4CF6__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+////////////////////////////////////////////////////////////////////////////////
+
+typedef std::vector<MP_ENVELOPE_SEGMENT> EnvelopeSegs;
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ParamInfo
+{
+ MP_PARAMINFO mppi; // external parameter info, as presented to the user
+ float fInternalMin; // minimum value used by internal processing code
+ float fInternalMax; // maximum value used by internal processing code
+ const WCHAR* pwszEnumText; // text for enumerations
+
+ float MapToInternal( float fValue ) const;
+ float MapToExternal( float fValue ) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CParamEnvelope : public CCritSec
+{
+public:
+ CParamEnvelope();
+ virtual ~CParamEnvelope();
+
+// Attributes
+public:
+
+ unsigned GetCount() const
+ {
+ return m_envSegs.size();
+ }
+
+ const MP_ENVELOPE_SEGMENT& GetAt( unsigned ix ) const
+ {
+ return m_envSegs[ ix ];
+ }
+
+ // Tell the envelope about the parameter being controlled
+ void SetParamInfo( const ParamInfo& info );
+
+ // These methods are called by CMediaParams to manipulate segments in an envelope
+ HRESULT AddEnvelope( DWORD cSegments, MP_ENVELOPE_SEGMENT* pEnvelopeSegments, double dSamplesPerRefTime );
+ HRESULT FlushEnvelope( REFERENCE_TIME refTimeStart, REFERENCE_TIME refTimeEnd, double dSamplesPerRefTime );
+ HRESULT GetEnvelope( DWORD* cSegments, MP_ENVELOPE_SEGMENT* pEnvelopeSegments );
+ HRESULT SetParam( float fValue );
+ HRESULT GetParam( float* pfValue );
+
+ // Manage UI capture and release
+ void BeginCapture() { m_bCaptured = TRUE; }
+ void EndCapture() { m_bCaptured = FALSE; }
+
+ // Set the current position, updating current envelope value and deltas
+ HRESULT UpdateValuesForRefTime( REFERENCE_TIME rt, long lSampleRate );
+
+ // Check if automation envelopes have been overriden with a specific value
+ BOOL IsOverrideActive() const { return m_bOverride || m_bCaptured; }
+
+ // Get the current automation data point
+ float GetCurrentValue() const
+ {
+ if (IsOverrideActive())
+ return m_fOverrideValue;
+ else
+ return m_fEnvelopeValue;
+ }
+
+ // Get the current automation deltas (for per-sample rendering)
+ HRESULT GetCurrentDeltas( double* pdDelta1, double* pdDelta2 ) const
+ {
+ if (!m_bValidDeltas)
+ return E_FAIL;
+ *pdDelta1 = m_dEnvelopeDelta1;
+ *pdDelta2 = m_dEnvelopeDelta2;
+ return S_OK;
+ }
+
+ int IndexForRefTime( REFERENCE_TIME rt ) const;
+
+private:
+
+ // Stop overriding data
+ void stopOverride()
+ {
+ if (IsOverrideActive() && GetCount() > 0)
+ m_bOverride = FALSE;
+ }
+
+ // Make sure the automation track is in a state suitable for playback
+ void cleanup();
+
+private:
+
+ ParamInfo m_info; // information about this parameter
+ EnvelopeSegs m_envSegs; // the list of envelope segments
+ float m_fEnvelopeValue; // our evolving dynamic value
+ double m_dEnvelopeDelta1; // 1st delta of current envelope (w.r.t. seconds)
+ double m_dEnvelopeDelta2; // 2nd delta of current envelope (w.r.t. seconds)
+ BOOL m_bValidDeltas; // TRUE when deltas can be used (e.g. except for sin)
+ BOOL m_bOverride; // TRUE while automation point value is overridden
+ BOOL m_bCaptured; // TRUE while the captured by the UI
+ float m_fOverrideValue; // our override value
+ REFERENCE_TIME m_rtRendered; // latest time rendered so far
+
+private:
+
+ CParamEnvelope( const CParamEnvelope& );
+ CParamEnvelope& operator=( const CParamEnvelope& );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // !defined(AFX_PARAMENVELOPE_H__F04D0178_4674_45AF_9F7A_5C8206DE4CF6__INCLUDED_)
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/Parameters.h b/Src/Plugins/DSP/dsp_sps/dxi/Parameters.h
new file mode 100644
index 00000000..f0bbfb3c
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/Parameters.h
@@ -0,0 +1,47 @@
+// Declarations of automated parameters used by the plug-in
+
+////////////////////////////////////////////////////////////////////////////////
+#ifndef DEFINE_PARAM_INFO
+////////////////////////////////////////////////////////////////////////////////
+
+enum
+{
+ PARAM_ENABLE,
+
+ // TODO: Add new automated parameter IDs here
+
+ NUM_AUTOMATED_PARAMS,
+
+ // TODO: Add new internal parameter IDs here. Make sure to assign the
+ // first value to NUM_AUTOMATED_PARAMS, i.e.,
+ //
+ // _PARAM_INTERNAL1 = NUM_AUTOMATED_PARAMS,
+ // _PARAM_INTERNAL2,
+ // ...
+
+ NUM_PARAMS
+};
+
+////////////////////////////////////////////////////////////////////////////////
+#else
+////////////////////////////////////////////////////////////////////////////////
+
+#define MP_NONE (0)
+#define MP_JUMP (MP_CURVE_JUMP)
+#define MP_LINES (MP_CURVE_JUMP|MP_CURVE_LINEAR)
+#define MP_QUADS (MP_CURVE_JUMP|MP_CURVE_LINEAR|MP_CURVE_SQUARE|MP_CURVE_INVSQUARE)
+#define MP_ALL (MP_CURVE_JUMP|MP_CURVE_LINEAR|MP_CURVE_SQUARE|MP_CURVE_INVSQUARE|MP_CURVE_SINE)
+
+const ParamInfo CMediaParams::m_aParamInfo[ NUM_PARAMS ] =
+{
+// MP_TYPE MP_CAPS min max def units label int.min int.max "Enum1,Enum2,.."
+// ------- ------- --- --- --- ----- ----- ------- ------- ---------------
+{ MPT_BOOL, MP_QUADS, 0, 1, 1, L"", L"Enabled", 0, 1, NULL },
+
+// TODO: Add entries for additional parameters here
+
+};
+
+////////////////////////////////////////////////////////////////////////////////
+#endif // DEFINE_PARAM_INFO
+////////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.cpp b/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.cpp
new file mode 100644
index 00000000..be1fdfbf
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.cpp
@@ -0,0 +1,192 @@
+// PlugInApp.cpp : Defines the initialization routines for the DLL.
+//
+
+#include "stdafx.h"
+#include "PlugInApp.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
+
+BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
+{
+ return DllEntryPoint( hInstance, ulReason, pv );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+LONG recursiveDeleteKey( HKEY hKeyParent, // Parent of key to delete
+ const char* lpszKeyChild ) // Key to delete
+{
+ // Open the child.
+ HKEY hKeyChild ;
+ LONG lRes = RegOpenKeyEx( hKeyParent, lpszKeyChild, 0, KEY_ALL_ACCESS, &hKeyChild );
+ if (lRes != ERROR_SUCCESS)
+ {
+ return lRes;
+ }
+
+ // Enumerate all of the decendents of this child.
+ FILETIME time;
+ char szBuffer[ 256 ];
+ DWORD dwSize = 256;
+ while (RegEnumKeyEx( hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time ) == S_OK)
+ {
+ // Delete the decendents of this child.
+ lRes = recursiveDeleteKey( hKeyChild, szBuffer );
+ if (lRes != ERROR_SUCCESS)
+ {
+ // Cleanup before exiting.
+ RegCloseKey( hKeyChild );
+ return lRes;
+ }
+ dwSize = 256;
+ }
+
+ // Close the child.
+ RegCloseKey( hKeyChild );
+
+ // Delete this child.
+ return RegDeleteKey( hKeyParent, lpszKeyChild );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static const char* s_pszReg = "CakewalkPlugIns\\";
+
+extern CFactoryTemplate g_Templates[];
+extern int g_cTemplates;
+
+////////////////////////////////////////////////////////////////////////////////
+
+STDAPI DllRegisterServer()
+{
+ HKEY hKey = 0;
+ char sz[ _MAX_PATH ];
+ OLECHAR wsz[ _MAX_PATH ];
+ char szCLSID[ 64 ];
+ ITypeLib* pTypeLib = 0;
+ int i = 0;
+ HRESULT hr = E_FAIL;
+
+ // Do DirectShow registration
+ hr = AMovieDllRegisterServer2( TRUE );
+ if (FAILED( hr ))
+ goto DONE;
+
+ // Get our full pathname, converting to multibyte
+ GetModuleFileName( g_hInst, sz, sizeof sz );
+ if (0 == MultiByteToWideChar( CP_ACP, 0, sz, _MAX_PATH, wsz, _MAX_PATH ))
+ goto DONE;
+
+ // Iterate over all exported CLSIDs
+ for (i = 0; i < g_cTemplates; i++)
+ {
+ CFactoryTemplate* pT = &g_Templates[ i ];
+
+ if (NULL != pT->m_pAMovieSetup_Filter)
+ {
+ // For backwards compatability, instantiate all servers and get hold of
+ // IAMovieSetup (if implemented) and call IAMovieSetup.Register() method
+ if (NULL != pT->m_lpfnNew)
+ {
+ IAMovieSetup* pSetup = 0;
+ if (SUCCEEDED( CoCreateInstance( *(pT->m_ClsID), 0, CLSCTX_INPROC_SERVER,
+ IID_IAMovieSetup, (void**)&pSetup ) ))
+ {
+ pSetup->Register();
+ pSetup->Release();
+ }
+ }
+
+ // Convert the CLSID to an ANSI string
+ StringFromGUID2( *(pT->m_ClsID), wsz, sizeof wsz );
+ if (0 == WideCharToMultiByte( CP_ACP, 0, wsz, -1, szCLSID, sizeof szCLSID, NULL, NULL ))
+ goto DONE;
+
+ // Add {...} to HKEY_CLASSES_ROOT\<s_pszReg>
+ strcpy( sz, s_pszReg );
+ strcat( sz, szCLSID );
+ if (ERROR_SUCCESS != RegCreateKey( HKEY_CLASSES_ROOT, sz, &hKey ))
+ goto DONE;
+
+ // {...}\Description = <description text>
+ if (0 == WideCharToMultiByte( CP_ACP, 0, pT->m_Name, -1, sz, sizeof sz, NULL, NULL ))
+ goto DONE;
+ RegSetValueEx( hKey, "Description", 0, REG_SZ, (BYTE*)sz, strlen(sz) );
+
+ // Written for backwards compatability with SONAR 1.x and Pro Audio:
+ // {...}\HelpFilePath = ""
+ // {...}\HelpFileTopic = ""
+ *sz = 0;
+ RegSetValueEx( hKey, "HelpFilePath", 0, REG_SZ, (BYTE*)sz, 1 );
+ RegSetValueEx( hKey, "HelpFileTopic", 0, REG_SZ, (BYTE*)sz, 1 );
+
+ RegCloseKey( hKey );
+ hKey = 0;
+ }
+ }
+
+ hr = S_OK;
+
+DONE:
+
+
+ if (hKey)
+ RegCloseKey( hKey );
+
+ return hr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+STDAPI DllUnregisterServer()
+{
+ char sz[ _MAX_PATH ];
+ OLECHAR wsz[ _MAX_PATH ];
+ char szCLSID[ 64 ];
+ int i = 0;
+ HRESULT hr = E_FAIL;
+
+ // Do DirectShow unregistration
+ hr = AMovieDllRegisterServer2( FALSE );
+ if (FAILED( hr ))
+ goto DONE;
+
+ // Iterate over all exported CLSIDs
+ for (i = 0; i < g_cTemplates; i++)
+ {
+ CFactoryTemplate* pT = &g_Templates[ i ];
+
+ // For backwards compatability, instantiate all servers and get hold of
+ // IAMovieSetup (if implemented) and call IAMovieSetup.Register() method
+ if (NULL != pT->m_lpfnNew)
+ {
+ IAMovieSetup* pSetup = 0;
+ if (SUCCEEDED( CoCreateInstance( *(pT->m_ClsID), 0, CLSCTX_INPROC_SERVER,
+ IID_IAMovieSetup, (void**)&pSetup ) ))
+ {
+ pSetup->Unregister();
+ pSetup->Release();
+ }
+ }
+
+ // Convert the CLSID to an ANSI string
+ StringFromGUID2( *(pT->m_ClsID), wsz, sizeof wsz );
+ if (0 == WideCharToMultiByte( CP_ACP, 0, wsz, -1, szCLSID, sizeof szCLSID, NULL, NULL ))
+ goto DONE;
+
+ // Delete HKEY_CLASSES_ROOT\<s_pszReg>
+ strcpy( sz, s_pszReg );
+ strcat( sz, szCLSID );
+ recursiveDeleteKey( HKEY_CLASSES_ROOT, sz );
+ }
+
+ hr = S_OK;
+
+DONE:
+
+ return hr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.h b/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.h
new file mode 100644
index 00000000..f7215ed3
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/PlugInApp.h
@@ -0,0 +1,8 @@
+// PlugInApp.h : main header file for PlugIn.ax
+//
+
+#ifndef _PLUGIN_APP_H_
+#define _PLUGIN_APP_H_
+extern HMODULE g_hInst;
+
+#endif // _PLUGIN_APP_H_
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/PlugInGUIDs.h b/Src/Plugins/DSP/dsp_sps/dxi/PlugInGUIDs.h
new file mode 100644
index 00000000..9476b4ba
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/PlugInGUIDs.h
@@ -0,0 +1,5 @@
+/////////////////////////////////////////////////////////////////////////////
+// Classes exported by this plug-in
+
+const GUID CLSID_Filter = { 0x2d63acbe, 0x64bd, 0x4fd9, { 0xa0, 0x23, 0xe3, 0xa7, 0x60, 0xc9, 0x6a, 0x14 } };
+const GUID CLSID_FilterPropPage = { 0xbf23bd81, 0x6e22, 0x42ab, { 0x9d, 0xa4, 0xc7, 0x93, 0xdb, 0xfc, 0x6, 0x85 } };
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/ReadMe.txt b/Src/Plugins/DSP/dsp_sps/dxi/ReadMe.txt
new file mode 100644
index 00000000..516d83e2
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/ReadMe.txt
@@ -0,0 +1,68 @@
+The Cakewalk DirectX Plug-In Wizard has created
+the following files for you:
+
+AudioPlugIn.h, AudioPlugIn.cpp:
+ CAudioPlugIn, the DirectX plug-in object.
+
+AudioPlugInPropPage.h, AudioPlugInPropPage.cpp:
+ CAudioPlugInPropPage, an class that implements the plug-in's
+ property page (IPropertyPage).
+
+AudioPlugIn.rc
+ This is a listing of all of the Microsoft Windows resources that the
+ program uses. It includes the icons, bitmaps, and cursors that are stored
+ in the RES subdirectory. This file can be directly edited in Microsoft
+ Developer Studio.
+
+res\AudioPlugIn.rc2
+ This file contains resources that are not edited by Microsoft
+ Developer Studio. You should place all resources not
+ editable by the resource editor in this file.
+
+AudioPlugIn.def
+ This file contains information about the DLL that must be
+ provided to run with Microsoft Windows. It defines parameters
+ such as the name and description of the DLL. It also exports
+ functions from the DLL.
+
+AudioPlugIn.clw
+ This file contains information used by ClassWizard to edit existing
+ classes or add new classes. ClassWizard also uses this file to store
+ information needed to create and edit message maps and dialog data
+ maps and to create prototype member functions.
+
+///////////////////////////////////////////////////////////
+Support files:
+
+AudioPlugInApp.h
+AudioPlugInApp.cpp:
+ Entry points for component registration and deregistration.
+
+MediaParams.h
+MediaParams.cpp:
+ CMediaParams, a helper class to implement all pertinent DirectX automation
+ intefaces, such as IMediaParams and IMediaParamsInfo.
+
+ParamEnvelope.h
+ParamEnvelope.cpp:
+ CParamEnvelope, a container for a single parameter's envelope, i.e., its
+ evolving shape over time. CMediaParams keeps a collection of these.
+
+///////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named AudioPlugIn.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+ This is the standard header file, which defines new resource IDs.
+ Microsoft Developer Studio reads and updates this file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.cpp b/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.cpp
new file mode 100644
index 00000000..52fe71a8
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.cpp
@@ -0,0 +1,9 @@
+// stdafx.cpp : source file that includes just the standard includes
+// DShowMFC.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// If the include file below cannot be opened, then you do not have DirectX 8 SDK installed, or do not
+// have its headers in your configured include path.
+#include <d3d8.h>
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.h b/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.h
new file mode 100644
index 00000000..7af62053
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/StdAfx.h
@@ -0,0 +1,43 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__5BCD2B6C_0D14_4C1E_8269_E522431AE0DD__INCLUDED_)
+#define AFX_STDAFX_H__5BCD2B6C_0D14_4C1E_8269_E522431AE0DD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+#include <windowsx.h>
+
+#ifdef _DEBUG
+#define DEBUG // the DirectShow headers use this symbol
+#endif
+
+#include <objbase.h>
+#include <control.h>
+#include <streams.h>
+#include <pstream.h>
+
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+ #define WAVE_FORMAT_IEEE_FLOAT (3)
+#endif
+
+#pragma warning( disable: 4786 ) // identifier was trucated to '255' characters in the debug information
+
+#include <string>
+#include <vector>
+#include <algorithm>
+using namespace std;
+
+#pragma warning( disable: 4355 ) // 'this' : used in base member initialization list
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__5BCD2B6C_0D14_4C1E_8269_E522431AE0DD__INCLUDED_)
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/dmoguids.lib b/Src/Plugins/DSP/dsp_sps/dxi/dmoguids.lib
new file mode 100644
index 00000000..89039a8f
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/dmoguids.lib
Binary files differ
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam.h b/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam.h
new file mode 100644
index 00000000..0ecf149a
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam.h
@@ -0,0 +1,461 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Fri May 03 10:13:47 2002
+ */
+/* Compiler settings for CakeMedParam.idl:
+ Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+*/
+//MIDL_FILE_HEADING( )
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 440
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __CakeMedParam_h__
+#define __CakeMedParam_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IMediaParamsUICallback_FWD_DEFINED__
+#define __IMediaParamsUICallback_FWD_DEFINED__
+typedef interface IMediaParamsUICallback IMediaParamsUICallback;
+#endif /* __IMediaParamsUICallback_FWD_DEFINED__ */
+
+
+#ifndef __IMediaParamsSetUICallback_FWD_DEFINED__
+#define __IMediaParamsSetUICallback_FWD_DEFINED__
+typedef interface IMediaParamsSetUICallback IMediaParamsSetUICallback;
+#endif /* __IMediaParamsSetUICallback_FWD_DEFINED__ */
+
+
+#ifndef __IMediaParamsCapture_FWD_DEFINED__
+#define __IMediaParamsCapture_FWD_DEFINED__
+typedef interface IMediaParamsCapture IMediaParamsCapture;
+#endif /* __IMediaParamsCapture_FWD_DEFINED__ */
+
+
+#ifndef __IMediaParamsUICallback_FWD_DEFINED__
+#define __IMediaParamsUICallback_FWD_DEFINED__
+typedef interface IMediaParamsUICallback IMediaParamsUICallback;
+#endif /* __IMediaParamsUICallback_FWD_DEFINED__ */
+
+
+#ifndef __IMediaParamsSetUICallback_FWD_DEFINED__
+#define __IMediaParamsSetUICallback_FWD_DEFINED__
+typedef interface IMediaParamsSetUICallback IMediaParamsSetUICallback;
+#endif /* __IMediaParamsSetUICallback_FWD_DEFINED__ */
+
+
+#ifndef __IMediaParamsCapture_FWD_DEFINED__
+#define __IMediaParamsCapture_FWD_DEFINED__
+typedef interface IMediaParamsCapture IMediaParamsCapture;
+#endif /* __IMediaParamsCapture_FWD_DEFINED__ */
+
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IMediaParamsUICallback_INTERFACE_DEFINED__
+#define __IMediaParamsUICallback_INTERFACE_DEFINED__
+
+/* interface IMediaParamsUICallback */
+/* [version][uuid][local][object] */
+
+
+EXTERN_C const IID IID_IMediaParamsUICallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("B8E0480A-E08D-4a5d-9228-248017032368")
+ IMediaParamsUICallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ParamsBeginCapture(
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ParamsChanged(
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints,
+ /* [in] */ MP_DATA __RPC_FAR *paData) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ParamsEndCapture(
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMediaParamsUICallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IMediaParamsUICallback __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IMediaParamsUICallback __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParamsBeginCapture )(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParamsChanged )(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints,
+ /* [in] */ MP_DATA __RPC_FAR *paData);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParamsEndCapture )(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints);
+
+ END_INTERFACE
+ } IMediaParamsUICallbackVtbl;
+
+ interface IMediaParamsUICallback
+ {
+ CONST_VTBL struct IMediaParamsUICallbackVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMediaParamsUICallback_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMediaParamsUICallback_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMediaParamsUICallback_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMediaParamsUICallback_ParamsBeginCapture(This,aIndex,cPoints) \
+ (This)->lpVtbl -> ParamsBeginCapture(This,aIndex,cPoints)
+
+#define IMediaParamsUICallback_ParamsChanged(This,aIndex,cPoints,paData) \
+ (This)->lpVtbl -> ParamsChanged(This,aIndex,cPoints,paData)
+
+#define IMediaParamsUICallback_ParamsEndCapture(This,aIndex,cPoints) \
+ (This)->lpVtbl -> ParamsEndCapture(This,aIndex,cPoints)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsUICallback_ParamsBeginCapture_Proxy(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints);
+
+
+void __RPC_STUB IMediaParamsUICallback_ParamsBeginCapture_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsUICallback_ParamsChanged_Proxy(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints,
+ /* [in] */ MP_DATA __RPC_FAR *paData);
+
+
+void __RPC_STUB IMediaParamsUICallback_ParamsChanged_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsUICallback_ParamsEndCapture_Proxy(
+ IMediaParamsUICallback __RPC_FAR * This,
+ /* [in] */ DWORD __RPC_FAR *aIndex,
+ /* [in] */ DWORD cPoints);
+
+
+void __RPC_STUB IMediaParamsUICallback_ParamsEndCapture_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IMediaParamsUICallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMediaParamsSetUICallback_INTERFACE_DEFINED__
+#define __IMediaParamsSetUICallback_INTERFACE_DEFINED__
+
+/* interface IMediaParamsSetUICallback */
+/* [version][uuid][local][object] */
+
+
+EXTERN_C const IID IID_IMediaParamsSetUICallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("F5011136-C416-48b9-8C35-E7C5F9AA6FDF")
+ IMediaParamsSetUICallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetUICallback(
+ /* [in] */ IMediaParamsUICallback __RPC_FAR *pICallback) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMediaParamsSetUICallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IMediaParamsSetUICallback __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IMediaParamsSetUICallback __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IMediaParamsSetUICallback __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetUICallback )(
+ IMediaParamsSetUICallback __RPC_FAR * This,
+ /* [in] */ IMediaParamsUICallback __RPC_FAR *pICallback);
+
+ END_INTERFACE
+ } IMediaParamsSetUICallbackVtbl;
+
+ interface IMediaParamsSetUICallback
+ {
+ CONST_VTBL struct IMediaParamsSetUICallbackVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMediaParamsSetUICallback_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMediaParamsSetUICallback_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMediaParamsSetUICallback_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMediaParamsSetUICallback_SetUICallback(This,pICallback) \
+ (This)->lpVtbl -> SetUICallback(This,pICallback)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsSetUICallback_SetUICallback_Proxy(
+ IMediaParamsSetUICallback __RPC_FAR * This,
+ /* [in] */ IMediaParamsUICallback __RPC_FAR *pICallback);
+
+
+void __RPC_STUB IMediaParamsSetUICallback_SetUICallback_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IMediaParamsSetUICallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMediaParamsCapture_INTERFACE_DEFINED__
+#define __IMediaParamsCapture_INTERFACE_DEFINED__
+
+/* interface IMediaParamsCapture */
+/* [version][uuid][local][object] */
+
+
+EXTERN_C const IID IID_IMediaParamsCapture;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("970FED79-6DEB-4ec4-A6EE-F72C6BA545CC")
+ IMediaParamsCapture : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ParamCapture(
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeCapture,
+ /* [in] */ MP_FLAGS flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ParamRelease(
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeRelease,
+ /* [in] */ MP_FLAGS flags) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMediaParamsCaptureVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IMediaParamsCapture __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IMediaParamsCapture __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IMediaParamsCapture __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParamCapture )(
+ IMediaParamsCapture __RPC_FAR * This,
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeCapture,
+ /* [in] */ MP_FLAGS flags);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ParamRelease )(
+ IMediaParamsCapture __RPC_FAR * This,
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeRelease,
+ /* [in] */ MP_FLAGS flags);
+
+ END_INTERFACE
+ } IMediaParamsCaptureVtbl;
+
+ interface IMediaParamsCapture
+ {
+ CONST_VTBL struct IMediaParamsCaptureVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMediaParamsCapture_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMediaParamsCapture_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMediaParamsCapture_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMediaParamsCapture_ParamCapture(This,dwIndex,refTimeCapture,flags) \
+ (This)->lpVtbl -> ParamCapture(This,dwIndex,refTimeCapture,flags)
+
+#define IMediaParamsCapture_ParamRelease(This,dwIndex,refTimeRelease,flags) \
+ (This)->lpVtbl -> ParamRelease(This,dwIndex,refTimeRelease,flags)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsCapture_ParamCapture_Proxy(
+ IMediaParamsCapture __RPC_FAR * This,
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeCapture,
+ /* [in] */ MP_FLAGS flags);
+
+
+void __RPC_STUB IMediaParamsCapture_ParamCapture_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IMediaParamsCapture_ParamRelease_Proxy(
+ IMediaParamsCapture __RPC_FAR * This,
+ /* [in] */ DWORD dwIndex,
+ /* [in] */ REFERENCE_TIME refTimeRelease,
+ /* [in] */ MP_FLAGS flags);
+
+
+void __RPC_STUB IMediaParamsCapture_ParamRelease_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IMediaParamsCapture_INTERFACE_DEFINED__ */
+
+
+
+#ifndef __CakeMedParam_LIBRARY_DEFINED__
+#define __CakeMedParam_LIBRARY_DEFINED__
+
+/* library CakeMedParam */
+/* [helpstring][version][uuid] */
+
+
+
+
+
+EXTERN_C const IID LIBID_CakeMedParam;
+#endif /* __CakeMedParam_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam_i.c b/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam_i.c
new file mode 100644
index 00000000..a166776e
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/include/CakeMedParam_i.c
@@ -0,0 +1,53 @@
+/* this file contains the actual definitions of */
+/* the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Fri May 03 10:13:47 2002
+ */
+/* Compiler settings for CakeMedParam.idl:
+ Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: allocation ref bounds_check enum stub_data
+*/
+//MIDL_FILE_HEADING( )
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+const IID IID_IMediaParamsUICallback = {0xB8E0480A,0xE08D,0x4a5d,{0x92,0x28,0x24,0x80,0x17,0x03,0x23,0x68}};
+
+
+const IID IID_IMediaParamsSetUICallback = {0xF5011136,0xC416,0x48b9,{0x8C,0x35,0xE7,0xC5,0xF9,0xAA,0x6F,0xDF}};
+
+
+const IID IID_IMediaParamsCapture = {0x970FED79,0x6DEB,0x4ec4,{0xA6,0xEE,0xF7,0x2C,0x6B,0xA5,0x45,0xCC}};
+
+
+const IID LIBID_CakeMedParam = {0xA8F8EF3E,0x4E39,0x49e2,{0x89,0xE7,0x3C,0x91,0x94,0x2C,0xC5,0x7B}};
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/include/DXi.h b/Src/Plugins/DSP/dsp_sps/dxi/include/DXi.h
new file mode 100644
index 00000000..44ce0dd1
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/include/DXi.h
@@ -0,0 +1,121 @@
+#ifndef _DXI_H_
+#define _DXI_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <DeferZeroFill.h>
+
+// DirectX automation helper
+#include "MediaParams.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct AudioBuffer
+{
+ long cSamp; // number of samples in the buffer
+ long lOffset; // offset into the data to process
+ IMediaSample* pms; // the raw IMediaSample for this buffer
+
+ AudioBuffer() : cSamp(0), lOffset(0), pms(NULL) {}
+
+ //----------------------------------------------------------------------------
+ // Get a pointer to the audio samples, zero-filling if necesssary
+
+ float* GetPointer()
+ {
+ // Get the raw-pointer
+ BYTE* pb = NULL;
+ pms->GetPointer( &pb );
+
+ // We cannot defer the zero fill any longer!
+ if (bZero)
+ {
+ IDeferZeroFill* pdzf;
+ if (SUCCEEDED( pms->QueryInterface( IID_IDeferZeroFill, (void**)&pdzf ) ))
+ {
+ // IDeferZeroFill will have taken care of the zero-fill for us, by
+ // virtue of our calling IMediaSample::GetPointer. Nothing more to do.
+ pdzf->Release();
+ }
+ else
+ {
+ // No IDeferZeroFill is available. We must zero-fill the hard way.
+ memset( pb, 0, cSamp * sizeof(float) );
+ }
+ bZero = FALSE;
+ }
+
+ return reinterpret_cast<float*>( pb + lOffset );
+ }
+
+ //----------------------------------------------------------------------------
+ // Allow buffers to be tagged as being all zeroes, without actually filling
+ // any data until someone asks for the buffer pointer
+
+ BOOL GetZerofill() const { return bZero; }
+
+ void SetZerofill( BOOL bZerofill )
+ {
+ bZero = bZerofill;
+ IDeferZeroFill* pdzf;
+ if (SUCCEEDED( pms->QueryInterface( IID_IDeferZeroFill, (void**)&pdzf ) ))
+ {
+ pdzf->put_NeedsZerofill( bZero );
+ pdzf->Release();
+ }
+ }
+
+private:
+
+ BOOL bZero;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class CDXi : public CCritSec
+{
+public:
+
+ virtual HRESULT Initialize() = 0;
+
+ virtual HRESULT IsValidInputFormat( const WAVEFORMATEX* pwfx ) const = 0;
+ virtual HRESULT IsValidOutputFormat( const WAVEFORMATEX* pwfx ) const = 0;
+ virtual HRESULT IsValidTransform( const WAVEFORMATEX* pwfxIn, const WAVEFORMATEX* pwfxOut ) const = 0;
+ virtual HRESULT SuggestOutputFormat( WAVEFORMATEX* pwfx ) const = 0;
+
+ virtual const WAVEFORMATEX* GetInputFormat() const { return &m_wfxIn; }
+ virtual const WAVEFORMATEX* GetOutputFormat() const { return &m_wfxOut; }
+
+ virtual HRESULT Process( LONGLONG llSampAudioTimestamp,
+ AudioBuffer* pbufIn,
+ AudioBuffer* pbufOut ) = 0;
+
+ virtual HRESULT AllocateResources() = 0;
+ virtual HRESULT FreeResources() = 0;
+
+ virtual int PersistGetSize() const = 0;
+ virtual HRESULT PersistLoad( IStream* pStream ) = 0;
+ virtual HRESULT PersistSave( IStream* pStream ) = 0;
+
+protected:
+ WAVEFORMATEX m_wfxIn;
+ WAVEFORMATEX m_wfxOut;
+ CMediaParams* m_pMediaParams;
+
+ float GetParamValue( DWORD dwParam ) const
+ {
+ return m_pMediaParams->GetParamEnvelope( dwParam ).GetCurrentValue();
+ }
+
+ HRESULT GetParamDeltas( DWORD dwParam, double* pdDelta1, double* pdDelta2 ) const
+ {
+ return m_pMediaParams->GetParamEnvelope( dwParam ).GetCurrentDeltas( pdDelta1, pdDelta2 );
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif //_DXI_H_
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/include/DeferZeroFill.h b/Src/Plugins/DSP/dsp_sps/dxi/include/DeferZeroFill.h
new file mode 100644
index 00000000..4aa13e8e
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/include/DeferZeroFill.h
@@ -0,0 +1,33 @@
+// IDeferZeroFill interface exposed a custom memory allocator and media sample.
+//
+// Copyright (C) 1997- Cakewalk Music Software. All rights reserved.
+//
+
+#ifndef _DEFERZEROFILL_H_
+#define _DEFERZEROFILL_H_
+
+/////////////////////////////////////////////////////////////////////////////
+// Clients that wish to create real copies of the GUID must first include INITGUID.H
+
+// {447DA113-4AC8-4833-849A-2BA285E1E52B}
+DEFINE_GUID(IID_IDeferZeroFill,
+0x447da113, 0x4ac8, 0x4833, 0x84, 0x9a, 0x2b, 0xa2, 0x85, 0xe1, 0xe5, 0x2b);
+
+#undef INTERFACE
+#define INTERFACE IDeferZeroFill
+
+DECLARE_INTERFACE_( IDeferZeroFill, IUnknown )
+{
+ // *** IUnknown methods ***
+ STDMETHOD_(HRESULT, QueryInterface)( THIS_ REFIID riid, LPVOID* ppvObj ) PURE;
+ STDMETHOD_(ULONG, AddRef)( THIS ) PURE;
+ STDMETHOD_(ULONG, Release)( THIS ) PURE;
+
+ // *** IDeferZeroFill methods ***
+ STDMETHOD_(BOOL, get_NeedsZerofill)( THIS ) PURE;
+ STDMETHOD_(void, put_NeedsZerofill)( THIS_ BOOL bZero ) PURE;
+ STDMETHOD_(HRESULT, GetRawPointer)( THIS_ BYTE** ppBuffer ) PURE;
+};
+
+#endif // _DEFERZEROFILL_H_
+
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/res/AudioPlugIn.rc2 b/Src/Plugins/DSP/dsp_sps/dxi/res/AudioPlugIn.rc2
new file mode 100644
index 00000000..2f7a81fc
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/res/AudioPlugIn.rc2
@@ -0,0 +1,13 @@
+//
+// MFCDELAY.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Src/Plugins/DSP/dsp_sps/dxi/resource.h b/Src/Plugins/DSP/dsp_sps/dxi/resource.h
new file mode 100644
index 00000000..a51c6904
--- /dev/null
+++ b/Src/Plugins/DSP/dsp_sps/dxi/resource.h
@@ -0,0 +1,59 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by AudioPlugIn.rc
+//
+#define IDS_NAME_PLUGIN 1
+#define IDS_DESC_PLUGIN 2
+#define IDS_SETTINGS 3
+#define IDS_HELPFILE_PLUGIN 4
+#define IDD_PROPPAGE 200
+#define IDC_STATIC -1
+#define IDD_DIALOG1 101
+#define IDD_EVAL_HELP 166
+#define IDC_SLIDER1 1000
+#define IDC_SLIDER1_LABEL 1001
+#define IDC_SLIDER1_LABEL1 1001
+#define IDC_SLIDER1_LABEL2 1002
+#define IDC_SLIDER1_LABEL3 1003
+#define IDC_SLIDER2 1004
+#define IDC_SLIDER2_LABEL1 1005
+#define IDC_SLIDER2_LABEL2 1006
+#define IDC_SLIDER2_LABEL3 1007
+#define IDC_SLIDER3 1008
+#define IDC_SLIDER3_LABEL1 1009
+#define IDC_SLIDER3_LABEL2 1010
+#define IDC_SLIDER3_LABEL3 1011
+#define IDC_SLIDER4 1012
+#define IDC_LOAD 1013
+#define IDC_EDIT 1014
+#define IDC_SAVE 1015
+#define IDC_BYPASS 1016
+#define IDC_NEW 1017
+#define IDC_PRESET 1018
+#define IDC_SHOWHELP 1019
+#define IDC_SLIDER4_LABEL2 1020
+#define IDC_SLIDER4_LABEL3 1021
+#define IDC_SLIDER4_LABEL1 1022
+#define IDC_TRIGGER1 1023
+#define IDC_TRIGGER2 1024
+#define IDC_TRIGGER3 1025
+#define IDC_TRIGGER4 1026
+#define IDC_EDIT1 1089
+#define IDC_PERSAMPLE 1090
+#define IDC_INIT 1092
+#define IDC_ONSLIDERCHANGE 1093
+#define IDC_TAB1 1203
+#define IDC_PRESETNAME -1
+
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 1100
+#define _APS_NEXT_SYMED_VALUE 5
+#endif
+#endif