ppsspp/Core/Util/AtracTrack.h

114 lines
3.8 KiB
C++

#pragma once
#include "Common/CommonTypes.h"
#include <vector>
#include <string>
// Atrac file parsing.
#define AT3_MAGIC 0x0270
#define AT3_PLUS_MAGIC 0xFFFE
#define PSP_MODE_AT_3_PLUS 0x00001000
#define PSP_MODE_AT_3 0x00001001
constexpr u32 ATRAC3_MAX_SAMPLES = 0x400; // 1024
constexpr u32 ATRAC3PLUS_MAX_SAMPLES = 0x800; // 2048
struct AtracLoopInfo {
int cuePointID;
int type;
int startSample;
int endSample;
int fraction;
int playCount;
};
// This is (mostly) constant info, once a track has been loaded.
struct Track {
// This both does and doesn't belong in Track - it's fixed for an Atrac instance. Oh well.
u32 codecType = 0;
// Size of the full track being streamed or played. Can be a lot larger than the in-memory buffer in the streaming modes.
u32 fileSize = 0;
// Not really used for much except queries, this keeps track of the bitrate of the track (kbps).
u32 bitrate = 64;
// Signifies whether to use a more efficient coding mode with less stereo separation. For our purposes, just metadata,
// not actually used in decoding.
int jointStereo = 0;
// Number of audio channels in the track.
u16 channels = 2;
// The size of an encoded frame in bytes.
u16 bytesPerFrame = 0;
// Byte offset of the first encoded frame in the input buffer. Note: Some samples may be skipped according to firstSampleOffset.
int dataByteOffset = 0;
// How many samples to skip from the beginning of a track when decoding.
// Actually, the real number is this added to FirstOffsetExtra(codecType). You can call
// FirstSampleOffset2() to get that.
// Some use of these offsets around the code seem to be inconsistent, sometimes the extra is included,
// sometimes not.
int firstSampleOffset = 0;
// Last sample number. Inclusive. Though, we made it so that in Analyze, it's exclusive in the file.
// Does not take firstSampleOffset into account.
int endSample = -1;
// NOTE: The below CAN be written.
// Loop configuration. The PSP only supports one loop but we store them all.
std::vector<AtracLoopInfo> loopinfo;
// The actual used loop offsets. These appear to be raw offsets, not taking FirstSampleOffset2() into account.
int loopStartSample = -1;
int loopEndSample = -1;
// Input frame size
int BytesPerFrame() const {
return bytesPerFrame;
}
inline int FirstOffsetExtra() const {
// These first samples are skipped, after first possibly skipping 0-2 full frames, it seems.
return codecType == PSP_MODE_AT_3_PLUS ? 0x170 : 0x45;
}
// Includes the extra offset. See firstSampleOffset comment above.
int FirstSampleOffsetFull() const {
return FirstOffsetExtra() + firstSampleOffset;
}
// Output frame size, different between the two supported codecs.
int SamplesPerFrame() const {
return codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES;
}
int Bitrate() const {
int bitrate = (bytesPerFrame * 352800) / 1000;
if (codecType == PSP_MODE_AT_3_PLUS)
bitrate = ((bitrate >> 11) + 8) & 0xFFFFFFF0;
else
bitrate = (bitrate + 511) >> 10;
return bitrate;
}
// This appears to be buggy, should probably include FirstOffsetExtra?
// Actually the units don't even make sense here.
int DecodePosBySample(int sample) const {
return (u32)(firstSampleOffset + sample / (int)SamplesPerFrame() * bytesPerFrame);
}
// This appears to be buggy, should probably include FirstOffsetExtra?
int FileOffsetBySample(int sample) const {
int offsetSample = sample + firstSampleOffset;
int frameOffset = offsetSample / (int)SamplesPerFrame();
return (u32)(dataByteOffset + bytesPerFrame + frameOffset * bytesPerFrame);
}
void DebugLog() const;
};
int AnalyzeAA3Track(const u8 *buffer, u32 size, u32 filesize, Track *track, std::string *error);
int AnalyzeAtracTrack(const u8 *buffer, u32 size, Track *track, std::string *error);