mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Work on the new implementation.
This commit is contained in:
parent
78e763b050
commit
724fc1dd95
4 changed files with 246 additions and 39 deletions
|
@ -192,9 +192,7 @@ public:
|
|||
|
||||
PSPPointer<SceAtracContext> context_{};
|
||||
|
||||
AtracStatus BufferState() const {
|
||||
return bufferState_;
|
||||
}
|
||||
virtual AtracStatus BufferState() const = 0;
|
||||
|
||||
virtual int SetLoopNum(int loopNum) = 0;
|
||||
virtual int LoopNum() const = 0;
|
||||
|
@ -241,7 +239,6 @@ protected:
|
|||
|
||||
// TODO: Save the internal state of this, now technically possible.
|
||||
AudioDecoder *decoder_ = nullptr;
|
||||
AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA;
|
||||
};
|
||||
|
||||
class Atrac : public AtracBase {
|
||||
|
@ -264,6 +261,10 @@ public:
|
|||
|
||||
u8 *BufferStart();
|
||||
|
||||
AtracStatus BufferState() const {
|
||||
return bufferState_;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
int GetNextDecodePosition(int *pos) const override;
|
||||
|
@ -357,4 +358,5 @@ private:
|
|||
u32 bufferHeaderSize_ = 0;
|
||||
|
||||
int atracID_ = -1;
|
||||
AtracStatus bufferState_ = ATRAC_STATUS_NO_DATA;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,8 @@ Atrac2::Atrac2(int atracID, u32 contextAddr, int codecType) {
|
|||
context_ = PSPPointer<SceAtracContext>::Create(contextAddr);
|
||||
track_.codecType = codecType;
|
||||
context_->info.codec = codecType;
|
||||
context_->info.atracID = atracID;
|
||||
context_->info.state = ATRAC_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
void Atrac2::DoState(PointerWrap &p) {
|
||||
|
@ -22,22 +24,53 @@ void Atrac2::DoState(PointerWrap &p) {
|
|||
}
|
||||
|
||||
int Atrac2::RemainingFrames() const {
|
||||
return 0;
|
||||
const SceAtracIdInfo &info = context_->info;
|
||||
|
||||
if (info.state == ATRAC_STATUS_ALL_DATA_LOADED) {
|
||||
// The buffer contains everything.
|
||||
return PSP_ATRAC_ALLDATA_IS_ON_MEMORY;
|
||||
}
|
||||
|
||||
const bool isStreaming = (info.state & ATRAC_STATUS_STREAMED_MASK) != 0;
|
||||
|
||||
if (info.decodePos >= track_.endSample) {
|
||||
if (info.state == ATRAC_STATUS_STREAMED_WITHOUT_LOOP) {
|
||||
return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY;
|
||||
}
|
||||
int loopEndAdjusted = track_.loopEndSample - track_.FirstOffsetExtra() - track_.firstSampleOffset;
|
||||
if (info.state == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER && info.decodePos > loopEndAdjusted) {
|
||||
// No longer looping in this case, outside the loop.
|
||||
return PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY;
|
||||
}
|
||||
if (isStreaming && loopNum_ == 0) {
|
||||
return PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY;
|
||||
}
|
||||
return info.streamDataByte / info.sampleSize;
|
||||
}
|
||||
|
||||
if (isStreaming) {
|
||||
// Since we're streaming, the remaining frames are what's valid in the buffer.
|
||||
return info.streamDataByte / info.sampleSize;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return info.dataEnd / info.sampleSize;
|
||||
}
|
||||
|
||||
u32 Atrac2::SecondBufferSize() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) {
|
||||
|
||||
}
|
||||
|
||||
int Atrac2::AddStreamData(u32 bytesToAdd) {
|
||||
return 0;
|
||||
const SceAtracIdInfo &info = context_->info;
|
||||
return info.secondBufferByte;
|
||||
}
|
||||
|
||||
u32 Atrac2::AddStreamDataSas(u32 bufPtr, u32 bytesToAdd) {
|
||||
_dbg_assert_(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Atrac2::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const {
|
||||
*endSample = track_.endSample;
|
||||
*loopStartSample = track_.loopStartSample == -1 ? -1 : track_.loopStartSample - track_.FirstSampleOffsetFull();
|
||||
*loopEndSample = track_.loopEndSample == -1 ? -1 : track_.loopEndSample - track_.FirstSampleOffsetFull();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -47,19 +80,158 @@ int Atrac2::ResetPlayPosition(int sample, int bytesWrittenFirstBuf, int bytesWri
|
|||
}
|
||||
|
||||
int Atrac2::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int sample) {
|
||||
_dbg_assert_(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Atrac2::GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Atrac2::SetData(const Track &track, u32 buffer, u32 readSize, u32 bufferSize, int outputChannels) {
|
||||
if (readSize == bufferSize) {
|
||||
bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED;
|
||||
} else {
|
||||
bufferState_ = ATRAC_STATUS_HALFWAY_BUFFER;
|
||||
int Atrac2::SetLoopNum(int loopNum) {
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
if (info.loopEnd <= 0) {
|
||||
return SCE_ERROR_ATRAC_NO_LOOP_INFORMATION;
|
||||
}
|
||||
info.loopNum = loopNum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 Atrac2::GetNextSamples() {
|
||||
// This has to be possible to do in an easier way, from the existing state.
|
||||
|
||||
int currentSample = context_->info.decodePos;
|
||||
// It seems like the PSP aligns the sample position to 0x800...?
|
||||
u32 skipSamples = track_.FirstSampleOffsetFull();
|
||||
u32 firstSamples = (track_.SamplesPerFrame() - skipSamples) % track_.SamplesPerFrame();
|
||||
u32 numSamples = track_.endSample + 1 - currentSample;
|
||||
if (currentSample == 0 && firstSamples != 0) {
|
||||
numSamples = firstSamples;
|
||||
}
|
||||
u32 unalignedSamples = (skipSamples + currentSample) % track_.SamplesPerFrame();
|
||||
if (unalignedSamples != 0) {
|
||||
// We're off alignment, possibly due to a loop. Force it back on.
|
||||
numSamples = track_.SamplesPerFrame() - unalignedSamples;
|
||||
}
|
||||
if (numSamples > track_.SamplesPerFrame())
|
||||
numSamples = track_.SamplesPerFrame();
|
||||
return numSamples;
|
||||
}
|
||||
|
||||
int Atrac2::AddStreamData(u32 bytesToAdd) {
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
// if (bytesToAdd > first_.writableBytes)
|
||||
// return SCE_ERROR_ATRAC_ADD_DATA_IS_TOO_BIG;
|
||||
info.streamDataByte += bytesToAdd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atrac2::GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) {
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
|
||||
*readOffset = info.bufferByte;
|
||||
*writePtr = context_->codec.inBuf + info.curOff;
|
||||
|
||||
*writableBytes = 0;
|
||||
// Probably we treat
|
||||
}
|
||||
|
||||
u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) {
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
|
||||
if (!decodeTemp_) {
|
||||
decodeTemp_ = new int16_t[track_.SamplesPerFrame() * track_.channels];
|
||||
}
|
||||
|
||||
/*
|
||||
const uint8_t *indata = Memory::GetPointer(context_->codec.inBuf + info.curOff);
|
||||
int bytesConsumed = 0;
|
||||
int outSamples = 0;
|
||||
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, decodeTemp_, &outSamples)) {
|
||||
// Decode failed.
|
||||
*SamplesNum = 0;
|
||||
*finish = 1;
|
||||
// Is this the right error code? Needs testing.
|
||||
return SCE_ERROR_ATRAC_ALL_DATA_DECODED;
|
||||
}
|
||||
*/
|
||||
|
||||
info.streamDataByte -= info.sampleSize;
|
||||
info.curOff += info.sampleSize;
|
||||
info.decodePos += track_.SamplesPerFrame();
|
||||
|
||||
// This one starts out being the same as curOff but sometimes gets reset??
|
||||
info.unk48 += info.sampleSize;
|
||||
|
||||
*remains = RemainingFrames();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 bufferSize, int outputChannels) {
|
||||
// TODO: Remove track_.
|
||||
track_ = track;
|
||||
|
||||
if (track_.codecType != PSP_MODE_AT_3 && track_.codecType != PSP_MODE_AT_3_PLUS) {
|
||||
// Shouldn't have gotten here, Analyze() checks this.
|
||||
context_->info.state = ATRAC_STATUS_NO_DATA;
|
||||
ERROR_LOG(Log::ME, "unexpected codec type %d in set data", track_.codecType);
|
||||
return SCE_ERROR_ATRAC_UNKNOWN_FORMAT;
|
||||
}
|
||||
|
||||
if (outputChannels != track_.channels) {
|
||||
// TODO: Figure out what this means
|
||||
WARN_LOG(Log::ME, "Atrac::SetData: outputChannels %d doesn't match track_.channels %d", outputChannels, track_.channels);
|
||||
}
|
||||
|
||||
context_->codec.inBuf = bufferAddr;
|
||||
|
||||
// Copied from the old implementation, let's see where they are useful.
|
||||
int bufOff = track_.dataByteOffset + track_.bytesPerFrame;
|
||||
int skipSamples = track_.FirstSampleOffsetFull();
|
||||
int firstExtra = track_.FirstOffsetExtra();
|
||||
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
// Copy parameters into struct.
|
||||
info.buffer = bufferAddr;
|
||||
info.bufferByte = bufferSize;
|
||||
info.samplesPerChan = track_.FirstSampleOffsetFull(); // TODO: Where does 970 come from?
|
||||
info.endSample = track_.endSample + info.samplesPerChan;
|
||||
if (track_.loopStartSample != 0xFFFFFFFF) {
|
||||
info.loopStart = track_.loopStartSample;
|
||||
info.loopEnd = track_.loopEndSample;
|
||||
}
|
||||
info.codec = track_.codecType;
|
||||
info.sampleSize = track_.bytesPerFrame;
|
||||
info.numChan = track_.channels;
|
||||
info.numFrame = 0;
|
||||
info.dataOff = track_.dataByteOffset;
|
||||
info.curOff = 0x1D8; // 472
|
||||
info.unk48 = info.curOff;
|
||||
info.streamDataByte = readSize - info.curOff;
|
||||
info.dataEnd = track_.fileSize;
|
||||
|
||||
if (readSize > track_.fileSize) {
|
||||
WARN_LOG(Log::ME, "readSize %d > track_.fileSize", readSize, track_.fileSize);
|
||||
readSize = track_.fileSize;
|
||||
}
|
||||
|
||||
if (bufferSize >= track_.fileSize) {
|
||||
// Buffer is big enough to fit the whole track.
|
||||
if (readSize < bufferSize) {
|
||||
info.state = ATRAC_STATUS_HALFWAY_BUFFER;
|
||||
} else {
|
||||
info.state = ATRAC_STATUS_ALL_DATA_LOADED;
|
||||
}
|
||||
} else {
|
||||
// Streaming cases with various looping types.
|
||||
if (track_.loopEndSample <= 0) {
|
||||
// There's no looping, but we need to stream the data in our buffer.
|
||||
info.state = ATRAC_STATUS_STREAMED_WITHOUT_LOOP;
|
||||
} else if (track_.loopEndSample == track_.endSample + track_.FirstSampleOffsetFull()) {
|
||||
info.state = ATRAC_STATUS_STREAMED_LOOP_FROM_END;
|
||||
} else {
|
||||
info.state = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER;
|
||||
}
|
||||
}
|
||||
|
||||
CreateDecoder();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -67,16 +239,37 @@ u32 Atrac2::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 Atrac2::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) {
|
||||
int Atrac2::Bitrate() const {
|
||||
const SceAtracIdInfo &info = context_->info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 Atrac2::GetNextSamples() {
|
||||
return 0;
|
||||
int bitrate = (info.sampleSize * 352800) / 1000;
|
||||
if (info.codec == PSP_MODE_AT_3_PLUS)
|
||||
bitrate = ((bitrate >> 11) + 8) & 0xFFFFFFF0;
|
||||
else
|
||||
bitrate = (bitrate + 511) >> 10;
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
void Atrac2::InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) {
|
||||
track_ = Track();
|
||||
track_.codecType = codecType;
|
||||
track_.channels = Memory::Read_U32(paramsAddr);
|
||||
outputChannels_ = Memory::Read_U32(paramsAddr + 4);
|
||||
track_.bytesPerFrame = Memory::Read_U32(paramsAddr + 8);
|
||||
if (track_.codecType == PSP_MODE_AT_3) {
|
||||
track_.bitrate = (track_.bytesPerFrame * 352800) / 1000;
|
||||
track_.bitrate = (track_.bitrate + 511) >> 10;
|
||||
track_.jointStereo = false;
|
||||
} else if (track_.codecType == PSP_MODE_AT_3_PLUS) {
|
||||
track_.bitrate = (track_.bytesPerFrame * 352800) / 1000;
|
||||
track_.bitrate = ((track_.bitrate >> 11) + 8) & 0xFFFFFFF0;
|
||||
track_.jointStereo = false;
|
||||
}
|
||||
track_.dataByteOffset = 0;
|
||||
|
||||
context_->info.decodePos = 0;
|
||||
context_->info.state = ATRAC_STATUS_LOW_LEVEL;
|
||||
CreateDecoder();
|
||||
}
|
||||
|
||||
int Atrac2::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) {
|
||||
|
|
|
@ -7,20 +7,28 @@
|
|||
class Atrac2 : public AtracBase {
|
||||
public:
|
||||
Atrac2(int atracID, u32 contextAddr, int codecType);
|
||||
~Atrac2() {
|
||||
delete[] decodeTemp_;
|
||||
}
|
||||
|
||||
AtracStatus BufferState() const {
|
||||
return context_->info.state;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
int GetID() const override { return 0; }
|
||||
int GetID() const override { return context_->info.atracID; }
|
||||
|
||||
int GetNextDecodePosition(int *pos) const override { return context_->info.decodePos; }
|
||||
|
||||
int GetNextDecodePosition(int *pos) const { return 0; }
|
||||
int RemainingFrames() const override;
|
||||
int LoopStatus() const override { return 0; }
|
||||
int Bitrate() const override { return 0; }
|
||||
int LoopNum() const override { return 0; }
|
||||
int Bitrate() const override;
|
||||
int LoopNum() const override { return context_->info.loopNum; }
|
||||
int SamplesPerFrame() const override { return 0; }
|
||||
int Channels() const override { return 2; }
|
||||
int BytesPerFrame() const override { return 0; }
|
||||
int SetLoopNum(int loopNum) override { return 0; }
|
||||
int Channels() const override { return context_->info.numChan; }
|
||||
int BytesPerFrame() const override { return context_->info.sampleSize; }
|
||||
int SetLoopNum(int loopNum) override;
|
||||
|
||||
void GetStreamDataInfo(u32 *writePtr, u32 *writableBytes, u32 *readOffset) override;
|
||||
int AddStreamData(u32 bytesToAdd) override;
|
||||
|
@ -34,6 +42,7 @@ public:
|
|||
u32 DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, int *remains) override;
|
||||
int DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData, int *bytesWritten) override;
|
||||
u32 GetNextSamples() override;
|
||||
|
||||
void InitLowLevel(u32 paramsAddr, bool jointStereo, int codecType) override;
|
||||
|
||||
int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const override;
|
||||
|
@ -43,5 +52,8 @@ public:
|
|||
void NotifyGetContextAddress() override {}
|
||||
|
||||
private:
|
||||
int currentSample_ = 0;
|
||||
// Just the current decoded frame, in order to be able to cut off the first part of it
|
||||
// to write the initial partial frame.
|
||||
// Does not need to be saved.
|
||||
int16_t *decodeTemp_ = nullptr;
|
||||
};
|
||||
|
|
|
@ -58,7 +58,7 @@ struct SceAtracIdInfo {
|
|||
u32_le endSample; // 4
|
||||
u32_le loopStart; // 8
|
||||
u32_le loopEnd; // 12
|
||||
s32_le samplesPerChan; // 16
|
||||
s32_le samplesPerChan; // 16 // This rather seems to be the number of skipped samples at the start. (plus one frame?)
|
||||
char numFrame; // 20
|
||||
// 2: all the stream data on the buffer
|
||||
// 6: looping -> second buffer needed
|
||||
|
@ -79,7 +79,7 @@ struct SceAtracIdInfo {
|
|||
u32_le bufferByte; // 64
|
||||
u32_le secondBufferByte; // 68
|
||||
// make sure the size is 128
|
||||
u8 unk[52];
|
||||
u32_le unk[13];
|
||||
u32_le atracID;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue