예제 #1
0
HRESULT CChannelMixer::FlushStream()
{
  HRESULT hr = S_OK;

  CAutoLock lock (&m_csOutputSample);
  if (m_pNextOutSample)
  {
    hr = OutputNextSample();
    if (FAILED(hr))
      Log("CChannelMixer::FlushStream OutputNextSample failed with: 0x%08x", hr);
  }

  return hr;
}
예제 #2
0
void CTimeStretchFilter::OutputSample(bool bForce)
{
  if (m_pNextOutSample)
  {
    UINT32 sampleLen = m_pNextOutSample->GetActualDataLength();
    if (bForce || (sampleLen + m_pOutputFormat->Format.nBlockAlign > DEFAULT_OUT_BUFFER_SIZE))
    {
      HRESULT hr = OutputNextSample();
      m_rtInSampleTime += sampleLen / m_pOutputFormat->Format.nBlockAlign * UNITS / m_pOutputFormat->Format.nSamplesPerSec;

      if (FAILED(hr))
        Log("CTimeStretchFilter::timestretch thread OutputNextSample failed with: 0x%08x", hr);
    }
  }
}
예제 #3
0
void CTimeStretchFilter::OutputSample(bool bForce)
{
  if (m_pNextOutSample)
  {
    UINT32 sampleLen = m_pNextOutSample->GetActualDataLength();
    if (bForce || (sampleLen + m_pOutputFormat->Format.nBlockAlign > m_nOutBufferSize))
    {
      HRESULT hr = OutputNextSample();
      m_rtInSampleTime += (sampleLen * UNITS) / (m_pOutputFormat->Format.nBlockAlign * m_pOutputFormat->Format.nSamplesPerSec);

      if (FAILED(hr))
        Log("CTimeStretchFilter::timestretch thread OutputNextSample failed with: 0x%08x", hr);
    }
  }
}
예제 #4
0
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;
}