123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AudioInput/WavParser.h>
- namespace Audio
- {
- ///////////////////////////////////////////////////////////////////////////////////////////////
- /*static*/ const AZ::u8 WavFileParser::riff_tag[4] = { 'R', 'I', 'F', 'F' };
- /*static*/ const AZ::u8 WavFileParser::wave_tag[4] = { 'W', 'A', 'V', 'E' };
- /*static*/ const AZ::u8 WavFileParser::fmt__tag[4] = { 'f', 'm', 't', ' ' };
- /*static*/ const AZ::u8 WavFileParser::data_tag[4] = { 'd', 'a', 't', 'a' };
- ///////////////////////////////////////////////////////////////////////////////////////////////
- WavFileParser::WavFileParser()
- {
- ::memset(&m_header, 0, sizeof(m_header));
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- WavFileParser::~WavFileParser()
- {
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- size_t WavFileParser::ParseHeader(AZ::IO::FileIOStream& fileStream)
- {
- if (IsHeaderValid())
- {
- // Header was already parsed then, no work needed.
- return 0;
- }
- AZ_Assert(fileStream.IsOpen(), "WavFileParser::ParseHeader - FileIOStream is not open!\n");
- // Parsers are allowed to seek into the stream if they want in order to perform their task
- // of gathering file information. Will return the byte-offset into the file where the
- // data starts.
- fileStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
- // Begin parsing, start with the RIFF + WAVE tags...
- AZ::u8* writePtr = reinterpret_cast<AZ::u8*>(&m_header);
- size_t copySize = sizeof(m_header.riff) + sizeof(m_header.wave);
- fileStream.Read(copySize, writePtr);
- if (!ValidTag(m_header.riff.tag, WavFileParser::riff_tag))
- {
- AZ_Error("WavFileParser", false, "WavFileParser::ParseHeader - Not a 'RIFF'!\n");
- return 0;
- }
- if (!ValidTag(m_header.wave, WavFileParser::wave_tag))
- {
- AZ_Error("WavFileParser", false, "WavFileParser::ParseHeader - Not a 'RIFF / WAVE'!\n");
- return 0;
- }
- writePtr += copySize;
- bool formatTagFound = false;
- bool dataTagFound = false;
- while (!dataTagFound)
- {
- // read the next tag, check what it is...
- ChunkHeader header;
- copySize = sizeof(header);
- fileStream.Read(copySize, &header);
- if (ValidTag(header.tag, WavFileParser::fmt__tag))
- {
- m_header.fmt.header = header;
- writePtr = reinterpret_cast<AZ::u8*>(&m_header.fmt);
- writePtr += sizeof(m_header.fmt.header); // skip forward because it was already read into the temp chunkheader.
- copySize = sizeof(m_header.fmt) - sizeof(m_header.fmt.header);
- fileStream.Read(copySize, writePtr);
- formatTagFound = true;
- }
- else if (ValidTag(header.tag, WavFileParser::data_tag))
- {
- m_header.data = header;
- dataTagFound = true;
- }
- else
- {
- // Unknown tag, skip by the size specified
- // It is possible that we want to read certain tag data in the future.
- // Tools/encoders may embed extra data in various sections.
- fileStream.Seek(header.size, AZ::IO::GenericStream::ST_SEEK_CUR);
- }
- // Check for Eof (premature)...
- if (fileStream.GetCurPos() == fileStream.GetLength())
- {
- AZ_Error("WavFileParser", false, "WavFileParser::ParseHeader - Got to end of file and did not locate a 'data' chunk!\n");
- return 0;
- }
- }
- if (!ValidTag(m_header.fmt.header.tag, WavFileParser::fmt__tag))
- {
- AZ_Error("WavFileParser", false, "WavFileParser::ParseHeader - Did not find a 'fmt' tag!\n");
- }
- if (!ValidTag(m_header.data.tag, WavFileParser::data_tag))
- {
- AZ_Error("WavFileParser", false, "WavFileParser::ParseHeader - Did not find a 'data' tag!\n");
- }
- #ifdef AZ_DEBUG_BUILD
- if (formatTagFound)
- {
- AZ_TracePrintf("WavFileParser", "Format: %u\n", static_cast<AZ::u32>(GetSampleType()));
- AZ_TracePrintf("WavFileParser", "Channels: %u\n", GetNumChannels());
- AZ_TracePrintf("WavFileParser", "SampleRate: %u\n", GetSampleRate());
- AZ_TracePrintf("WavFileParser", "ByteRate: %u\n", GetByteRate());
- AZ_TracePrintf("WavFileParser", "BitsPerSample: %u\n", GetBitsPerSample());
- AZ_TracePrintf("WavFileParser", "DataSize: %u\n", GetDataSize());
- }
- #endif // AZ_DEBUG_BUILD
- if (dataTagFound && formatTagFound)
- {
- m_headerIsValid = true;
- return fileStream.GetCurPos();
- }
- else
- {
- return 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- AudioInputSampleType WavFileParser::GetSampleType() const
- {
- switch (m_header.fmt.audioFormat)
- {
- case 1:
- return AudioInputSampleType::Int;
- case 3:
- return AudioInputSampleType::Float;
- default:
- return AudioInputSampleType::Unsupported;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- // static
- AZ_FORCE_INLINE bool WavFileParser::ValidTag(const AZ::u8 tag[4], const AZ::u8 name[4])
- {
- return (tag[0] == name[0] && tag[1] == name[1] && tag[2] == name[2] && tag[3] == name[3]);
- }
- } // namespace Audio
|