duckstation/src/common/cd_xa.h

70 lines
1.9 KiB
C++

#pragma once
#include "bitfield.h"
#include "types.h"
namespace CDXA {
enum
{
XA_SUBHEADER_SIZE = 4,
XA_ADPCM_SAMPLES_PER_SECTOR_4BIT = 4032, // 28 words * 8 nibbles per word * 18 chunks
XA_ADPCM_SAMPLES_PER_SECTOR_8BIT = 2016 // 28 words * 4 bytes per word * 18 chunks
};
struct XASubHeader
{
u8 file_number;
u8 channel_number;
union Submode
{
u8 bits;
BitField<u8, bool, 0, 1> eor;
BitField<u8, bool, 1, 1> video;
BitField<u8, bool, 2, 1> audio;
BitField<u8, bool, 3, 1> data;
BitField<u8, bool, 4, 1> trigger;
BitField<u8, bool, 5, 1> form2;
BitField<u8, bool, 6, 1> realtime;
BitField<u8, bool, 7, 1> eof;
} submode;
union Codinginfo
{
u8 bits;
BitField<u8, u8, 0, 2> mono_stereo;
BitField<u8, u8, 2, 2> sample_rate;
BitField<u8, u8, 4, 2> bits_per_sample;
BitField<u8, bool, 6, 1> emphasis;
bool IsStereo() const { return mono_stereo == 1; }
bool IsHalfSampleRate() const { return sample_rate == 1; }
u32 GetSampleRate() const { return sample_rate == 1 ? 18900 : 37800; }
u32 GetBitsPerSample() const { return bits_per_sample == 1 ? 8 : 4; }
u32 GetSamplesPerSector() const
{
return bits_per_sample == 1 ? XA_ADPCM_SAMPLES_PER_SECTOR_8BIT : XA_ADPCM_SAMPLES_PER_SECTOR_4BIT;
}
} codinginfo;
};
union XA_ADPCMBlockHeader
{
u8 bits;
BitField<u8, u8, 0, 4> shift;
BitField<u8, u8, 4, 2> filter;
// For both 4bit and 8bit ADPCM, reserved shift values 13..15 will act same as shift=9).
u8 GetShift() const
{
const u8 shift_value = shift;
return (shift_value > 12) ? 9 : shift_value;
}
u8 GetFilter() const { return filter; }
};
static_assert(sizeof(XA_ADPCMBlockHeader) == 1, "XA-ADPCM block header is one byte");
// Decodes XA-ADPCM samples in an audio sector. Stereo samples are interleaved with left first.
void DecodeADPCMSector(const void* data, s16* samples, s32* last_samples);
} // namespace CDXA