ctrff-pub/include/ctrff/bcwav.hpp
2025-05-04 13:32:07 +02:00

188 lines
4.3 KiB
C++

#pragma once
#include <ctrff/binutil.hpp>
#include <ctrff/pd_p_api.hpp>
#include <pd.hpp>
namespace ctrff {
class CTRFF_API BCWAV {
public:
BCWAV() : pReader(pFile) {}
~BCWAV() { CleanUp(); }
void LoadFile(const std::string& path);
void CleanUp();
void ReadGotoBeginning(bool use_loop_beg = false);
void ReadBlock(PD::u32 block, PD::u8* ref);
/** Internal Data (can be made private with private: but public by default) */
enum Endianness : PD::u16 {
Big = 0xfffe, ///< Big Endian
Little = 0xfeff, ///< Little Endian
};
enum ReferenceTypes : PD::u16 {
Ref_DSP_ADPCM_Info = 0x0300,
Ref_IMA_ADPCM_Info = 0x0301,
Ref_SampleData = 0x1f00,
Ref_InfoBlock = 0x7000,
Ref_DataBlock = 0x7001,
Ref_ChannelInfo = 0x7100,
};
enum Encoding : PD::u8 {
PCM8 = 0,
PCM16 = 1,
/** Only supported encoding in BCSTM-Player */
DSP_ADPCM = 2,
IMA_ADPCM = 3,
};
struct Reference {
PD::u16 TypeID;
PD::u16 Padding;
PD::u32 Offset; /** null -> uint32_max */
};
struct ReferenceTable {
PD::u32 Count;
PD::Vec<Reference> Refs;
};
struct SizedReference {
Reference Ref;
PD::u32 Size;
};
struct StreamInfo {
PD::u8 Encoding;
PD::u8 Loop;
PD::u8 ChannelCount;
PD::u8 Padding;
PD::u32 SampleRate;
PD::u32 LoopStartFrame;
PD::u32 LoopEndFrame;
PD::u32 SampleBlockNum;
PD::u32 SampleBlockSize;
PD::u32 SampleBlockSampleNum;
PD::u32 LastSampleBlockSize;
PD::u32 LastSampleBlockSampleNum;
PD::u32 LastSampleBlockPaddedSize;
PD::u32 SeekDataSize;
PD::u32 SeekIntervalSampleNum;
Reference SampleDataRef;
};
struct BlockHeader {
PD::u32 Magic;
PD::u32 Size;
};
struct InfoBlock {
BlockHeader Header;
PD::u8 Encoding;
PD::u8 Loop;
PD::u16 Padding;
PD::u32 SampleRate;
PD::u32 LoopStartFrame;
PD::u32 LoopEndFrame;
PD::u32 Reserved;
ReferenceTable ChannelInfoTab;
PD::Vec<Reference> ChannelInfoRefs; /** The refs of the refs ?? */
};
struct DataBlock {
BlockHeader Header;
PD::u32 Padding[3];
PD::Vec<PD::u8> Data;
};
struct DSP_ADPCM_Param {
PD::u16 Coefficients[0x10];
};
struct DSP_ADPCM_Context {
PD::u8 PredictorScale;
PD::u8 Reserved;
PD::u16 PreviousSample;
PD::u16 SecondPreviousSample;
};
struct DSP_ADPCM_Info {
DSP_ADPCM_Param Param;
DSP_ADPCM_Context Context;
DSP_ADPCM_Context LoopContext;
PD::u16 Padding;
};
struct Header {
PD::u32 Magic; /** CWAV */
PD::u16 Endianness = Little; /** Default */
PD::u16 HeaderSize; /** Header Size probably */
PD::u32 Version; /** Format Version? */
PD::u32 FileSize; /** File Size */
PD::u16 NumBlocks; /** Number of blocks */
PD::u16 Reserved; /** Reserved */
};
Header pHeader;
SizedReference pInfoBlockRef;
SizedReference pDataBlockRef;
InfoBlock pInfoBlock;
DataBlock pDataBlock;
PD::Vec<DSP_ADPCM_Info> pDSP_ADPCM_Info;
/** File Stream */
std::fstream pFile;
/** Endianness based reader */
BinUtil pReader;
void ReadReference(Reference& ref);
void ReadSizedReference(SizedReference& ref);
void ReadInfoBlock(InfoBlock& block);
void ReadReferenceTab(ReferenceTable& tab);
static std::string Endianness2String(const Endianness& e) {
switch (e) {
case Little:
return "Little";
case Big:
return "Big";
default:
return "Unknown";
}
}
static std::string ReferenceType2String(const ReferenceTypes& e) {
switch (e) {
case Ref_DSP_ADPCM_Info:
return "DSP_ADPCM_Info";
case Ref_IMA_ADPCM_Info:
return "IMA_ADPCM_Info";
case Ref_SampleData:
return "SampleData";
case Ref_InfoBlock:
return "InfoBlock";
case Ref_DataBlock:
return "DataBlock";
case Ref_ChannelInfo:
return "ChannelInfo";
default:
return "Unknown";
}
}
static std::string Encoding2String(const Encoding& e) {
switch (e) {
case PCM8:
return "PCM8";
case PCM16:
return "PCM16";
case DSP_ADPCM:
return "DSP ADPCM";
case IMA_ADPCM:
return "IMA ADPCM";
default:
return "Unknown";
}
}
};
} // namespace ctrff