Ejemplo n.º 1
0
U32 SFXWavStream::read( U8 *buffer, U32 bytes )
{
   AssertFatal( mStream, "SFXWavStream::seek() - Stream is null!" );

   // Read in even sample chunks.
   
   bytes -= bytes % mFormat.getBytesPerSample();

   // Read the data and determine how much we've read.
   // FileStreams apparently report positions past
   // the actual stream length, so manually cap the
   // numbers here.
   
   const U32 oldPosition = mStream->getPosition();
   mStream->read( bytes, buffer );
   U32 newPosition = mStream->getPosition();
   const U32 maxPosition = getDataLength() + mDataStart;
   if( newPosition > maxPosition )
      newPosition = maxPosition;
      
   const U32 numBytesRead = newPosition - oldPosition;

   // TODO: Is it *just* 16 bit samples that needs to 
   // be flipped?  What about 32 bit samples?
   #ifdef TORQUE_BIG_ENDIAN

      // We need to endian-flip 16-bit data.
      if ( getFormat().getBytesPerChannel() == 2 ) 
      {
         U16 *ds = (U16*)buffer;
         U16 *de = (U16*)(buffer+bytes);
         while (ds<de)
         {
            *ds = convertLEndianToHost(*ds);
            ds++;
         }
      }

   #endif

   return numBytesRead;
}
Ejemplo n.º 2
0
bool load_wav(const uint8_t* inData,
              const int32_t inDataLen,
              uint8_t* outData,
              wav_info* outInfo)
{
    if (inData == NULL)
    {
        lmLogError(gSoundAssetGroup, "No input data passed to wav loader");
        return false;
    }
    
    const uint8_t* cursor = inData;
    
    riff_header* riff = (riff_header*)cursor;
    if (riff->header.chunkId[0] != 'R' ||
        riff->header.chunkId[1] != 'I' ||
        riff->header.chunkId[2] != 'F' ||
        riff->header.chunkId[3] != 'F')
    {
        lmLogError(gSoundAssetGroup, "Bad wav file format");
        return false;
    }
    
    if (riff->riffType[0] != 'W' ||
        riff->riffType[1] != 'A' ||
        riff->riffType[2] != 'V' ||
        riff->riffType[3] != 'E')
    {
        lmLogError(gSoundAssetGroup, "Bad wav file format");
        return false;
    }
    
    riff->header.chunkDataSize = convertLEndianToHost(riff->header.chunkDataSize);
    
    if (inDataLen < static_cast<int32_t>(sizeof(chunk_header) + riff->header.chunkDataSize))
    {
        lmLogError(gSoundAssetGroup, "Not enough data in wav buffer");
        return false;
    }
    
    cursor += sizeof(riff_header);
    
    while (cursor < inData + inDataLen)
    {
        chunk_header* curChunkHeader = (chunk_header*)cursor;
        curChunkHeader->chunkDataSize = convertLEndianToHost(curChunkHeader->chunkDataSize);
        
        if (curChunkHeader->chunkId[0] == 'f' &&
            curChunkHeader->chunkId[1] == 'm' &&
            curChunkHeader->chunkId[2] == 't' &&
            curChunkHeader->chunkId[3] == ' ')
        {
            fmt_chunk* fmt = (fmt_chunk*)(cursor + sizeof(chunk_header));
            fmt->compressionType = convertLEndianToHost(fmt->compressionType);
            if (fmt->compressionType != 0x01)
            {
                // This loader only supports simple PCM (8-bit or 16-bit, which should be the most common)
                lmLogError(gSoundAssetGroup, "Unsupported wav format: 0x%2x. Recommend 8 or 16-bit PCM",
                           fmt->compressionType);
                return false;
            }
            
            if (outInfo)
            {
                outInfo->numChannels = convertLEndianToHost(fmt->numChannels);
                outInfo->samplesPerSecond = convertLEndianToHost(fmt->sampleRate);
                outInfo->sampleSize = convertLEndianToHost(fmt->bitsPerSample);
            }
        }
        else if (curChunkHeader->chunkId[0] == 'd' &&
                 curChunkHeader->chunkId[1] == 'a' &&
                 curChunkHeader->chunkId[2] == 't' &&
                 curChunkHeader->chunkId[3] == 'a')
        {
            if (outInfo)
            {
                outInfo->sampleDataSize = curChunkHeader->chunkDataSize;
            }
            
            if (outData != NULL)
            {
                memcpy(outData, cursor + sizeof(chunk_header), curChunkHeader->chunkDataSize);
            }
        }
        
        cursor += sizeof(chunk_header) + curChunkHeader->chunkDataSize;
    }
    
    return true;
}