// // syslink.cpp // /* Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved. */ #include "common.h" #include "private.h" #define STR_MODULENAME "DDKSynth.sys:SysLink: " /***************************************************************************** ***************************************************************************** * CDmSynthStream-- ISynthSinkDMus implementation ***************************************************************************** ****************************************************************************/ #pragma code_seg() /***************************************************************************** * CDmSynthStream::Render() ***************************************************************************** * Render is called from the port driver, to fill the given buffer. This is * in turn forwarded to the synth (which -- roughly -- goes to the different * voices, which goes to the DigitalAudios, which goes to the mix functions). * * Typically, a synthesizer manages converting messages into * rendered wave data in two processes. First, it time stamps the MIDI * messages it receives from the application via calls to * PlayBuffer and places them in its own internal queue. * * Then, in response to Render, it generates audio by pulling MIDI * messages from the queue and synthesizing the appropriate tones within * the time span of the requested render buffer. * * As the synthesizer renders the MIDI messages into the buffer, it * calls RefTimeToSample to translate the MIDI time stamps into sample * positions. This guarantees extremely accurate timing. */ void CDmSynthStream::Render( IN PBYTE pBuffer, IN DWORD dwLength, IN LONGLONG llPosition) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_BLAB, ("CDmSynthStream::Render")); ASSERT(pBuffer); m_pSynth->Mix((short*)pBuffer, dwLength, llPosition); m_llLastPosition = llPosition + dwLength; } /***************************************************************************** * CDmSynthStream::SyncToMaster() ***************************************************************************** * Sync this stream to the master clock, using the given slave time, and * whether we are starting now. */ STDMETHODIMP CDmSynthStream::SyncToMaster(IN REFERENCE_TIME rtSlaveTime, IN BOOL fStart) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_BLAB, ("CDmSynthStream::SyncToMaster")); REFERENCE_TIME rtMasterTime; m_pMasterClock->GetTime(&rtMasterTime); if (!fStart) { m_SampleClock.SyncToMaster(rtSlaveTime, rtMasterTime); } else { m_llStartPosition = ((rtSlaveTime / 1000) * m_PortParams.SampleRate) / 10000; m_SampleClock.Start(m_pMasterClock, m_PortParams.SampleRate, m_llStartPosition); } return S_OK; } /***************************************************************************** * CDmSynthStream::SampleToRefTime() ***************************************************************************** * Translate between sample time and reference clock time. */ STDMETHODIMP CDmSynthStream::SampleToRefTime(IN LONGLONG llSampleTime, OUT REFERENCE_TIME * prtTime) { _DbgPrintF(DEBUGLVL_BLAB, ("CDmSynthStream::SampleToRefTime")); ASSERT(prtTime); m_SampleClock.SampleToRefTime(llSampleTime + m_llStartPosition, prtTime); return S_OK; } /***************************************************************************** * CDmSynthStream::RefTimeToSample() ***************************************************************************** * Translate between sample time and reference clock time. */ STDMETHODIMP CDmSynthStream::RefTimeToSample(IN REFERENCE_TIME rtTime, OUT LONGLONG * pllSampleTime) { _DbgPrintF(DEBUGLVL_BLAB, ("CDmSynthStream::RefTimeToSample")); ASSERT(pllSampleTime); *pllSampleTime = m_SampleClock.RefTimeToSample(rtTime) - m_llStartPosition; return S_OK; }