Ejemplo n.º 1
0
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());
  }
}
Ejemplo n.º 2
0
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();
    }
  }
}
Ejemplo n.º 3
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;
}