322 lines
9 KiB
C++
322 lines
9 KiB
C++
// Velocity.cpp : Implementation of CVelocityTool
|
|
//
|
|
// Copyright (C) 2000 Microsoft Corporation. All Rights Reserved
|
|
//
|
|
|
|
#include "dmusicc.h"
|
|
#include "dmusici.h"
|
|
#include "debug.h"
|
|
#include "velocity.h"
|
|
#include "toolhelp.h"
|
|
|
|
CVelocityTool::CVelocityTool()
|
|
{
|
|
ParamInfo Params[DMUS_VELOCITY_PARAMCOUNT] =
|
|
{
|
|
{ DMUS_VELOCITY_STRENGTH, MPT_INT,MP_CAPS_ALL,0,100,100,
|
|
L"Percent",L"Strength",NULL }, // Strength - 100% by default
|
|
{ DMUS_VELOCITY_LOWLIMIT, MPT_INT,MP_CAPS_ALL,1,127,1,
|
|
L"Velocity",L"Lower Limit",NULL }, // Lower limit - 1 by default
|
|
{ DMUS_VELOCITY_HIGHLIMIT, MPT_INT,MP_CAPS_ALL,1,127,127,
|
|
L"Velocity",L"Upper Limit",NULL }, // Upper limit - 127 by default
|
|
{ DMUS_VELOCITY_CURVESTART, MPT_INT,MP_CAPS_ALL,1,127,1,
|
|
L"Velocity",L"Curve Start",NULL }, // Curve start - 1 by default
|
|
{ DMUS_VELOCITY_CURVEEND, MPT_INT,MP_CAPS_ALL,1,127,127,
|
|
L"Velocity",L"Curve End",NULL }, // Curve End - 127 by default
|
|
};
|
|
InitParams(DMUS_VELOCITY_PARAMCOUNT,Params);
|
|
m_fMusicTime = TRUE; // override default setting.
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CVelocityTool::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CVelocityTool::Release()
|
|
{
|
|
if( 0 == InterlockedDecrement(&m_cRef) )
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::QueryInterface(const IID &iid, void **ppv)
|
|
{
|
|
if (iid == IID_IUnknown || iid == IID_IDirectMusicTool || iid == IID_IDirectMusicTool8)
|
|
{
|
|
*ppv = static_cast<IDirectMusicTool8*>(this);
|
|
}
|
|
else if(iid == IID_IPersistStream)
|
|
{
|
|
*ppv = static_cast<IPersistStream*>(this);
|
|
}
|
|
else if(iid == IID_IDirectMusicVelocityTool)
|
|
{
|
|
*ppv = static_cast<IDirectMusicVelocityTool*>(this);
|
|
}
|
|
else if(iid == IID_IMediaParams)
|
|
{
|
|
*ppv = static_cast<IMediaParams*>(this);
|
|
}
|
|
else if(iid == IID_IMediaParamInfo)
|
|
{
|
|
*ppv = static_cast<IMediaParamInfo*>(this);
|
|
}
|
|
else if(iid == IID_ISpecifyPropertyPages)
|
|
{
|
|
*ppv = static_cast<ISpecifyPropertyPages*>(this);
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// IPersistStream
|
|
|
|
STDMETHODIMP CVelocityTool::GetClassID(CLSID* pClassID)
|
|
|
|
{
|
|
if (pClassID)
|
|
{
|
|
*pClassID = CLSID_DirectMusicVelocityTool;
|
|
return S_OK;
|
|
}
|
|
return E_POINTER;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// IPersistStream Methods:
|
|
|
|
STDMETHODIMP CVelocityTool::IsDirty()
|
|
|
|
{
|
|
if (m_fDirty) return S_OK;
|
|
else return S_FALSE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CVelocityTool::Load(IStream* pStream)
|
|
{
|
|
EnterCriticalSection(&m_CrSec);
|
|
DWORD dwChunkID;
|
|
DWORD dwSize;
|
|
|
|
HRESULT hr = pStream->Read(&dwChunkID, sizeof(dwChunkID), NULL);
|
|
hr = pStream->Read(&dwSize, sizeof(dwSize), NULL);
|
|
|
|
if(SUCCEEDED(hr) && (dwChunkID == FOURCC_VELOCITY_CHUNK))
|
|
{
|
|
DMUS_IO_VELOCITY_HEADER Header;
|
|
memset(&Header,0,sizeof(Header));
|
|
hr = pStream->Read(&Header, min(sizeof(Header),dwSize), NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SetParam(DMUS_VELOCITY_STRENGTH,(float) Header.lStrength);
|
|
SetParam(DMUS_VELOCITY_LOWLIMIT,(float) Header.lLowLimit);
|
|
SetParam(DMUS_VELOCITY_HIGHLIMIT,(float) Header.lHighLimit);
|
|
SetParam(DMUS_VELOCITY_CURVESTART,(float) Header.lCurveStart);
|
|
SetParam(DMUS_VELOCITY_CURVEEND,(float) Header.lCurveEnd);
|
|
}
|
|
}
|
|
m_fDirty = FALSE;
|
|
LeaveCriticalSection(&m_CrSec);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::Save(IStream* pStream, BOOL fClearDirty)
|
|
|
|
{
|
|
EnterCriticalSection(&m_CrSec);
|
|
DWORD dwChunkID = FOURCC_VELOCITY_CHUNK;
|
|
DWORD dwSize = sizeof(DMUS_IO_VELOCITY_HEADER);
|
|
|
|
HRESULT hr = pStream->Write(&dwChunkID, sizeof(dwChunkID), NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pStream->Write(&dwSize, sizeof(dwSize), NULL);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DMUS_IO_VELOCITY_HEADER Header;
|
|
GetParamInt(DMUS_VELOCITY_STRENGTH,MAX_REF_TIME,&Header.lStrength);
|
|
GetParamInt(DMUS_VELOCITY_LOWLIMIT,MAX_REF_TIME,&Header.lLowLimit);
|
|
GetParamInt(DMUS_VELOCITY_HIGHLIMIT,MAX_REF_TIME,&Header.lHighLimit);
|
|
GetParamInt(DMUS_VELOCITY_CURVESTART,MAX_REF_TIME,&Header.lCurveStart);
|
|
GetParamInt(DMUS_VELOCITY_CURVEEND,MAX_REF_TIME,&Header.lCurveEnd);
|
|
hr = pStream->Write(&Header, sizeof(Header),NULL);
|
|
}
|
|
if (fClearDirty) m_fDirty = FALSE;
|
|
LeaveCriticalSection(&m_CrSec);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetSizeMax(ULARGE_INTEGER* pcbSize)
|
|
|
|
{
|
|
if (pcbSize == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
pcbSize->QuadPart = sizeof(DMUS_IO_VELOCITY_HEADER) + 8; // Data plus RIFF header.
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetPages(CAUUID * pPages)
|
|
|
|
{
|
|
pPages->cElems = 1;
|
|
pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
|
|
if (pPages->pElems == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*(pPages->pElems) = CLSID_VelocityPage;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// IDirectMusicTool
|
|
|
|
STDMETHODIMP CVelocityTool::ProcessPMsg( IDirectMusicPerformance* pPerf,
|
|
DMUS_PMSG* pPMsg )
|
|
{
|
|
// returning S_FREE frees the message. If StampPMsg()
|
|
// fails, there is no destination for this message so
|
|
// free it.
|
|
if(NULL == pPMsg->pGraph )
|
|
{
|
|
return DMUS_S_FREE;
|
|
}
|
|
if (FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
|
|
{
|
|
return DMUS_S_FREE;
|
|
}
|
|
// We need to know the time format so we can call GetParamInt() to read control parameters.
|
|
REFERENCE_TIME rtTime;
|
|
if (m_fMusicTime) rtTime = pPMsg->mtTime;
|
|
else rtTime = pPMsg->rtTime;
|
|
if( pPMsg->dwType == DMUS_PMSGT_NOTE )
|
|
{
|
|
DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG *) pPMsg;
|
|
long lStrength;
|
|
long lLowLimit, lHighLimit, lCurveStart, lCurveEnd;
|
|
GetParamInt(DMUS_VELOCITY_STRENGTH,rtTime,&lStrength);
|
|
GetParamInt(DMUS_VELOCITY_LOWLIMIT,rtTime,&lLowLimit);
|
|
GetParamInt(DMUS_VELOCITY_HIGHLIMIT,rtTime,&lHighLimit);
|
|
GetParamInt(DMUS_VELOCITY_CURVESTART,rtTime,&lCurveStart);
|
|
GetParamInt(DMUS_VELOCITY_CURVEEND,rtTime,&lCurveEnd);
|
|
if (lCurveStart <= lCurveEnd)
|
|
{
|
|
long lNewVelocity;
|
|
if (pNote->bVelocity <= lCurveStart)
|
|
{
|
|
lNewVelocity = lLowLimit;
|
|
}
|
|
else if (pNote->bVelocity >= lCurveEnd)
|
|
{
|
|
lNewVelocity = lHighLimit;
|
|
}
|
|
else
|
|
{
|
|
// For this case, compute the point on the line between (lCurveStart, lLowLimit) and (lCurveEnd, lHighLimit)
|
|
lNewVelocity = lLowLimit + ((lHighLimit - lLowLimit) * (pNote->bVelocity - lCurveStart)) / (lCurveEnd - lCurveStart);
|
|
}
|
|
// Now, calculate the change we want to apply.
|
|
lNewVelocity -= pNote->bVelocity;
|
|
// Scale it to the amount we'll actually do.
|
|
lNewVelocity = (lNewVelocity * lStrength) / 100;
|
|
lNewVelocity += pNote->bVelocity;
|
|
if (lNewVelocity < 1) lNewVelocity = 1;
|
|
if (lNewVelocity > 127) lNewVelocity = 127;
|
|
pNote->bVelocity = (BYTE) lNewVelocity;
|
|
}
|
|
|
|
}
|
|
return DMUS_S_REQUEUE;
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::Clone( IDirectMusicTool ** ppTool)
|
|
|
|
{
|
|
CVelocityTool *pNew = new CVelocityTool;
|
|
if (pNew)
|
|
{
|
|
HRESULT hr = pNew->CopyParamsFromSource(this);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppTool = (IDirectMusicTool *) pNew;
|
|
}
|
|
else
|
|
{
|
|
delete pNew;
|
|
}
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::SetStrength(long lStrength)
|
|
{
|
|
return SetParam(DMUS_VELOCITY_STRENGTH,(float) lStrength);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::SetLowLimit(long lVelocityOut)
|
|
{
|
|
return SetParam(DMUS_VELOCITY_LOWLIMIT,(float) lVelocityOut);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::SetHighLimit(long lVelocityOut)
|
|
{
|
|
return SetParam(DMUS_VELOCITY_HIGHLIMIT,(float) lVelocityOut);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::SetCurveStart(long lVelocityIn)
|
|
{
|
|
return SetParam(DMUS_VELOCITY_CURVESTART,(float) lVelocityIn);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::SetCurveEnd(long lVelocityIn)
|
|
{
|
|
return SetParam(DMUS_VELOCITY_CURVEEND,(float) lVelocityIn);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetStrength(long * plStrength)
|
|
{
|
|
return GetParamInt(DMUS_VELOCITY_STRENGTH,MAX_REF_TIME,plStrength);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetLowLimit(long * plVelocityOut)
|
|
{
|
|
return GetParamInt(DMUS_VELOCITY_LOWLIMIT,MAX_REF_TIME,plVelocityOut);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetHighLimit(long * plVelocityOut)
|
|
{
|
|
return GetParamInt(DMUS_VELOCITY_HIGHLIMIT,MAX_REF_TIME,plVelocityOut);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetCurveStart(long * plVelocityIn)
|
|
{
|
|
return GetParamInt(DMUS_VELOCITY_CURVESTART,MAX_REF_TIME,plVelocityIn);
|
|
}
|
|
|
|
STDMETHODIMP CVelocityTool::GetCurveEnd(long * plVelocityIn)
|
|
{
|
|
return GetParamInt(DMUS_VELOCITY_CURVEEND,MAX_REF_TIME,plVelocityIn);
|
|
}
|