Пример #1
0
// This function calculates the Root mean square (RMS) of all samples in the buffer,
// converts the result into a reference dB value, and adds it to the volume floating average
void CLAVAudio::UpdateVolumeStats(const BufferDetails &buffer)
{
  const BYTE bSampleSize = get_byte_per_sample(buffer.sfFormat);
  const DWORD dwSamplesPerChannel = buffer.nSamples;
  const BYTE *pBuffer = buffer.bBuffer->Ptr();
  float * const fChAvg = (float *)calloc(buffer.wChannels, sizeof(float));
  for (DWORD i = 0; i < dwSamplesPerChannel; ++i) {
    for (WORD ch = 0; ch < buffer.wChannels; ++ch) {
      const float fSample = get_sample_from_buffer<float>(pBuffer, buffer.sfFormat);
      fChAvg[ch] += fSample * fSample;
      pBuffer += bSampleSize;
    }
  }

  for (int ch = 0; ch < buffer.wChannels; ++ch) {
    if (fChAvg[ch] > FLT_EPSILON) {
      const float fAvgSqrt =  sqrt(fChAvg[ch] / dwSamplesPerChannel);
      const float fDb = 20.0f * log10(fAvgSqrt);
      m_faVolume[ch].Sample(fDb);
    } else {
      m_faVolume[ch].Sample(-100.0f);
    }
  }
  free(fChAvg);
}
Пример #2
0
LAVAudioSampleFormat CLAVAudio::GetBestAvailableSampleFormat(LAVAudioSampleFormat inFormat, int *bits, BOOL bNoFallback)
{
  ASSERT(inFormat >= 0 && inFormat < SampleFormat_Bitstream);

  if (m_FallbackFormat != SampleFormat_None && !bNoFallback)
    return m_FallbackFormat;

  LAVAudioSampleFormat outFormat = sampleFormatMapping[inFormat][0];
  for(int i = 0; i < 5; i++) {
    if (GetSampleFormat(sampleFormatMapping[inFormat][i])) {
      outFormat = sampleFormatMapping[inFormat][i];
      break;
    }
  }

  if (bits && outFormat != inFormat)
    *bits = get_byte_per_sample(outFormat) << 3;

  return outFormat;
}
Пример #3
0
HRESULT CLAVAudio::DecodeDTS(const BYTE * pDataBuffer, int buffsize, int &consumed, HRESULT *hrDeliver)
{
  HRESULT hr = S_FALSE;
  int nPCMLength	= 0;

  BOOL bFlush = (pDataBuffer == nullptr);

  BufferDetails out;

  consumed = 0;
  while (buffsize > 0) {
    nPCMLength = 0;
    if (bFlush) buffsize = 0;

    ASSERT(m_pParser);

    BYTE *pOut = nullptr;
    int pOut_size = 0;
    int used_bytes = av_parser_parse2(m_pParser, m_pAVCtx, &pOut, &pOut_size, pDataBuffer, buffsize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
    if (used_bytes < 0) {
      return E_FAIL;
    } else if(used_bytes == 0 && pOut_size == 0) {
      DbgLog((LOG_TRACE, 50, L"::Decode() - could not process buffer, starving?"));
      break;
    }

    // Timestamp cache to compensate for one frame delay the parser might introduce, in case the frames were already perfectly sliced apart
    // If we used more (or equal) bytes then was output again, we encountered a new frame, update timestamps
    if (used_bytes >= pOut_size && m_bUpdateTimeCache) {
      m_rtStartInputCache = m_rtStartInput;
      m_rtStopInputCache = m_rtStopInput;
      m_rtStartInput = m_rtStopInput = AV_NOPTS_VALUE;
      m_bUpdateTimeCache = FALSE;
    }

    if (!bFlush && used_bytes > 0) {
      buffsize -= used_bytes;
      pDataBuffer += used_bytes;
      consumed += used_bytes;
    }

    if (pOut && pOut_size > 0) {
      // Parse DTS headers
      m_bsParser.Parse(AV_CODEC_ID_DTS, pOut, pOut_size, nullptr);
      unsigned decode_channels = dts_determine_decode_channels(m_bsParser.m_DTSHeader);

      // Init Decoder with new Parameters, if required
      if (m_DTSDecodeChannels != decode_channels) {
        DbgLog((LOG_TRACE, 20, L"::Decode(): Switching to %d channel decoding", decode_channels));
        m_DTSDecodeChannels = decode_channels;

        FlushDTSDecoder();
      }

      int bitdepth = 0, channels = 0, CoreSampleRate = 0, HDSampleRate = 0, profile = 0;
      int unk4 = 0, unk5 = 0;
      nPCMLength = SafeDTSDecode(pOut, pOut_size, m_pDTSDecoderContext->dtsPCMBuffer, 0, 8, &bitdepth, &channels, &CoreSampleRate, &unk4, &HDSampleRate, &unk5, &profile);
      if (nPCMLength > 0 && bitdepth != m_DTSBitDepth) {
        int decodeBits = bitdepth > 16 ? 24 : 16;

        // If the bit-depth changed, instruct the DTS Decoder to decode to the new bit depth, and decode the previous sample again.
        if (decodeBits != m_DTSBitDepth && out.bBuffer->GetCount() == 0) {
          DbgLog((LOG_TRACE, 20, L"::Decode(): The DTS decoder indicated that it outputs %d bits, changing config to %d bits to compensate", bitdepth, decodeBits));
          m_DTSBitDepth = decodeBits;

          FlushDTSDecoder();
          nPCMLength = SafeDTSDecode(pOut, pOut_size, m_pDTSDecoderContext->dtsPCMBuffer, 0, 2, &bitdepth, &channels, &CoreSampleRate, &unk4, &HDSampleRate, &unk5, &profile);
        }
      }
      if (nPCMLength <= 0) {
        DbgLog((LOG_TRACE, 50, L"::Decode() - DTS decoding failed"));
        FlushDTSDecoder(TRUE);
        m_bQueueResync = TRUE;
        continue;
      }

      out.wChannels        = channels;
      out.dwSamplesPerSec  = HDSampleRate;
      out.sfFormat         = m_DTSBitDepth == 24 ? SampleFormat_24 : SampleFormat_16;
      out.dwChannelMask    = get_channel_mask(channels); // TODO
      out.wBitsPerSample   = bitdepth;

      int profile_index = 0;
      while(profile >>= 1) profile_index++;

      if (profile_index > 7)
        m_pAVCtx->profile =  FF_PROFILE_UNKNOWN;
      else if (profile == 0 && !m_bsParser.m_DTSHeader.HasCore)
        m_pAVCtx->profile = FF_PROFILE_DTS_EXPRESS;
      else
        m_pAVCtx->profile = DTSProfiles[profile_index];

      // TODO: get rid of these
      m_pAVCtx->sample_rate = HDSampleRate;
      m_pAVCtx->bits_per_raw_sample = bitdepth;

      // Send current input time to the delivery function
      out.rtStart = m_rtStartInputCache;
      m_rtStartInputCache = AV_NOPTS_VALUE;
      m_bUpdateTimeCache = TRUE;
    }

    // Send to Output
    if (nPCMLength > 0) {
      hr = S_OK;
      out.bBuffer->Append(m_pDTSDecoderContext->dtsPCMBuffer, nPCMLength);
      out.nSamples = out.bBuffer->GetCount() / get_byte_per_sample(out.sfFormat) / out.wChannels;

      if (m_pAVCtx->profile != (1 << 7)) {
        DTSRemapOutputChannels(&out, m_bsParser.m_DTSHeader);
      }

      m_pAVCtx->channels = out.wChannels;
      m_DecodeFormat = out.sfFormat;
      m_DecodeLayout = out.dwChannelMask;

      if (SUCCEEDED(PostProcess(&out))) {
        *hrDeliver = QueueOutput(out);
        if (FAILED(*hrDeliver)) {
          return S_FALSE;
        }
      }
    }
  }