//------------------------------------------------------------------------- // Description: // // Validates input/output format pair during LockForProcess. // // Parameters: // // u32NumInputConnections - [in] number of input connections attached to this APO // ppInputConnections - [in] format of each input connection attached to this APO // u32NumOutputConnections - [in] number of output connections attached to this APO // ppOutputConnections - [in] format of each output connection attached to this APO // // Return values: // // S_OK Connections are valid. // // See Also: // // CBaseAudioProcessingObject::LockForProcess // // Remarks: // // This method is an internal call that is called by the default implementation of // CBaseAudioProcessingObject::LockForProcess(). This is called after the connections // are validated for simple conformance to the APO's registration properties. It may be // used to verify that the APO is initialized properly and that the connections that are passed // agree with the data used for initialization. Any failure code passed back from this // function will get returned by LockForProcess, and cause it to fail. // // By default, this routine just ASSERTS and returns S_OK. // HRESULT CSwapAPOGFX::ValidateAndCacheConnectionInfo(UINT32 u32NumInputConnections, APO_CONNECTION_DESCRIPTOR** ppInputConnections, UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) { ASSERT_NONREALTIME(); HRESULT hResult; CComPtr<IAudioMediaType> pFormat; UNCOMPRESSEDAUDIOFORMAT UncompInputFormat, UncompOutputFormat; FLOAT32 f32InverseChannelCount; UNREFERENCED_PARAMETER(u32NumInputConnections); UNREFERENCED_PARAMETER(u32NumOutputConnections); _ASSERTE(!m_bIsLocked); _ASSERTE(((0 == u32NumInputConnections) || (NULL != ppInputConnections)) && ((0 == u32NumOutputConnections) || (NULL != ppOutputConnections))); EnterCriticalSection(&m_CritSec); // get the uncompressed formats and channel masks hResult = ppInputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompInputFormat); IF_FAILED_JUMP(hResult, Exit); hResult = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompOutputFormat); IF_FAILED_JUMP(hResult, Exit); // Since we haven't overridden the IsIn{Out}putFormatSupported APIs in this example, this APO should // always have input channel count == output channel count. The sampling rates should also be eqaul, // and formats 32-bit float. _ASSERTE(UncompOutputFormat.fFramesPerSecond == UncompInputFormat.fFramesPerSecond); _ASSERTE(UncompOutputFormat. dwSamplesPerFrame == UncompInputFormat.dwSamplesPerFrame); // Allocate some locked memory. We will use these as scaling coefficients during APOProcess->ProcessSwapScale hResult = AERT_Allocate(sizeof(FLOAT32)*m_u32SamplesPerFrame, (void**)&m_pf32Coefficients); IF_FAILED_JUMP(hResult, Exit); // Set scalars to decrease volume from 1.0 to 1.0/N where N is the number of channels // starting with the first channel. f32InverseChannelCount = 1.0f/m_u32SamplesPerFrame; for (UINT16 u16Index=0; u16Index<m_u32SamplesPerFrame; u16Index++) { m_pf32Coefficients[u16Index] = 1.0f - (FLOAT32)(f32InverseChannelCount)*u16Index; } Exit: LeaveCriticalSection(&m_CritSec); return hResult;}
//------------------------------------------------------------------------- // Description: // // Report delay added by the APO between samples given on input // and samples given on output. // // Parameters: // // pTime - [out] hundreds-of-nanoseconds of delay added // // Return values: // // S_OK on success, a failure code on failure STDMETHODIMP CSwapAPOMFX::GetLatency(HNSTIME* pTime) { ASSERT_NONREALTIME(); HRESULT hr = S_OK; IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)) { *pTime = 0; } else { *pTime = (m_fEnableDelayMFX ? HNS_DELAY : 0); } Exit: return hr; }
//------------------------------------------------------------------------- // Description: // // Verifies that the APO is ready to process and locks its state if so. // // Parameters: // // u32NumInputConnections - [in] number of input connections attached to this APO // ppInputConnections - [in] connection descriptor of each input connection attached to this APO // u32NumOutputConnections - [in] number of output connections attached to this APO // ppOutputConnections - [in] connection descriptor of each output connection attached to this APO // // Return values: // // S_OK Object is locked and ready to process. // E_POINTER Invalid pointer passed to function. // APOERR_INVALID_CONNECTION_FORMAT Invalid connection format. // APOERR_NUM_CONNECTIONS_INVALID Number of input or output connections is not valid on // this APO. STDMETHODIMP CSwapAPOMFX::LockForProcess(UINT32 u32NumInputConnections, APO_CONNECTION_DESCRIPTOR** ppInputConnections, UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) { ASSERT_NONREALTIME(); HRESULT hr = S_OK; hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections); IF_FAILED_JUMP(hr, Exit); if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX) { m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY); m_iDelayIndex = 0; m_pf32DelayBuffer.Free(); // Allocate one second's worth of audio // // This allocation is being done using CoTaskMemAlloc because the delay is very large // This introduces a risk of glitches if the delay buffer gets paged out // // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames); WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame()); if (nullptr == m_pf32DelayBuffer) { hr = E_OUTOFMEMORY; goto Exit; } } Exit: return hr; }