Merge pull request #19062 from hrydgard/atrac-fix-mono-output

Fix mono output from Atrac decoders. (sceAtrac*MOut* functions)
This commit is contained in:
Henrik Rydgård 2024-04-15 12:23:00 +02:00 committed by GitHub
commit c782d54464
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 32 additions and 19 deletions

View file

@ -831,7 +831,7 @@ void Atrac::SeekToSample(int sample) {
const u32 start = off - track_.dataOff < backfill ? track_.dataOff : off - backfill;
for (u32 pos = start; pos < off; pos += track_.bytesPerFrame) {
decoder_->Decode(BufferStart() + pos, track_.bytesPerFrame, nullptr, nullptr, nullptr);
decoder_->Decode(BufferStart() + pos, track_.bytesPerFrame, nullptr, 2, nullptr, nullptr);
}
}
@ -933,7 +933,7 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i
uint8_t *indata = BufferStart() + off;
int bytesConsumed = 0;
int outBytes = 0;
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outbuf, &outBytes)) {
if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, outbuf, &outBytes)) {
// Decode failed.
*SamplesNum = 0;
*finish = 1;

View file

@ -948,7 +948,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo
int bytesConsumed = 0;
int bytesWritten = 0;
atrac->GetDecoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, outp, &bytesWritten);
atrac->GetDecoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, 2, outp, &bytesWritten);
*srcConsumed = bytesConsumed;
*outWritten = bytesWritten;

View file

@ -119,7 +119,7 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
auto ctx = PSPPointer<AudioCodecContext>::Create(ctxPtr); // On stack, no need to allocate.
// Decode audio
int inDataConsumed = 0;
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes);
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, 2, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes);
}
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
return 0;

View file

@ -744,7 +744,7 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed
int outpcmbytes = 0;
int inbytesConsumed = 0;
ctx->decoder->Decode(inbuff, 4096, &inbytesConsumed, outbuff, &outpcmbytes);
ctx->decoder->Decode(inbuff, 4096, &inbytesConsumed, 2, outbuff, &outpcmbytes);
NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode");
Memory::Write_U32(inbytesConsumed, sourceBytesConsumedAddr);

View file

@ -15,7 +15,8 @@ inline int16_t clamp16(float f) {
// Test case for ATRAC3: Mega Man Maverick Hunter X, PSP menu sound
class Atrac3Audio : public AudioDecoder {
public:
Atrac3Audio(PSPAudioType audioType, int channels, size_t blockAlign, const uint8_t *extraData, size_t extraDataSize) : audioType_(audioType) {
Atrac3Audio(PSPAudioType audioType, int channels, size_t blockAlign, const uint8_t *extraData, size_t extraDataSize)
: audioType_(audioType), channels_(channels) {
blockAlign_ = (int)blockAlign;
if (audioType == PSP_CODEC_AT3PLUS) {
at3pCtx_ = atrac3p_alloc(channels, &blockAlign_);
@ -55,7 +56,7 @@ public:
}
}
bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override {
bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override {
if (!codecOpen_) {
_dbg_assert_(false);
}
@ -84,12 +85,20 @@ public:
*outbytes = nb_samples * 2 * 2;
}
if (outbuf) {
// Convert frame to outbuf. TODO: Very SIMDable, though hardly hot.
for (int channel = 0; channel < 2; channel++) {
int16_t *output = (int16_t *)outbuf;
_dbg_assert_(outputChannels == 1 || outputChannels == 2);
int16_t *output = (int16_t *)outbuf;
const float *left = buffers_[0];
if (outputChannels == 2) {
// Stereo output, standard.
const float *right = channels_ == 2 ? buffers_[1] : buffers_[0];
for (int i = 0; i < nb_samples; i++) {
output[i * 2] = clamp16(buffers_[0][i]);
output[i * 2 + 1] = clamp16(buffers_[1][i]);
output[i * 2] = clamp16(left[i]);
output[i * 2 + 1] = clamp16(right[i]);
}
} else {
// Mono output, just take the left channel.
for (int i = 0; i < nb_samples; i++) {
output[i] = clamp16(left[i]);
}
}
}
@ -113,6 +122,7 @@ private:
ATRAC3PContext *at3pCtx_ = nullptr;
ATRAC3Context *at3Ctx_ = nullptr;
int channels_ = 0;
int blockAlign_ = 0;
int outSamples_ = 0;

View file

@ -1078,7 +1078,7 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) {
}
int inbytesConsumed = 0;
if (!m_audioContext->Decode(audioFrame, frameSize, &inbytesConsumed, buffer, &outbytes)) {
if (!m_audioContext->Decode(audioFrame, frameSize, &inbytesConsumed, 2, buffer, &outbytes)) {
ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType));
}

View file

@ -67,7 +67,9 @@ public:
}
~MiniMp3Audio() {}
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override {
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override {
_dbg_assert_(outputChannels == 2);
mp3dec_frame_info_t info{};
int samplesWritten = mp3dec_decode_frame(&mp3_, inbuf, inbytes, (mp3d_sample_t *)outbuf, &info);
*inbytesConsumed = info.frame_bytes;
@ -101,7 +103,7 @@ public:
FFmpegAudioDecoder(PSPAudioType audioType, int sampleRateHz = 44100, int channels = 2);
~FFmpegAudioDecoder();
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) override;
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override;
bool IsOK() const override {
#ifdef USE_FFMPEG
return codec_ != 0;
@ -264,7 +266,7 @@ FFmpegAudioDecoder::~FFmpegAudioDecoder() {
}
// Decodes a single input frame.
bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) {
bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) {
#ifdef USE_FFMPEG
if (!codecOpen_) {
OpenCodec(inbytes);
@ -315,6 +317,7 @@ bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesC
if (got_frame) {
// Initializing the sample rate convert. We will use it to convert float output into int.
_dbg_assert_(outputChannels == 2);
int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout
int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout
@ -436,7 +439,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr) {
nextSync = (int)FindNextMp3Sync();
}
int inbytesConsumed = 0;
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, outbuf, &outpcmbufsize);
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, 2, outbuf, &outpcmbufsize);
if (outpcmbufsize == 0) {
// Nothing was output, hopefully we're at the end of the stream.

View file

@ -37,7 +37,7 @@ public:
virtual PSPAudioType GetAudioType() const = 0;
// inbytesConsumed can include skipping metadata.
virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, uint8_t *outbuf, int *outbytes) = 0;
virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) = 0;
virtual bool IsOK() const = 0;
// These two are only ever called after Decode, so can initialize on first.

View file

@ -219,7 +219,7 @@ public:
while (bgQueue.size() < (size_t)(len * 2)) {
int outBytes = 0;
int inbytesConsumed = 0;
decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, &inbytesConsumed, (uint8_t *)buffer_, &outBytes);
decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, &inbytesConsumed, 2, (uint8_t *)buffer_, &outBytes);
if (!outBytes)
return false;