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; }
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; }