void CTimeStretchFilter::CreateOutput(UINT32 nInFrames, UINT32 nOutFrames, double dBias, double dAdjustment, double dAVMult, bool bFlushPartialSample) { HRESULT hr = S_OK; UINT32 maxBufferFrames = DEFAULT_OUT_BUFFER_SIZE / m_pOutputFormat->Format.nBlockAlign; UINT32 nOutFramesTotal = 0; while (nOutFrames > 0) { // try to get an output buffer if none available if (!m_pNextOutSample && FAILED(hr = RequestNextOutBuffer(m_rtInSampleTime))) { Log("CTimeStretchFilter::timestretch thread - Failed to get next output sample!"); break; } BYTE* pOutData = NULL; m_pNextOutSample->GetPointer(&pOutData); if (pOutData) { UINT32 nOffset = m_pNextOutSample->GetActualDataLength(); UINT32 nOffsetInFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; if (nOutFrames > maxBufferFrames - nOffsetInFrames) nOutFrames = maxBufferFrames - nOffsetInFrames; m_pNextOutSample->SetActualDataLength(nOffset + nOutFrames * m_pOutputFormat->Format.nBlockAlign); pOutData += nOffset; receiveSamplesInternal((short*)pOutData, nOutFrames); nOutFramesTotal += nOutFrames; if (m_pMediaType) m_pNextOutSample->SetMediaType(m_pMediaType); OutputSample(bFlushPartialSample); nOutFrames = numSamples(); } } if (nOutFramesTotal > 0) { double rtSampleDuration = (double)nInFrames * (double)UNITS / (double)m_pOutputFormat->Format.nSamplesPerSec; double rtProcessedSampleDuration = (double)(nOutFramesTotal) * (double)UNITS / (double)m_pOutputFormat->Format.nSamplesPerSec; m_pClock->AudioResampled(rtProcessedSampleDuration, rtSampleDuration, dBias, dAdjustment, dAVMult); //Log(m_pClock->DebugData()); } }
void CTimeStretchFilter::CreateOutput(UINT32 nInFrames, UINT32 nOutFrames, double dBias, double dAdjustment, double dAVMult, bool bFlushPartialSample) { HRESULT hr = S_OK; UINT32 maxBufferFrames = m_nOutBufferSize / m_pOutputFormat->Format.nBlockAlign; UINT32 nOutFramesTotal = 0; while (nOutFrames > 0) { // try to get an output buffer if none available if (!m_pNextOutSample && FAILED(hr = RequestNextOutBuffer(m_rtInSampleTime))) { Log("CTimeStretchFilter::timestretch thread - Failed to get next output sample!"); break; } BYTE* pOutData = NULL; m_pNextOutSample->GetPointer(&pOutData); if (pOutData) { UINT32 nOffset = m_pNextOutSample->GetActualDataLength(); UINT32 nOffsetInFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; if (nOutFrames > maxBufferFrames - nOffsetInFrames) nOutFrames = maxBufferFrames - nOffsetInFrames; m_pNextOutSample->SetActualDataLength(nOffset + nOutFrames * m_pOutputFormat->Format.nBlockAlign); pOutData += nOffset; receiveSamplesInternal((short*)pOutData, nOutFrames); nOutFramesTotal += nOutFrames; if (m_pMediaType) m_pNextOutSample->SetMediaType(m_pMediaType); OutputSample(bFlushPartialSample); nOutFrames = numSamples(); } } }
HRESULT CChannelMixer::ProcessData(const BYTE* pData, long cbData, long* pcbDataProcessed) { HRESULT hr = S_OK; long bytesOutput = 0; CAutoLock lock (&m_csOutputSample); while (cbData) { if (m_pNextOutSample) { // If there is not enough space in output sample, flush it long nOffset = m_pNextOutSample->GetActualDataLength(); long nSize = m_pNextOutSample->GetSize(); if (nOffset + m_nOutFrameSize > nSize) { hr = OutputNextSample(); UINT nFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; m_rtInSampleTime += nFrames * UNITS / m_pOutputFormat->Format.nSamplesPerSec; if (FAILED(hr)) { Log("CChannelMixer::ProcessData OutputNextSample failed with: 0x%08x", hr); return hr; } } } // try to get an output buffer if none available if (!m_pNextOutSample && FAILED(hr = RequestNextOutBuffer(m_rtInSampleTime))) { if (pcbDataProcessed) *pcbDataProcessed = bytesOutput + cbData; // we can't realy process the data, lie about it! return hr; } long nOffset = m_pNextOutSample->GetActualDataLength(); long nSize = m_pNextOutSample->GetSize(); BYTE* pOutData = NULL; if (FAILED(hr = m_pNextOutSample->GetPointer(&pOutData))) { Log("CChannelMixer: Failed to get output buffer pointer: 0x%08x", hr); return hr; } ASSERT(pOutData); pOutData += nOffset; int framesToConvert = min(cbData / m_nInFrameSize, (nSize - nOffset) / m_nOutFrameSize); m_pRemap->Remap((float*)pData, (float*)pOutData, framesToConvert); pData += framesToConvert * m_nInFrameSize; bytesOutput += framesToConvert * m_nInFrameSize; cbData -= framesToConvert * m_nInFrameSize; nOffset += framesToConvert * m_nOutFrameSize; m_pNextOutSample->SetActualDataLength(nOffset); if (nOffset + m_nOutFrameSize > nSize) { hr = OutputNextSample(); UINT nFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; m_rtInSampleTime += nFrames * UNITS / m_pOutputFormat->Format.nSamplesPerSec; if (FAILED(hr)) { Log("CChannelMixer::ProcessData OutputNextSample failed with: 0x%08x", hr); return hr; } } // all samples should contain an integral number of frames ASSERT(cbData == 0 || cbData >= m_nInFrameSize); } if (pcbDataProcessed) *pcbDataProcessed = bytesOutput; return hr; }
HRESULT CSampleRateConverter::FlushStream() { HRESULT hr = S_OK; CAutoLock lock (&m_csOutputSample); if (m_pNextOutSample) { if (FAILED(OutputNextSample())) { Log("CSampleRateConverter::FlushStream OutputNextSample failed with: 0x%08x", hr); return hr; } } LONGLONG framesLeft = (m_llFramesInput * m_dSampleRateRation) - m_llFramesOutput; if (framesLeft > 0) { // SRC allows only one call to "flush" so we use a new sample for the last bits of the stream if (!m_pNextOutSample && FAILED(hr = RequestNextOutBuffer(m_rtInSampleTime))) return hr; long nSize = m_pNextOutSample->GetSize(); BYTE *pOutData = NULL; if (FAILED(hr = m_pNextOutSample->GetPointer(&pOutData))) { Log("CSampleRateConverter: Failed to get output buffer pointer: 0x%08x", hr); return hr; } if (nSize / m_nFrameSize < framesLeft) Log("CSampleRateConverter: Overflow - Failed to flush SRC data, increase internal sample size!"); BYTE* tmp[1]; SRC_DATA data; data.data_in = (float*)tmp; data.data_out = (float*)pOutData; data.input_frames = 0; data.output_frames = min(nSize / m_nFrameSize, framesLeft); data.src_ratio = m_dSampleRateRation; data.end_of_input = 1; int srcRet = src_process(m_pSrcState, &data); if (srcRet == 0 && data.output_frames_gen > 0) { ASSERT(data.output_frames_gen == data.output_frames); m_pNextOutSample->SetActualDataLength(data.output_frames_gen * m_nFrameSize); UINT nFrames = m_pNextOutSample->GetActualDataLength() / m_pOutputFormat->Format.nBlockAlign; m_rtInSampleTime += nFrames * UNITS / m_pOutputFormat->Format.nSamplesPerSec; hr = OutputNextSample(); if (FAILED(hr)) { Log("CSampleRateConverter::FlushStream OutputNextSample failed with: 0x%08x", hr); return hr; } } else m_pNextOutSample.Release(); } m_llFramesInput = 0; m_llFramesOutput = 0; int srcRet = src_reset(m_pSrcState); if (srcRet != 0) return S_FALSE; return hr; }
HRESULT CSampleRateConverter::ProcessData(const BYTE* pData, long cbData, long* pcbDataProcessed) { HRESULT hr = S_OK; long bytesProcessed = 0; CAutoLock lock (&m_csOutputSample); while (cbData) { if (m_pNextOutSample) { // If there is not enough space in output sample, flush it long nOffset = m_pNextOutSample->GetActualDataLength(); long nSize = m_pNextOutSample->GetSize(); if (nOffset + m_nFrameSize > nSize) { hr = OutputNextSample(); UINT nFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; m_rtInSampleTime += nFrames * UNITS / m_pOutputFormat->Format.nSamplesPerSec; if (FAILED(hr)) { Log("CSampleRateConverter::ProcessData OutputNextSample failed with: 0x%08x", hr); return hr; } } } // try to get an output buffer if none available if (!m_pNextOutSample && FAILED(hr = RequestNextOutBuffer(m_rtInSampleTime))) { if (pcbDataProcessed) *pcbDataProcessed = bytesProcessed + cbData; // we can't realy process the data, lie about it! return hr; } long nOffset = m_pNextOutSample->GetActualDataLength(); long nSize = m_pNextOutSample->GetSize(); BYTE* pOutData = NULL; if (FAILED(hr = m_pNextOutSample->GetPointer(&pOutData))) { Log("CSampleRateConverter: Failed to get output buffer pointer: 0x%08x", hr); return hr; } ASSERT(pOutData); pOutData += nOffset; SRC_DATA data; data.data_in = (float*)pData; data.data_out = (float*)pOutData; data.input_frames = cbData / m_nFrameSize; data.output_frames = (nSize - nOffset) / m_nFrameSize; data.src_ratio = m_dSampleRateRation; data.end_of_input = 0; int ret = src_process(m_pSrcState, &data); //LogProcessingInfo(&data); bytesProcessed += data.input_frames_used * m_nFrameSize; pData += data.input_frames_used * m_nFrameSize; cbData -= data.input_frames_used * m_nFrameSize; nOffset += data.output_frames_gen * m_nFrameSize; m_llFramesInput += data.input_frames_used; m_llFramesOutput += data.output_frames_gen; m_pNextOutSample->SetActualDataLength(nOffset); if (nOffset + m_nFrameSize > nSize) { hr = OutputNextSample(); UINT nFrames = nOffset / m_pOutputFormat->Format.nBlockAlign; m_rtInSampleTime += nFrames * UNITS / m_pOutputFormat->Format.nSamplesPerSec; if (FAILED(hr)) { Log("CSampleRateConverter::ProcessData OutputNextSample failed with: 0x%08x", hr); return hr; } } // all samples should contain an integral number of frames ASSERT(cbData == 0 || cbData >= m_nFrameSize); } if (pcbDataProcessed) *pcbDataProcessed = bytesProcessed; return hr; }