|
DXi2 SDK Errata
Page
The following is a list of errors in the
DXi SDK, and how to correct them. This page will be updated as
necessary. You can be informed of new releases of the DXi2 SDK by
filling out the simple Development Kit Update
Notification form.
Note: To determine which version of the
SDK you have installed, go to the Windows Control Panel, Add/Remove
programs, click on "Cakewalk DXi 2 SDK", and then click on the
support information link.
SDK Version
2.0.0.0
Cause
The Win32 DeleteCriticalSection
API was being called multiple times by the termination code.
Solution
Change DXi2 SDK\HostApp\DXiPlayer.cpp:
Move the code at line 144 ...
DeleteCriticalSection( &m_csData );
... to line 56, making it the last step of the CDXiPlayer destructor.
SDK Version
2.0.0.0
Cause
A COM reference count leak in the code to obtain input and output pins
from the patched DXi.
Solution
Change DXi2 SDK\HostApp\DXiClasses\DxFilterGraph.cpp:
(1) Replace the code at line 160 ...
if (count == nOutPin)
return pIPin;
... with this code:
if (count == nOutPin)
{
pIEnumPins->Release();
pIPin->Release();
return pIPin;
}
(2) Replace the code at line 201 ...
if (PINDIR_INPUT
== PinInfo.dir)
return pIPin;
with this code ...
if (PINDIR_INPUT
== PinInfo.dir)
{
pIEnumPins->Release();
pIPin->Release();
return pIPin;
}
SDK Version
2.0.0.0
Cause
The AFX_MANAGE_STATE macro was missing in a required locations.
Solution
Change Filter.cpp,
in your plug-in project.
(1) Add a call to
AFX_MANAGE_STATE as the first line of the CFilter constructor:
CFilter::CFilter( TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr ) :
...
{
AFX_MANAGE_STATE(
AfxGetStaticModuleState() );
...
}
(2) Add a call to
AFX_MANAGE_STATE as the first line of the CFilter destructor:
CFilter::~CFilter()
{
AFX_MANAGE_STATE(
AfxGetStaticModuleState() );
...
}
SDK Version
2.0.0.0
Cause
Missing casts when converting from floating point to integer data
types.
Solution
These errors have been fixed in the 2.0.1.0 SDK.
Please download for a fix.
SDK Version
2.0.0.0
Cause
STLPORT requires some custom configuration if it is to work with the free
.NET compiler outside of visual studio.
Also. the STLPORT mulitset type is not compatible with the DXi SDK's
use of multiset.
Solution
To allow STLPORT to recognize the free .NET compiler, please add the
following lines to the end of stl_user_config.h
# define _STLP_NO_NEW_C_HEADERS 1
# define _STLP_NO_BAD_ALLOC 1
# define _STLP_NO_EXCEPTION_HEADER 1
# define _STLP_USE_NO_IOSTREAMS 1
# undef _STLP_DEBUG
#
undef _STLP_DEBUG_ALLOC
To fix the problem with the STLPORT multiset, you may do one of two
things. First, you can
download the 2.0.1.0 DXi SDK. Second,
edit SoftSynth.h and SoftSynth.cpp, using a vector<DXiEvent>
instead of multiset<DXiEvent> as the data type for m_qPending.
SDK Version
2.0.0.0
Cause
After destroying the filter graph, the memory allocator needs to be told
to
reset its properties, specifically the number of media samples it will
allocate. Not doing this causes the number of media samples to
increase
each time a new DXi is selected.
Solution
Add the following line of code to DXiClasses/DxFilterGraph.cpp.
CFilterGraph::DestroyGraph()
{
...
CHECK(
m_pMemAllocator->FreeAll() );
CHECK(
m_pMemAllocator->ResetProperties( 0 ) ); // NEW NEW
return
hr;
}
SDK Version
2.0.0.0
Cause
A misplaced semicolon in the wizard-generated code.
Solution
Remove the semicolon after "sizeof(DWORD)" in the implentation of
PersistGetSize, located in <project>/<project>.cpp:
int
C$$Safe_root$$::PersistGetSize() const
{
int
const cb
= sizeof(DWORD)
+ NUM_PARAMS * (sizeof(DWORD) + sizeof(float));
return
cb;
}
SDK Version
2.0.0.0
Cause
Non-MFC projects were being configured to use DirectShow's DllEntryPoint
function as the entry point for the DLL.
This is incorrect, because it prevents the C-runtime initialization
code from being run.
Solution
(1) Add the following lines of code to PlugInApp.cpp, in your
project directory:
extern
"C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL WINAPI
DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pv)
{
return
DllEntryPoint( hInstance, ulReason, pv );
}
(2) Go to Project |
Settings, choose settings for All Configurations, click on the [Link]
tab, and select the Output category.
Clear the contents of the Entry-point symbol field.
SDK Version
2.0.0.0
Cause
Cubase attempts to get the size of property page before first setting its
property page site. This
behavior causes the MFC COlePropertyPage base class to report an incorrect
size for the property page.
Solution
Add the following lines of code to the NonDelegatingQueryInterface method
of xxxPropPage.cpp, in your project directory:
STDMETHODIMP
...PropPage::NonDelegatingQueryInterface(...)
{
AFX_MANAGE_STATE(
AfxGetStaticModuleState() );
...
if (S_OK
== hr && m_bFirstQI)
{
// Work around interaction with Cubase, which asks
// for the dialog's size before setting its site
OnSetPageSite();
...
}
return
hr;
}
SDK Version
2.0.0.0
Cause
Sound Forge will only apply parameter changes if the property page's "modified
flag" has been set. The
sample code is missing call(s) to set this flag where needed.
Solution
Call COlePropertyPage::SetModifiedFlag whenever a parameter had been
changed. For example, in the
AutoClip sample, you would need to add this call in 2 places:
void
CAutoClipPropPage::OnEnabled()
{
SetModifiedFlag( TRUE );
...
}
void
CAutoClipPropPage::OnHScroll(...)
{
SetModifiedFlag( TRUE );
...
}
SDK Version
2.0.0.0
Cause
The major media type for plug-in setup data should be MEDIATYPE_Audio, not
MEDIATYPE_NULL. Also, the
filter object needs to implement a GetSetupData method.
Solution
In Filter.cpp, change the following lines of code.
The Major CLSID for sudPinTypes is changed to MEDIATYPE_Audio, the
declarations of all setup data objects are changed from const to static,
and GetSetupData is added.
static
AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_Audio,
// Major CLSID
&MEDIASUBTYPE_NULL
// Minor type
};
static
AMOVIESETUP_PIN psudPins[] =
{
...
};
static
AMOVIESETUP_FILTER sudFilter =
{
...
};
LPAMOVIESETUP_FILTER
CFilter::GetSetupData()
{
return &sudFilter;
}
In Filter.h, add
the following line of code.
class
CFilter ...
{
public:
...
LPAMOVIESETUP_FILTER
GetSetupData();
};
SDK Version
2.0.0.0
Cause
Logic to flush "stale" envelopes in
CParamEnvelope::UpdateValuesForRefTime was incorrect, leading to lost
automation during looping playback. This
logic belongs in CParamEnvelope::AddEnvelope.
Solution
Remove the following lines in ParamEnvelope.cpp:
HRESULT
CParamEnvelope::UpdateValuesForRefTime( ... )
{
...
if (ix > 0)
m_envSegs.erase(
m_envSegs.begin(), m_envSegs.begin() + ix );
Add the following lines
in ParamEnvelope.cpp:
HRESULT
CParamEnvelope::AddEnvelope( ... )
{
...
// Add each segment, noting which one is earliest
REFERENCE_TIME rtMin = _I64_MAX;
for (DWORD ix = 0; ix < cSegments; ix++)
{
...
if (mpes.rtStart < rtMin)
rtMin = mpes.rtStart;
}
// Flush all segments prior to the first newly added one
ix = IndexForRefTime( rtMin );
if (ix >
0)
m_envSegs.erase( m_envSegs.begin(), m_envSegs.begin()+ix );
...
}
SDK Version
2.0.0.0, 2.0.1.0
Cause
Pitch wheel data was being treated as a unsigned value instead of a signed
value, when converted into the MfxEvent format.
Solution
Add the following line in HostApp/SMF.cpp:
case
WHEEL: //
WHEEL <wheellsb> <wheelmsb>
{
...
nWheel
-= 8192; // BUG FIX
event.SetWheel( nWheel );
pTrk->push_back( event
);
break;
}
SDK Version
2.0.0.0, 2.0.1.0
Cause
Logic to update the stream sample position assumed that automation data
was present, and would get handled by a 'for' loop.
Solution
Change the following line in Filter.cpp
HRESULT
CFilterInputPin::Receive( IMediaSample* pms )
{
...
HRESULT
hrProcess = S_OK;
LONGLONG
llPrevPos = m_pFilter->m_llSamplePosition;
LONGLONG
llCurrPos = llPrevPos;
// BUG FIX
...
}
SDK Version
2.0.0.0, 2.0.1.0
Cause
Due to a typopgraphical error, an '=' was used where '==' was
required.
Solution
Change the following line in MediaParams.cpp:
HRESULT
CMediaParams::GetParamText(...)
{
...
if (*pwsz == L',') // BUG FIX
...
}
SDK Version
2.0.0.0, 2.0.1.0
Cause
When converting an OnInput event's tick time to samples, the DXi code
would always position the all events at the start of the buffer (by
subtracting off the first event's time from all events).
This winds up moving the position of time-stamped input events,
like those generated by Cakewalk's Arpeggiator MFX.
The fix is to convert ticks to sample directly from the input
event's time, without repositioning.
Solution
Change the following lines in SoftSynth.cpp:
STDMETHODIMP
CSoftSynth::OnInput( ... )
{
CAutoLock
lock( m_pDXi );
if (NULL == pqIn)
return
E_POINTER;
if (NULL ==
m_pTempoMap)
return E_UNEXPECTED;
long lTimeFirst
= 0; // BUG FIX:
remove this line
int
nCount = 0;
HRESULT
hr = pqIn->GetCount( &nCount );
if (FAILED( hr ))
return hr;
for (int
ix = 0; ix < nCount; ++ix)
{
// Get the next
datum
MfxData
md;
hr
= pqIn->GetAt( ix, &md );
if
(FAILED( hr ))
break;
// BUG
FIX: remove these lines
// Determine the
offset of the first event
if (0 == ix)
lTimeFirst
= md.m_lTime;
// Determine offset in
samples of this event
LONGLONG llSampOffset =
TicksToSamples(
md.m_lTime ); // BUG FIX
...
}
SDK Version
2.0.0.0, 2.0.1.0
Cause
A variable that should have been signed was declared as unsigned, and then
allowing -1 (interpreted as ULONG_MAX due to unsigned) to access an out of
bounds array element. Also, if
the host pre-rolls automation by a long amount, envelopes can be flushed
prematurely.
Solution
Declare loop variable 'ix' as an int instead of a DWORD.
Keep track of the latest time actually rendered, and make sure we
never auto-flush envelopes before that time.
Change the following
lines in ParamEnvelope.cpp:
CParamEnvelope::CParamEnvelope()
:
...
m_bValidDeltas( TRUE
),
m_rtRendered(
0 )
{
}
HRESULT CParamEnvelope::UpdateValuesForRefTime( ... )
{
...
// Keep track of the
latest time rendered so far
m_rtRendered =
max( m_rtRendered, rt );
return
S_OK;
}
HRESULT CParamEnvelope::AddEnvelope( ... )
{
...
for (int ix =
0; ix < cSegments; ix++) // BUG FIX
{
...
}
// Flush all segments
prior to the first newly added one
ix = IndexForRefTime(
rtMin );
if (ix > 0
&& rtMin < m_rtRendered) // BUG FIX
...
}
HRESULT
CParamEnvelope::FlushEnvelope( ... )
{
...
// Once envelopes get thrown away, we need to
redetermine
// our max render time
m_rtRendered =
0; // BUG FIX
cleanup();
return S_OK;
}
Add the following line
to ParamEnvelope.h:
class
CParamEnvelope : public CCritSec
{
...
private:
float
m_fOverrideValue;
REFERENCE_TIME m_rtRendered; // BUG FIX
};
|