nvm fuck libxm, fuck msvc, fuck bill gates and fuck (You)

This commit is contained in:
2025-11-11 22:01:30 -05:00
parent 7ab7ed3ee2
commit 0ce567c282
10 changed files with 30357 additions and 1947 deletions

View File

@@ -1,24 +1,10 @@
#include "audio.h"
#include <SDL3/SDL_properties.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <utility>
#include <vector>
#include <xm.h>
namespace anm2ed::resource
{
namespace
{
constexpr int XM_SAMPLE_RATE_ = 44100;
constexpr uint16_t XM_CHUNK_FRAMES = 1024;
constexpr int XM_MAX_SECONDS = 600;
constexpr int XM_CHANNELS = 2;
}
MIX_Mixer* Audio::mixer_get()
{
static auto mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr);
@@ -32,67 +18,9 @@ namespace anm2ed::resource
Audio::Audio(const unsigned char* data, size_t size)
{
if (!data || size == 0) return;
auto is_chunk_silent = [](const float* samples, size_t count)
{
constexpr float epsilon = 1e-6f;
for (size_t i = 0; i < count; ++i)
if (std::fabs(samples[i]) > epsilon) return false;
return true;
};
auto prescanStorage = std::make_unique<unsigned char[]>(XM_PRESCAN_DATA_SIZE);
auto prescan = (xm_prescan_data_t*)prescanStorage.get();
if (!xm_prescan_module((const char*)data, (uint32_t)size, prescan)) return;
const auto contextSize = static_cast<size_t>(xm_size_for_context(prescan));
auto pool = std::make_unique<char[]>(contextSize);
auto context = xm_create_context(pool.get(), prescan, (const char*)data, (uint32_t)size);
if (!context) return;
xm_set_sample_rate(context, (uint16_t)XM_SAMPLE_RATE_);
xm_set_max_loop_count(context, 1);
auto pcm = std::vector<float>{};
pcm.reserve(static_cast<size_t>(XM_CHUNK_FRAMES) * XM_CHANNELS * 8);
size_t framesGenerated = 0;
const auto maxFrames = static_cast<size_t>(XM_SAMPLE_RATE_) * XM_MAX_SECONDS;
auto heardAudio = false;
while (framesGenerated < maxFrames)
{
auto framesThisPass = (uint16_t)std::min<size_t>(XM_CHUNK_FRAMES, maxFrames - framesGenerated);
auto offset = pcm.size();
pcm.resize(offset + framesThisPass * XM_CHANNELS);
auto* chunkStart = pcm.data() + offset;
xm_generate_samples(context, chunkStart, framesThisPass);
framesGenerated += framesThisPass;
auto chunkSamples = (size_t)framesThisPass * XM_CHANNELS;
auto chunkSilent = is_chunk_silent(chunkStart, chunkSamples);
if (!chunkSilent)
{
heardAudio = true;
}
else if (heardAudio)
{
pcm.resize(offset);
break;
}
if (xm_get_loop_count(context) > 0) break;
}
if (pcm.empty()) return;
auto spec = SDL_AudioSpec{};
spec.freq = XM_SAMPLE_RATE_;
spec.format = SDL_AUDIO_F32;
spec.channels = XM_CHANNELS;
internal = MIX_LoadRawAudio(nullptr, pcm.data(), pcm.size() * sizeof(float), &spec);
SDL_IOStream* io = SDL_IOFromConstMem(data, size);
if (!io) return;
internal = MIX_LoadAudio_IO(mixer_get(), io, true, true);
}
void Audio::unload()