mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 16:15:45 -04:00
CDImage: Support generating Q Sub-Channel
This commit is contained in:
@ -21,9 +21,10 @@ public:
|
||||
DATA_SECTOR_SIZE = 2048,
|
||||
SECTOR_SYNC_SIZE = 12,
|
||||
SECTOR_HEADER_SIZE = 4,
|
||||
FRAMES_PER_SECOND = 75, // "sectors"
|
||||
FRAMES_PER_SECOND = 75, // "sectors", or "timecode frames" (not "channel frames")
|
||||
SECONDS_PER_MINUTE = 60,
|
||||
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE
|
||||
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE,
|
||||
SUBCHANNEL_BYTES_PER_FRAME = 12
|
||||
};
|
||||
|
||||
enum class ReadMode : u32
|
||||
@ -33,6 +34,18 @@ public:
|
||||
RawNoSync, // 2340 bytes per sector.
|
||||
};
|
||||
|
||||
enum class TrackMode : u32
|
||||
{
|
||||
Audio, // 2352 bytes per sector
|
||||
Mode1, // 2048 bytes per sector
|
||||
Mode1Raw, // 2352 bytes per sector
|
||||
Mode2, // 2336 bytes per sector
|
||||
Mode2Form1, // 2048 bytes per sector
|
||||
Mode2Form2, // 2324 bytes per sector
|
||||
Mode2FormMix, // 2332 bytes per sector
|
||||
Mode2Raw // 2352 bytes per sector
|
||||
};
|
||||
|
||||
struct SectorHeader
|
||||
{
|
||||
u8 minute;
|
||||
@ -70,6 +83,11 @@ public:
|
||||
return ZeroExtend32(minute) * FRAMES_PER_MINUTE + ZeroExtend32(second) * FRAMES_PER_SECOND + ZeroExtend32(frame);
|
||||
}
|
||||
|
||||
constexpr std::tuple<u8, u8, u8> ToBCD() const
|
||||
{
|
||||
return std::make_tuple<u8, u8, u8>(DecimalToBCD(minute), DecimalToBCD(second), DecimalToBCD(frame));
|
||||
}
|
||||
|
||||
Position operator+(const Position& rhs) { return FromLBA(ToLBA() + rhs.ToLBA()); }
|
||||
Position& operator+=(const Position& pos)
|
||||
{
|
||||
@ -78,7 +96,7 @@ public:
|
||||
}
|
||||
|
||||
#define RELATIONAL_OPERATOR(op) \
|
||||
bool operator op (const Position& rhs) const \
|
||||
bool operator op(const Position& rhs) const \
|
||||
{ \
|
||||
return std::tie(minute, second, frame) op std::tie(rhs.minute, rhs.second, rhs.frame); \
|
||||
}
|
||||
@ -93,6 +111,43 @@ public:
|
||||
#undef RELATIONAL_OPERATOR
|
||||
};
|
||||
|
||||
union SubChannelQ
|
||||
{
|
||||
union Control
|
||||
{
|
||||
u8 bits;
|
||||
|
||||
BitField<u8, u8, 0, 4> adr;
|
||||
BitField<u8, bool, 4, 1> audio_preemphasis;
|
||||
BitField<u8, bool, 5, 1> digital_copy_permitted;
|
||||
BitField<u8, bool, 6, 1> data;
|
||||
BitField<u8, bool, 7, 1> four_channel_audio;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Control control;
|
||||
u8 track_number_bcd;
|
||||
u8 index_number_bcd;
|
||||
u8 relative_minute_bcd;
|
||||
u8 relative_second_bcd;
|
||||
u8 relative_frame_bcd;
|
||||
u8 reserved;
|
||||
u8 absolute_minute_bcd;
|
||||
u8 absolute_second_bcd;
|
||||
u8 absolute_frame_bcd;
|
||||
u16 crc;
|
||||
};
|
||||
|
||||
u8 data[SUBCHANNEL_BYTES_PER_FRAME];
|
||||
|
||||
u16 ComputeCRC() const;
|
||||
};
|
||||
static_assert(sizeof(SubChannelQ) == SUBCHANNEL_BYTES_PER_FRAME, "SubChannelQ is correct size");
|
||||
|
||||
// Helper functions.
|
||||
static u32 GetBytesPerSector(TrackMode mode);
|
||||
|
||||
// Opening disc image.
|
||||
static std::unique_ptr<CDImage> Open(const char* filename);
|
||||
static std::unique_ptr<CDImage> OpenBinImage(const char* filename);
|
||||
@ -126,6 +181,9 @@ public:
|
||||
// Read a single raw sector from the current LBA.
|
||||
bool ReadRawSector(void* buffer);
|
||||
|
||||
// Reads sub-channel Q for the current LBA.
|
||||
virtual bool ReadSubChannelQ(SubChannelQ* subq);
|
||||
|
||||
protected:
|
||||
struct Track
|
||||
{
|
||||
@ -133,6 +191,8 @@ protected:
|
||||
LBA start_lba;
|
||||
u32 first_index;
|
||||
u32 length;
|
||||
TrackMode mode;
|
||||
SubChannelQ::Control control;
|
||||
};
|
||||
|
||||
struct Index
|
||||
@ -145,12 +205,20 @@ protected:
|
||||
u32 index_number;
|
||||
LBA start_lba_in_track;
|
||||
u32 length;
|
||||
TrackMode mode;
|
||||
SubChannelQ::Control control;
|
||||
bool is_pregap;
|
||||
};
|
||||
|
||||
const Index* GetIndexForDiscPosition(LBA pos);
|
||||
const Index* GetIndexForTrackPosition(u32 track_number, LBA track_pos);
|
||||
|
||||
/// Generates sub-channel Q given the specified position.
|
||||
bool GenerateSubChannelQ(SubChannelQ* subq, LBA lba);
|
||||
|
||||
/// Generates sub-channel Q from the given index and index-offset.
|
||||
void GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 index_offset);
|
||||
|
||||
std::string m_filename;
|
||||
u32 m_lba_count = 0;
|
||||
|
||||
|
Reference in New Issue
Block a user