• 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.

    Errata

    1. Host Application crashes in KERNEL32 on shutdown (Win9x, ME)

    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.

    2. Host Application leaving an invisible process running upon exit

    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;
        }

    3. Plug-ins created with the DXi 2 Wizard (MFC) do not unload

    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() );
            ...
        }

    4. .NET compiler errors with NonMFC template projects

    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.

    5. Compiler errors when using STLPORT library

    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_NEW_NEW_HEADER 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.

    6. Memory Leak in Sample Host Application

    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;
    }

    7. GetPersistSize Returns The Wrong Value

    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;
    }

    8. Static Objects Are Not Constructed In Non-MFC Plug-Ins

    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.

    9. MFC-based Property Pages Do Not Appear In Cubase

    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;
    }


    10. Parameter Changes Aren't Applied In Sound Forge

    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 );
                ...
          }

    11. Plug-Ins Do Not Appear In Certain Host Applications

    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();
    };

     

    12. Automation Rendering Can "Drop Out" During Looped Playback

    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 );

             ...
          }


    13. Pitch Wheel events are read incorrectly from SMFs

    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;
    }

     

    14. Stream sample position does not update if no automation exists

    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
         
    ...

    }

     

    15. Enumerated parameter values are parsed incorrectly

    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
          ...
    }

     

    16. Live MIDI input timestamps are incorrect for soft synths

    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

          ...

    }


    17. Automation can lock up host app and not be rendered correctly

    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

    };