コード例 #1
0
bool
WaveReader::FindDataOffset()
{
  // RIFF chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "FindDataOffset called with unaligned resource");

  // The "data" chunk may not directly follow the "format" chunk, so skip
  // over any intermediate chunks.
  uint32_t length;
  if (!ScanForwardUntil(DATA_CHUNK_MAGIC, &length)) {
    return false;
  }

  int64_t offset = mDecoder->GetResource()->Tell();
  if (offset <= 0 || offset > UINT32_MAX) {
    NS_WARNING("PCM data offset out of range");
    return false;
  }

  ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor());
  mWaveLength = length;
  mWavePCMOffset = uint32_t(offset);
  return true;
}
コード例 #2
0
bool
WaveReader::LoadFormatChunk()
{
  uint32_t fmtSize, rate, channels, frameSize, sampleFormat;
  char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
  const char* p = waveFormat;

  // RIFF chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadFormatChunk called with unaligned resource");

  // The "format" chunk may not directly follow the "riff" chunk, so skip
  // over any intermediate chunks.
  if (!ScanForwardUntil(FRMT_CHUNK_MAGIC, &fmtSize)) {
    return false;
  }

  if (!ReadAll(waveFormat, sizeof(waveFormat))) {
    return false;
  }

  PR_STATIC_ASSERT(sizeof(uint16_t) +
                   sizeof(uint16_t) +
                   sizeof(uint32_t) +
                   4 +
                   sizeof(uint16_t) +
                   sizeof(uint16_t) <= sizeof(waveFormat));
  if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) {
    NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported");
    return false;
  }

  channels = ReadUint16LE(&p);
  rate = ReadUint32LE(&p);

  // Skip over average bytes per second field.
  p += 4;

  frameSize = ReadUint16LE(&p);

  sampleFormat = ReadUint16LE(&p);

  // PCM encoded WAVEs are not expected to have an extended "format" chunk,
  // but I have found WAVEs that have a extended "format" chunk with an
  // extension size of 0 bytes.  Be polite and handle this rather than
  // considering the file invalid.  This code skips any extension of the
  // "format" chunk.
  if (fmtSize > WAVE_FORMAT_CHUNK_SIZE) {
    char extLength[2];
    const char* p = extLength;

    if (!ReadAll(extLength, sizeof(extLength))) {
      return false;
    }

    PR_STATIC_ASSERT(sizeof(uint16_t) <= sizeof(extLength));
    uint16_t extra = ReadUint16LE(&p);
    if (fmtSize - (WAVE_FORMAT_CHUNK_SIZE + 2) != extra) {
      NS_WARNING("Invalid extended format chunk size");
      return false;
    }
    extra += extra % 2;

    if (extra > 0) {
      PR_STATIC_ASSERT(UINT16_MAX + (UINT16_MAX % 2) < UINT_MAX / sizeof(char));
      nsAutoArrayPtr<char> chunkExtension(new char[extra]);
      if (!ReadAll(chunkExtension.get(), extra)) {
        return false;
      }
    }
  }

  // RIFF chunks are always word (two byte) aligned.
  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
                    "LoadFormatChunk left resource unaligned");

  // Make sure metadata is fairly sane.  The rate check is fairly arbitrary,
  // but the channels check is intentionally limited to mono or stereo
  // because that's what the audio backend currently supports.
  unsigned int actualFrameSize = sampleFormat == 8 ? 1 : 2 * channels;
  if (rate < 100 || rate > 96000 ||
      channels < 1 || channels > MAX_CHANNELS ||
      (frameSize != 1 && frameSize != 2 && frameSize != 4) ||
      (sampleFormat != 8 && sampleFormat != 16) ||
      frameSize != actualFrameSize) {
    NS_WARNING("Invalid WAVE metadata");
    return false;
  }

  ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor());
  mSampleRate = rate;
  mChannels = channels;
  mFrameSize = frameSize;
  if (sampleFormat == 8) {
    mSampleFormat = FORMAT_U8;
  } else {
    mSampleFormat = FORMAT_S16;
  }
  return true;
}
コード例 #3
0
ファイル: s_vox.c プロジェクト: n00ner/xash3d
//-----------------------------------------------------------------------------
// Purpose: Take a NULL terminated sentence, and parse any commands contained in
//			{}.  The string is rewritten in place with those commands removed.
//
// Input  : *pSentenceData - sentence data to be modified in place
//			sentenceIndex - global sentence table index for any data that is
//							parsed out
//-----------------------------------------------------------------------------
void VOX_ParseLineCommands( char *pSentenceData, int sentenceIndex )
{
    char	tempBuffer[512];
    char	*pNext, *pStart;
    int	length, tempBufferPos = 0;

    if( !pSentenceData )
        return;

    pStart = pSentenceData;

    while( *pSentenceData )
    {
        pNext = ScanForwardUntil( pSentenceData, '{' );

        // find length of "good" portion of the string (not a {} command)
        length = pNext - pSentenceData;
        if( tempBufferPos + length > sizeof( tempBuffer ))
        {
            MsgDev( D_ERROR, "sentence too long!\n" );
            return;
        }

        // Copy good string to temp buffer
        Q_memcpy( tempBuffer + tempBufferPos, pSentenceData, length );

        // move the copy position
        tempBufferPos += length;

        pSentenceData = pNext;

        // skip ahead of the opening brace
        if( *pSentenceData ) pSentenceData++;

        // skip whitespace
        while( *pSentenceData && *pSentenceData <= 32 )
            pSentenceData++;

        // simple comparison of string commands:
        switch( Q_tolower( *pSentenceData ))
        {
        case 'l':
            // all commands starting with the letter 'l' here
            if( !Q_strnicmp( pSentenceData, "len", 3 ))
            {
                g_Sentences[sentenceIndex].length = Q_atof( pSentenceData + 3 );
            }
            break;
        case 0:
        default:
            break;
        }

        pSentenceData = ScanForwardUntil( pSentenceData, '}' );

        // skip the closing brace
        if( *pSentenceData ) pSentenceData++;

        // skip trailing whitespace
        while( *pSentenceData && *pSentenceData <= 32 )
            pSentenceData++;
    }

    if( tempBufferPos < sizeof( tempBuffer ))
    {
        // terminate cleaned up copy
        tempBuffer[tempBufferPos] = 0;

        // copy it over the original data
        Q_strcpy( pStart, tempBuffer );
    }
}