looper/backends/playback/gme/gme_backend.cpp
Zachary Hall c2a971d225
Some checks failed
Build / download-system-deps (push) Successful in 5m0s
Build / build-gentoo (push) Failing after 14s
Build / get-source-code (push) Successful in 12m59s
Build / build-deb (push) Failing after 5m28s
Build / build-appimage (push) Successful in 4m46s
Build / build-android (push) Failing after 3m22s
Build / build-windows (push) Failing after 7m54s
Use system game-music-emu
2025-01-18 09:59:06 -08:00

123 lines
3.5 KiB
C++

#include "gme_backend.hpp"
#include <algorithm>
#include <ipc/common.pb.h>
#include <exception>
#include <filesystem>
#include "file_backend.hpp"
#include <stddef.h>
#include <string.h>
#include <file_backend.hpp>
#include <util.hpp>
#include <license.hpp>
#include <assets/assets.h>
#include <limits.h>
#include <gme/gme.h>
void GmeBackend::load(const char *filename) {
memset(&spec, 0, sizeof(spec));
current_file = filename;
spec.format = AUDIO_S16SYS;
spec.samples = 100;
spec.channels = 2;
spec.freq = 48000;
spec.size = 100 * 2 * sizeof(int16_t);
gme_open_file(filename, &gme_backend, spec.freq);
if (gme_backend == NULL) {
throw std::exception();
}
int track_count = gme_track_count(gme_backend);
streams.clear();
for (int i = 0; i < track_count; i++) {
gme_info_t *info;
gme_track_info(gme_backend, &info, i);
PlaybackStream stream;
if (info->song[0] == '\0') {
stream.name = fmt::format("Song {}", i);
} else {
stream.name = info->song;
}
stream.length = ((double)info->length) / 1000.0;
if (stream.length < 0.0) stream.length = 0.0;
stream.id = i;
streams.push_back(stream);
gme_free_info(info);
}
}
extern SDL_AudioSpec obtained;
void GmeBackend::switch_stream(int idx) {
if (gme_backend == NULL) {
throw std::exception();
}
if (idx > streams.size()) {
throw std::exception();
}
gme_start_track(gme_backend, idx);
gme_info_t *info;
gme_track_info(gme_backend, &info, idx);
if (info->length < 0) {
info->length = 0;
}
uint64_t tmp = info->length;
tmp *= spec.freq;
tmp /= 1000;
this->length = tmp;
this->loop_len = info->loop_length;
this->loop_start = info->intro_length;
if (info->song[0] == '\0') {
this->current_title = {};
} else {
this->current_title = info->song;
}
gme_free_info(info);
gme_ignore_silence(gme_backend, true);
open = true;
}
void GmeBackend::cleanup() {
gme_delete(gme_backend);
gme_backend = NULL;
streams.clear();
}
size_t GmeBackend::render(void *buf, size_t maxlen) {
if (gme_backend == NULL) return 0;
const char *err;
size_t sample_type_len = 4;
maxlen /= sample_type_len;
if (err = gme_play(gme_backend, maxlen * 2, (short*)buf)) {
ERROR.writefln("Failed to play audio: %s", err);
return 0;
}
int pos_samples = gme_tell_samples(gme_backend);
int loop_end = loop_len + loop_start;
uint64_t loop_end_samples = loop_end;
loop_end_samples *= spec.freq;
loop_end_samples /= 1000;
uint64_t loop_start_samples = loop_start;
loop_start_samples *= spec.freq;
loop_start_samples /= 1000;
if (pos_samples >= loop_end_samples || gme_track_ended(gme_backend)) {
gme_seek_samples(gme_backend, loop_start_samples + (pos_samples - loop_end_samples));
}
maxlen *= sample_type_len;
return maxlen;
}
uint64_t GmeBackend::get_min_samples() {
return spec.size;
}
std::optional<uint64_t> GmeBackend::get_max_samples() {
return get_min_samples();
}
void GmeBackend::seek_samples(uint64_t position) {
gme_seek_samples(gme_backend, position);
}
uint64_t GmeBackend::get_position_samples() {
return gme_tell_samples(gme_backend);
}
int GmeBackend::get_stream_idx() {
return streamidx;
}
void GmeBackend::add_licenses() {
auto &license_data = get_license_data();
auto gme = LicenseData("gme", "lgpl-2.1");
LOAD_LICENSE(gme, lgpl_2_1);
license_data.insert(gme);
}