mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Remove minimp3
MP3 emulation already went through FFmpeg, leaving MiniMp3Audio dead. The one live user was loading MP3 UI sound effects (custom achievement sounds), which now splits the file into frames and decodes them with the FFmpeg MP3 decoder. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
87ad32d578
commit
761e2f3706
15 files changed
+115
-3397
No files matched your search
@@ -365,7 +365,6 @@
|
||||
<ClInclude Include="..\ext\lzma-sdk\LzmaDec.h" />
|
||||
<ClInclude Include="..\ext\lzma-sdk\Precomp.h" />
|
||||
<ClInclude Include="..\ext\lzma-sdk\RotateDefs.h" />
|
||||
<ClInclude Include="..\ext\minimp3\minimp3.h" />
|
||||
<ClInclude Include="..\ext\naett-lib\naett.h" />
|
||||
<ClInclude Include="..\ext\naett-lib\src\naett_internal.h" />
|
||||
<ClInclude Include="..\ext\nanosvg\src\nanosvg.h" />
|
||||
@@ -867,7 +866,6 @@
|
||||
<ClCompile Include="..\ext\lzma-sdk\Delta.c" />
|
||||
<ClCompile Include="..\ext\lzma-sdk\Lzma2Dec.c" />
|
||||
<ClCompile Include="..\ext\lzma-sdk\LzmaDec.c" />
|
||||
<ClCompile Include="..\ext\minimp3\minimp3.cpp" />
|
||||
<ClCompile Include="..\ext\naett-lib\src\naett_core.c" />
|
||||
<ClCompile Include="..\ext\naett-lib\src\naett_win.c" />
|
||||
<ClCompile Include="..\ext\pugixml\pugixml.cpp" />
|
||||
|
||||
@@ -515,9 +515,6 @@
|
||||
<ClInclude Include="Math\CrossSIMD.h">
|
||||
<Filter>Math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\minimp3\minimp3.h">
|
||||
<Filter>ext\minimp3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\at3_standalone\atrac3data.h">
|
||||
<Filter>ext\at3_standalone</Filter>
|
||||
</ClInclude>
|
||||
@@ -1246,9 +1243,6 @@
|
||||
<ClCompile Include="GPU\Vulkan\VulkanDescSet.cpp">
|
||||
<Filter>GPU\Vulkan</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ext\minimp3\minimp3.cpp">
|
||||
<Filter>ext\minimp3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ext\at3_standalone\atrac3.cpp">
|
||||
<Filter>ext\at3_standalone</Filter>
|
||||
</ClCompile>
|
||||
@@ -1588,9 +1582,6 @@
|
||||
<Filter Include="ext\libchdr">
|
||||
<UniqueIdentifier>{b681797d-7747-487f-b448-5ef5b2d2805b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ext\minimp3">
|
||||
<UniqueIdentifier>{83cd76d0-d1ac-4ed1-9bdc-11fb5a20e5d3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ext\at3_standalone">
|
||||
<UniqueIdentifier>{586da66e-922a-4479-9dac-9d608a1b9183}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
+1
-1
@@ -735,7 +735,7 @@ endif()
|
||||
|
||||
list(APPEND CoreExtraLibs armips)
|
||||
|
||||
target_link_libraries(Core GPU Common chdr kirk cityhash sfmt19937 xbrz xxhash rcheevos minimp3 at3_standalone lua
|
||||
target_link_libraries(Core GPU Common chdr kirk cityhash sfmt19937 xbrz xxhash rcheevos at3_standalone lua
|
||||
aemu_postoffice_client ${CoreExtraLibs} ${CMAKE_DL_LIBS})
|
||||
|
||||
# Winsock
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "Core/HW/BufferQueue.h"
|
||||
#include "Core/HW/Atrac3Standalone.h"
|
||||
|
||||
#include "ext/minimp3/minimp3.h"
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
|
||||
extern "C" {
|
||||
@@ -59,51 +57,6 @@ extern "C" {
|
||||
// * https://github.com/meerkat-cv/h264_decoder
|
||||
// * https://github.com/shengbinmeng/ffmpeg-h264-dec
|
||||
|
||||
// minimp3-based decoder.
|
||||
class MiniMp3Audio : public AudioDecoder {
|
||||
public:
|
||||
MiniMp3Audio() {
|
||||
mp3dec_init(&mp3_);
|
||||
}
|
||||
~MiniMp3Audio() {}
|
||||
|
||||
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) override {
|
||||
_dbg_assert_(outputChannels == 2);
|
||||
|
||||
// When used from sceMp3LowLevelDecode, this fails to parse the mp3 header!
|
||||
// It's because minimp3 is a bit more sensitive than ffmpeg - if you give it a buffer that's larger than the frame size,
|
||||
// it'll check that there's a second matching frame before accepting. But in our case we only get one frame,
|
||||
// but we do not know the size. So this might need some modifications in minimp3.
|
||||
mp3dec_frame_info_t info{};
|
||||
int samplesWritten = mp3dec_decode_frame(&mp3_, inbuf, inbytes, (mp3d_sample_t *)temp_, &info);
|
||||
_dbg_assert_(samplesWritten <= MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||
_dbg_assert_(info.channels <= 2);
|
||||
if (info.channels == 1) {
|
||||
for (int i = 0; i < samplesWritten; i++) {
|
||||
outbuf[i * 2] = temp_[i];
|
||||
outbuf[i * 2 + 1] = temp_[i];
|
||||
}
|
||||
} else {
|
||||
memcpy(outbuf, temp_, 4 * samplesWritten);
|
||||
}
|
||||
*inbytesConsumed = info.frame_bytes;
|
||||
*outSamples = samplesWritten;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsOK() const override { return true; }
|
||||
void SetChannels(int channels) override {
|
||||
// Hmm. ignore for now.
|
||||
}
|
||||
|
||||
PSPAudioType GetAudioType() const override { return PSP_CODEC_MP3; }
|
||||
|
||||
private:
|
||||
// We use the lowest-level API.
|
||||
mp3dec_t mp3_{};
|
||||
int16_t temp_[MINIMP3_MAX_SAMPLES_PER_FRAME]{};
|
||||
};
|
||||
|
||||
// FFMPEG-based decoder. TODO: Replace with individual codecs.
|
||||
// Based on http://ffmpeg.org/doxygen/trunk/doc_2examples_2decoding_encoding_8c-example.html#_a13
|
||||
class FFmpegAudioDecoder : public AudioDecoder {
|
||||
@@ -150,13 +103,6 @@ AudioDecoder *CreateAudioDecoder(PSPAudioType audioType, int sampleRateHz, int c
|
||||
}
|
||||
|
||||
switch (audioType) {
|
||||
// Our MiniMP3 backend has too many issues:
|
||||
// * Doesn't accept sample rate
|
||||
// * Doesn't accept data where there's only one valid frame if the buffer is bigger.
|
||||
// This prevents sceMp3LowLevelDecode from working, since nothing passes us the frame size.
|
||||
//
|
||||
// case PSP_CODEC_MP3:
|
||||
// return new MiniMp3Audio();
|
||||
case PSP_CODEC_AT3:
|
||||
return CreateAtrac3Audio(channels, blockAlign, extraData, extraDataSize);
|
||||
case PSP_CODEC_AT3PLUS:
|
||||
|
||||
+114
-21
@@ -1,9 +1,8 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ext/minimp3/minimp3_ex.h"
|
||||
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/UI/Root.h"
|
||||
|
||||
@@ -434,6 +433,114 @@ inline int16_t ConvertU8ToI16(uint8_t value) {
|
||||
return ivalue * 255;
|
||||
}
|
||||
|
||||
// Returns the size of the MPEG-1/2/2.5 Layer III frame whose header is at p, or 0 if it isn't one.
|
||||
static int Mp3FrameSize(const uint8_t *p, int *sampleRate) {
|
||||
if (p[0] != 0xFF || (p[1] & 0xE0) != 0xE0 || (p[1] & 0x06) != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
static const int bitratesV1[16] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
|
||||
static const int bitratesV2[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 };
|
||||
static const int sampleRatesV1[4] = { 44100, 48000, 32000, 0 };
|
||||
const int version = (p[1] >> 3) & 3; // 3 = MPEG-1, 2 = MPEG-2, 0 = MPEG-2.5.
|
||||
if (version == 1) {
|
||||
return 0;
|
||||
}
|
||||
const int bitrate = (version == 3 ? bitratesV1 : bitratesV2)[p[2] >> 4] * 1000;
|
||||
int rate = sampleRatesV1[(p[2] >> 2) & 3];
|
||||
if (!bitrate || !rate) {
|
||||
return 0;
|
||||
}
|
||||
rate >>= (version == 3 ? 0 : (version == 2 ? 1 : 2));
|
||||
*sampleRate = rate;
|
||||
const int padding = (p[2] >> 1) & 1;
|
||||
return (version == 3 ? 144 : 72) * bitrate / rate + padding;
|
||||
}
|
||||
|
||||
// Checks for a Xing/Info frame, which some encoders put first. If it carries a LAME tag,
|
||||
// also returns the samples to trim from the start and end of the decoded stream.
|
||||
static bool ParseXingFrame(const uint8_t *p, int frameSize, int *delay, int *padding) {
|
||||
const int version = (p[1] >> 3) & 3;
|
||||
const bool mono = (p[3] >> 6) == 3;
|
||||
const int sideInfoSize = version == 3 ? (mono ? 17 : 32) : (mono ? 9 : 17);
|
||||
const int tagPos = 4 + sideInfoSize;
|
||||
if (tagPos + 8 > frameSize || (memcmp(p + tagPos, "Xing", 4) && memcmp(p + tagPos, "Info", 4))) {
|
||||
return false;
|
||||
}
|
||||
const uint8_t flags = p[tagPos + 7];
|
||||
// Skip the optional frame count, byte count, seek table and quality fields.
|
||||
static const int fieldSizes[4] = { 4, 4, 100, 4 };
|
||||
int lamePos = tagPos + 8;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (flags & (1 << i)) {
|
||||
lamePos += fieldSizes[i];
|
||||
}
|
||||
}
|
||||
if (lamePos + 24 <= frameSize && (!memcmp(p + lamePos, "LAME", 4) || !memcmp(p + lamePos, "Lav", 3))) {
|
||||
const uint8_t *t = p + lamePos + 21;
|
||||
// The decoder adds 529 samples of its own delay (and so drops them from the padding).
|
||||
const int decoderDelay = 529;
|
||||
*delay = ((t[0] << 4) | (t[1] >> 4)) + decoderDelay;
|
||||
*padding = std::max(0, (((t[1] & 0xF) << 8) | t[2]) - decoderDelay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Sample *LoadMp3(const uint8_t *data, size_t size) {
|
||||
size_t pos = 0;
|
||||
// Skip an ID3v2 tag.
|
||||
if (size >= 10 && !memcmp(data, "ID3", 3)) {
|
||||
pos = 10 + (((data[6] & 0x7F) << 21) | ((data[7] & 0x7F) << 14) | ((data[8] & 0x7F) << 7) | (data[9] & 0x7F));
|
||||
if (data[5] & 0x10) {
|
||||
pos += 10; // Footer.
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> decoder;
|
||||
std::vector<int16_t> samples;
|
||||
int16_t frameBuf[1152 * 2];
|
||||
int sampleRate = 0;
|
||||
int delay = 0;
|
||||
int padding = 0;
|
||||
while (pos + 4 <= size) {
|
||||
int frameRate = 0;
|
||||
int frameSize = Mp3FrameSize(data + pos, &frameRate);
|
||||
if (frameSize == 0 || pos + frameSize > size) {
|
||||
// Resync, byte by byte.
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (!decoder) {
|
||||
sampleRate = frameRate;
|
||||
decoder.reset(CreateAudioDecoder(PSP_CODEC_MP3, sampleRate, 2));
|
||||
if (ParseXingFrame(data + pos, frameSize, &delay, &padding)) {
|
||||
// It decodes to silence.
|
||||
pos += frameSize;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int consumed = 0;
|
||||
int outSamples = 0;
|
||||
if (frameRate == sampleRate && decoder->Decode(data + pos, frameSize, &consumed, 2, frameBuf, &outSamples)) {
|
||||
samples.insert(samples.end(), frameBuf, frameBuf + outSamples * 2);
|
||||
}
|
||||
pos += frameSize;
|
||||
}
|
||||
|
||||
// Trim the encoder delay and padding, in stereo frames.
|
||||
const size_t trim = (size_t)(delay + padding) * 2;
|
||||
if (samples.size() > trim) {
|
||||
samples.erase(samples.end() - padding * 2, samples.end());
|
||||
samples.erase(samples.begin(), samples.begin() + delay * 2);
|
||||
}
|
||||
|
||||
if (samples.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
int16_t *sampleData = new int16_t[samples.size()];
|
||||
memcpy(sampleData, samples.data(), samples.size() * sizeof(int16_t));
|
||||
return new Sample(sampleData, 2, (int)samples.size() / 2, sampleRate);
|
||||
}
|
||||
|
||||
Sample *Sample::Load(const std::string &path) {
|
||||
size_t data_size = 0;
|
||||
uint8_t *data = g_VFS.ReadFile(path.c_str(), &data_size);
|
||||
@@ -442,7 +549,6 @@ Sample *Sample::Load(const std::string &path) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *mp3_magic = "ID3\03";
|
||||
const char *wav_magic = "RIFF";
|
||||
if (!memcmp(data, wav_magic, 4)) {
|
||||
RIFFReader reader(data, (int)data_size);
|
||||
@@ -476,25 +582,12 @@ Sample *Sample::Load(const std::string &path) {
|
||||
return new Sample(samples, wave.num_channels, actualFrames, wave.sample_rate);
|
||||
}
|
||||
|
||||
// Something else.
|
||||
// Let's see if minimp3 can read it.
|
||||
mp3dec_t mp3d;
|
||||
mp3dec_init(&mp3d);
|
||||
mp3dec_file_info_t mp3_info;
|
||||
int retval = mp3dec_load_buf(&mp3d, data, data_size, &mp3_info, nullptr, nullptr);
|
||||
|
||||
if (retval < 0 || mp3_info.samples == 0) {
|
||||
ERROR_LOG(Log::Audio, "Couldn't load MP3 for sound effect from %s", path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// mp3_info contains the decoded data.
|
||||
int16_t *sample_data = new int16_t[mp3_info.samples];
|
||||
memcpy(sample_data, mp3_info.buffer, mp3_info.samples * sizeof(int16_t));
|
||||
|
||||
Sample *sample = new Sample(sample_data, mp3_info.channels, (int)mp3_info.samples / mp3_info.channels, mp3_info.hz);
|
||||
free(mp3_info.buffer);
|
||||
// Something else, try MP3.
|
||||
Sample *sample = LoadMp3(data, data_size);
|
||||
delete[] data;
|
||||
if (!sample) {
|
||||
ERROR_LOG(Log::Audio, "Couldn't load MP3 for sound effect from %s", path.c_str());
|
||||
}
|
||||
return sample;
|
||||
}
|
||||
|
||||
|
||||
@@ -717,7 +717,6 @@ void CreditsScroller::Draw(UIContext &dc) {
|
||||
"zstd",
|
||||
"glew",
|
||||
"libchdr",
|
||||
"minimp3",
|
||||
"xxhash",
|
||||
"naett-http",
|
||||
"PSP SDK",
|
||||
|
||||
@@ -291,8 +291,6 @@
|
||||
<ClInclude Include="..\..\ext\lzma-sdk\LzmaDec.h" />
|
||||
<ClInclude Include="..\..\ext\lzma-sdk\Precomp.h" />
|
||||
<ClInclude Include="..\..\ext\lzma-sdk\RotateDefs.h" />
|
||||
<ClInclude Include="..\..\ext\minimp3\minimp3.h" />
|
||||
<ClInclude Include="..\..\ext\minimp3\minimp3_ex.h" />
|
||||
<ClInclude Include="..\..\ext\naett-lib\naett.h" />
|
||||
<ClInclude Include="..\..\ext\naett-lib\src\naett_internal.h" />
|
||||
<ClInclude Include="..\..\ext\pugixml\pugiconfig.hpp" />
|
||||
@@ -476,7 +474,6 @@
|
||||
<ClCompile Include="..\..\ext\lzma-sdk\Delta.c" />
|
||||
<ClCompile Include="..\..\ext\lzma-sdk\Lzma2Dec.c" />
|
||||
<ClCompile Include="..\..\ext\lzma-sdk\LzmaDec.c" />
|
||||
<ClCompile Include="..\..\ext\minimp3\minimp3.cpp" />
|
||||
<ClCompile Include="..\..\ext\naett-lib\src\naett_core.c" />
|
||||
<ClCompile Include="..\..\ext\naett-lib\src\naett_win.c" />
|
||||
<ClCompile Include="..\..\ext\pugixml\pugixml.cpp" />
|
||||
|
||||
@@ -97,9 +97,6 @@
|
||||
<Filter Include="ext\naett-lib">
|
||||
<UniqueIdentifier>{403c3154-5e8a-4da1-ba82-8f69bef25e14}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ext\minimp3">
|
||||
<UniqueIdentifier>{7b5c3ddc-225d-48d5-a829-9a1e71e304be}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ext\at3_standalone">
|
||||
<UniqueIdentifier>{47e3b9c8-3a5f-4c78-b62b-3fa65bf23594}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -473,9 +470,6 @@
|
||||
<ClCompile Include="..\..\ext\naett-lib\src\naett_win.c">
|
||||
<Filter>ext\naett-lib</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\minimp3\minimp3.cpp">
|
||||
<Filter>ext\minimp3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\at3_standalone\atrac.cpp">
|
||||
<Filter>ext\at3_standalone</Filter>
|
||||
</ClCompile>
|
||||
@@ -1006,12 +1000,6 @@
|
||||
<ClInclude Include="..\..\Common\Math\CrossSIMD.h">
|
||||
<Filter>Math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\minimp3\minimp3.h">
|
||||
<Filter>ext\minimp3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\minimp3\minimp3_ex.h">
|
||||
<Filter>ext\minimp3</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\at3_standalone\aac_defines.h">
|
||||
<Filter>ext\at3_standalone</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -168,9 +168,6 @@ NAETT_FILES := \
|
||||
${SRC}/ext/naett-lib/src/naett_core.c \
|
||||
${SRC}/ext/naett-lib/src/naett_android.c
|
||||
|
||||
MINIMP3_FILES := \
|
||||
${SRC}/ext/minimp3/minimp3.cpp
|
||||
|
||||
AT3_STANDALONE_FILES := \
|
||||
${SRC}/ext/at3_standalone/atrac.cpp \
|
||||
${SRC}/ext/at3_standalone/atrac3.cpp \
|
||||
@@ -306,7 +303,6 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SPIRV_CROSS_FILES) \
|
||||
$(RCHEEVOS_FILES) \
|
||||
$(NAETT_FILES) \
|
||||
$(MINIMP3_FILES) \
|
||||
$(AT3_STANDALONE_FILES) \
|
||||
$(EXT_FILES) \
|
||||
$(NATIVE_FILES) \
|
||||
|
||||
@@ -31,7 +31,6 @@ set(ENABLE_GLSLANG_INSTALL OFF)
|
||||
add_subdirectory(glslang EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(snappy)
|
||||
add_subdirectory(lua-build)
|
||||
add_subdirectory(minimp3)
|
||||
add_subdirectory(at3_standalone)
|
||||
add_subdirectory(udis86)
|
||||
add_subdirectory(SPIRV-Cross-build)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
cmake_minimum_required (VERSION 3.16)
|
||||
project (minimp3)
|
||||
|
||||
set(SRC_DIR .)
|
||||
|
||||
# format
|
||||
set(ALL_SOURCE_FILES
|
||||
# rapi
|
||||
${SRC_DIR}/minimp3.cpp
|
||||
)
|
||||
|
||||
add_library(minimp3 STATIC ${ALL_SOURCE_FILES})
|
||||
@@ -1,11 +0,0 @@
|
||||
// Gotta define it somewhere.
|
||||
#define MINIMP3_IMPLEMENTATION
|
||||
#define MINIMP3_NO_STDIO
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4267)
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
#include "minimp3.h"
|
||||
#include "minimp3_ex.h"
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -25,7 +25,6 @@ INCFLAGS += \
|
||||
-I$(EXTDIR)/glslang \
|
||||
-I$(EXTDIR)/glslang-build \
|
||||
-I$(EXTDIR)/native \
|
||||
-I$(EXTDIR)/minimp3 \
|
||||
-I$(EXTDIR)/zlib \
|
||||
-I$(EXTDIR)/cpu_features/include \
|
||||
-I$(ZSTDDIR) \
|
||||
@@ -174,9 +173,6 @@ endif
|
||||
|
||||
SOURCES_C += $(LIBRETRODIR)/ext/glew/glew.c
|
||||
|
||||
SOURCES_CXX += \
|
||||
$(EXTDIR)/minimp3/minimp3.cpp
|
||||
|
||||
SOURCES_C += \
|
||||
$(EXTDIR)/libkirk/AES.c \
|
||||
$(EXTDIR)/libkirk/amctrl.c \
|
||||
|
||||
Reference in new issue
Block a user