From 1b366afa35c7465243d03805fc5d734b0846fc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Apr 2024 15:31:11 +0200 Subject: [PATCH] Refactor: Change *outBytes to *outSamples in AudioDecoder::Decode. --- Core/HLE/AtracCtx.cpp | 7 +++--- Core/HLE/sceAtrac.cpp | 7 +++--- Core/HLE/sceAudiocodec.cpp | 4 ++-- Core/HLE/sceMp3.cpp | 13 ++++++----- Core/HW/Atrac3Standalone.cpp | 28 ++++++++++------------- Core/HW/MediaEngine.cpp | 9 ++++---- Core/HW/SimpleAudioDec.cpp | 43 ++++++++++++++---------------------- Core/HW/SimpleAudioDec.h | 7 ++---- UI/BackgroundAudio.cpp | 7 +++--- 9 files changed, 57 insertions(+), 68 deletions(-) diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index d8a2725e1a..d871e39164 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -949,16 +949,17 @@ u32 Atrac::DecodeData(u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u32 *finish, i if (off < first_.size) { uint8_t *indata = BufferStart() + off; int bytesConsumed = 0; - int outBytes = 0; - if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, outbuf, &outBytes)) { + int outSamples = 0; + if (!decoder_->Decode(indata, track_.bytesPerFrame, &bytesConsumed, outputChannels_, (int16_t *)outbuf, &outSamples)) { // Decode failed. *SamplesNum = 0; *finish = 1; return ATRAC_ERROR_ALL_DATA_DECODED; } + int outBytes = outSamples * outputChannels_ * sizeof(int16_t); gotFrame = true; - numSamples = outBytes / 4; + numSamples = outSamples; uint32_t packetAddr = CurBufferAddress(-skipSamples); // got a frame int skipped = std::min((u32)skipSamples, numSamples); diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 15513b031d..2002895974 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -944,7 +944,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedAddr, u32 samplesAddr, u32 sampleBytesAddr) { auto srcp = PSPPointer::Create(sourceAddr); auto srcConsumed = PSPPointer::Create(sourceBytesConsumedAddr); - auto outp = PSPPointer::Create(samplesAddr); + auto outp = PSPPointer::Create(samplesAddr); auto outWritten = PSPPointer::Create(sampleBytesAddr); AtracBase *atrac = getAtrac(atracID); @@ -958,8 +958,9 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo } int bytesConsumed = 0; - int bytesWritten = 0; - atrac->Decoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, 2, outp, &bytesWritten); + int outSamples = 0; + atrac->Decoder()->Decode(srcp, atrac->GetTrack().BytesPerFrame(), &bytesConsumed, 2, outp, &outSamples); + int bytesWritten = outSamples * 2 * sizeof(int16_t); *srcConsumed = bytesConsumed; *outWritten = bytesWritten; diff --git a/Core/HLE/sceAudiocodec.cpp b/Core/HLE/sceAudiocodec.cpp index 7361468063..7676593630 100644 --- a/Core/HLE/sceAudiocodec.cpp +++ b/Core/HLE/sceAudiocodec.cpp @@ -102,7 +102,6 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) { } if (IsValidCodec(audioType)){ - int outbytes = 0; // find a decoder in audioList auto decoder = findDecoder(ctxPtr); @@ -119,7 +118,8 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) { auto ctx = PSPPointer::Create(ctxPtr); // On stack, no need to allocate. // Decode audio int inDataConsumed = 0; - decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, 2, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes); + int outSamples = 0; + decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, 2, (int16_t *)Memory::GetPointerWrite(ctx->outDataPtr), &outSamples); } DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec)); return 0; diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index 1b337e800f..f364acd80f 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -739,16 +739,17 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed return -1; } - auto inbuff = Memory::GetPointerWriteUnchecked(sourceAddr); - auto outbuff = Memory::GetPointerWriteUnchecked(samplesAddr); + const u8 *inbuff = Memory::GetPointerWriteUnchecked(sourceAddr); + int16_t *outbuf = (int16_t *)Memory::GetPointerWriteUnchecked(samplesAddr); - int outpcmbytes = 0; + int outSamples = 0; int inbytesConsumed = 0; - ctx->decoder->Decode(inbuff, 4096, &inbytesConsumed, 2, outbuff, &outpcmbytes); - NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode"); + ctx->decoder->Decode(inbuff, 4096, &inbytesConsumed, 2, outbuf, &outSamples); + int outBytes = outSamples * sizeof(int16_t) * 2; + NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outBytes, "Mp3LowLevelDecode"); Memory::Write_U32(inbytesConsumed, sourceBytesConsumedAddr); - Memory::Write_U32(outpcmbytes, sampleBytesAddr); + Memory::Write_U32(outBytes, sampleBytesAddr); return 0; } diff --git a/Core/HW/Atrac3Standalone.cpp b/Core/HW/Atrac3Standalone.cpp index 63845bbc37..6fb5ffc540 100644 --- a/Core/HW/Atrac3Standalone.cpp +++ b/Core/HW/Atrac3Standalone.cpp @@ -56,7 +56,7 @@ public: } } - bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override { + bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) override { if (!codecOpen_) { _dbg_assert_(false); } @@ -73,45 +73,42 @@ public: result = atrac3_decode_frame(at3Ctx_, buffers_, &nb_samples, inbuf, inbytes); } if (result < 0) { - *outbytes = 0; + if (outSamples) { + *outSamples = 0; + } return false; } if (inbytesConsumed) { *inbytesConsumed = result; } - outSamples_ = nb_samples; + if (outSamples) { + *outSamples = nb_samples; + } if (nb_samples > 0) { - if (outbytes) { - *outbytes = nb_samples * 2 * 2; + if (outSamples) { + *outSamples = nb_samples; } if (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(left[i]); - output[i * 2 + 1] = clamp16(right[i]); + outbuf[i * 2] = clamp16(left[i]); + outbuf[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]); + outbuf[i] = clamp16(left[i]); } } } - } else if (outbytes) { - *outbytes = 0; } return true; } - int GetOutSamples() const override { - return outSamples_; - } - void SetChannels(int channels) override { // Hmm. ignore for now. } @@ -125,7 +122,6 @@ private: int channels_ = 0; int blockAlign_ = 0; - int outSamples_ = 0; int srcPos_ = 0; float *buffers_[2]{}; diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index c7f89de5c4..79c52a5763 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -1054,7 +1054,7 @@ int MediaEngine::getNextAudioFrame(u8 **buf, int *headerCode1, int *headerCode2) } int MediaEngine::getAudioSamples(u32 bufferPtr) { - u8 *buffer = Memory::GetPointerWriteRange(bufferPtr, 8192); + int16_t *buffer = (int16_t *)Memory::GetPointerWriteRange(bufferPtr, 8192); if (buffer == nullptr) { ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); } @@ -1068,7 +1068,7 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) { if (frameSize == 0) { return 0; } - int outbytes = 0; + int outSamples = 0; if (m_audioContext != nullptr) { if (headerCode1 == 0x24) { @@ -1078,11 +1078,12 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) { } int inbytesConsumed = 0; - if (!m_audioContext->Decode(audioFrame, frameSize, &inbytesConsumed, 2, buffer, &outbytes)) { + if (!m_audioContext->Decode(audioFrame, frameSize, &inbytesConsumed, 2, buffer, &outSamples)) { ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType)); } + int outBytes = outSamples * sizeof(int16_t) * 2; - NotifyMemInfo(MemBlockFlags::WRITE, bufferPtr, outbytes, "VideoDecodeAudio"); + NotifyMemInfo(MemBlockFlags::WRITE, bufferPtr, outBytes, "VideoDecodeAudio"); } return 0x2000; diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index 2b7a16055f..538886cc22 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -67,22 +67,17 @@ public: } ~MiniMp3Audio() {} - bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override { + bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) 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; - *outbytes = samplesWritten * sizeof(mp3d_sample_t) * info.channels; - outSamples_ = samplesWritten * info.channels; + *outSamples = samplesWritten; return true; } bool IsOK() const override { return true; } - int GetOutSamples() const override { - return outSamples_; - } - void SetChannels(int channels) override { // Hmm. ignore for now. } @@ -92,8 +87,6 @@ public: private: // We use the lowest-level API. mp3dec_t mp3_{}; - int outSamples_ = 0; - int srcPos_ = 0; }; // FFMPEG-based decoder. TODO: Replace with individual codecs. @@ -103,7 +96,7 @@ public: FFmpegAudioDecoder(PSPAudioType audioType, int sampleRateHz = 44100, int channels = 2); ~FFmpegAudioDecoder(); - bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) override; + bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) override; bool IsOK() const override { #ifdef USE_FFMPEG return codec_ != 0; @@ -112,10 +105,6 @@ public: #endif } - int GetOutSamples() const override { - return outSamples_; - } - void SetChannels(int channels) override; // These two are only here because of save states. @@ -127,7 +116,6 @@ private: PSPAudioType audioType; int sample_rate_; int channels_; - int outSamples_ = 0; // output samples per frame AVFrame *frame_ = nullptr; AVCodec *codec_ = nullptr; @@ -266,7 +254,7 @@ FFmpegAudioDecoder::~FFmpegAudioDecoder() { } // Decodes a single input frame. -bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) { +bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) { #ifdef USE_FFMPEG if (!codecOpen_) { OpenCodec(inbytes); @@ -280,8 +268,12 @@ bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesC int got_frame = 0; av_frame_unref(frame_); - *outbytes = 0; - *inbytesConsumed = 0; + if (outSamples) { + *outSamples = 0; + } + if (inbytesConsumed) { + *inbytesConsumed = 0; + } #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) if (inbytes != 0) { int err = avcodec_send_packet(codecCtx_, &packet); @@ -344,17 +336,14 @@ bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesC // convert audio to AV_SAMPLE_FMT_S16 int swrRet = 0; if (outbuf != nullptr) { - swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples); + swrRet = swr_convert(swrCtx_, (uint8_t **)&outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples); } if (swrRet < 0) { ERROR_LOG(ME, "swr_convert: Error while converting: %d", swrRet); return false; } - // output samples per frame, we should *2 since we have two channels - outSamples_ = swrRet * 2; - - // each sample occupies 2 bytes - *outbytes = outSamples_ * 2; + // output stereo samples per frame + *outSamples = swrRet; // Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file. // SaveAudio("dump.pcm", outbuf, *outbytes); @@ -439,7 +428,9 @@ u32 AuCtx::AuDecode(u32 pcmAddr) { nextSync = (int)FindNextMp3Sync(); } int inbytesConsumed = 0; - decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, 2, outbuf, &outpcmbufsize); + int outSamples = 0; + decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, 2, (int16_t *)outbuf, &outSamples); + outpcmbufsize = outSamples * 2 * sizeof(int16_t); if (outpcmbufsize == 0) { // Nothing was output, hopefully we're at the end of the stream. @@ -447,7 +438,7 @@ u32 AuCtx::AuDecode(u32 pcmAddr) { sourcebuff.clear(); } else { // Update our total decoded samples, but don't count stereo. - SumDecodedSamples += decoder->GetOutSamples() / 2; + SumDecodedSamples += outSamples; // get consumed source length int srcPos = inbytesConsumed + nextSync; // remove the consumed source diff --git a/Core/HW/SimpleAudioDec.h b/Core/HW/SimpleAudioDec.h index ddf3d9c589..34bf3b9342 100644 --- a/Core/HW/SimpleAudioDec.h +++ b/Core/HW/SimpleAudioDec.h @@ -37,14 +37,11 @@ public: virtual PSPAudioType GetAudioType() const = 0; // inbytesConsumed can include skipping metadata. - virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, uint8_t *outbuf, int *outbytes) = 0; + // outSamples is in stereo samples. So you have to multiply by 4 for 16-bit stereo audio to get bytes. + virtual bool Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) = 0; virtual bool IsOK() const = 0; - // These two are only ever called after Decode, so can initialize on first. - virtual int GetOutSamples() const = 0; - virtual void SetChannels(int channels) = 0; - virtual void FlushBuffers() {} // Just metadata. diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index 2f6c7ea3f7..100c79d66d 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -217,11 +217,12 @@ public: return false; while (bgQueue.size() < (size_t)(len * 2)) { - int outBytes = 0; + int outSamples = 0; int inbytesConsumed = 0; - decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, &inbytesConsumed, 2, (uint8_t *)buffer_, &outBytes); - if (!outBytes) + bool result = decoder_->Decode(wave_.raw_data + raw_offset_, wave_.raw_bytes_per_frame, &inbytesConsumed, 2, (int16_t *)buffer_, &outSamples); + if (!result || !outSamples) return false; + int outBytes = outSamples * 2 * sizeof(int16_t); if (wave_.raw_offset_loop_end != 0 && raw_offset_ == wave_.raw_offset_loop_end) { // Only take the remaining bytes, but convert to stereo s16.