mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-12-03 11:05:40 +00:00
8c7a192128
Should've did this in the beginning.
73 lines
2 KiB
C++
73 lines
2 KiB
C++
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
|
|
#pragma once
|
|
#include "common/bitfield.h"
|
|
#include "common/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
|