103 lines
3.1 KiB
C++
103 lines
3.1 KiB
C++
#include "sdl_mixer_x.hpp"
|
|
#include <filesystem>
|
|
#include "file_backend.hpp"
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
std::optional<uint64_t> SDLMixerXBackend::get_max_samples() {
|
|
return 100;
|
|
}
|
|
void SDLMixerXBackend::load(const char *filename) {
|
|
Mix_Init(MIX_INIT_FLAC|MIX_INIT_MID|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_OPUS|MIX_INIT_WAVPACK);
|
|
memset(&spec, 0, sizeof(spec));
|
|
spec.callback = NULL;
|
|
spec.channels = 2;
|
|
spec.format = AUDIO_F32SYS;
|
|
spec.freq = 48000;
|
|
spec.samples = get_max_samples().value();
|
|
spec.size = spec.samples * sizeof(float);
|
|
Mix_InitMixer(&spec, SDL_FALSE);
|
|
mixer = Mix_GetGeneralMixer();
|
|
{
|
|
std::filesystem::path fpath = std::string(filename);
|
|
fpath = fpath.parent_path() / fpath.stem();
|
|
|
|
std::string fpath_str = fpath.string();
|
|
std::vector<std::string> soundfonts = {fpath_str + ".sf2", fpath_str + ".dls"};
|
|
std::string sf_path_str = "";
|
|
bool any_path_exists = false;
|
|
for (auto sf_path : soundfonts) {
|
|
if (std::filesystem::exists(sf_path)) {
|
|
any_path_exists = true;
|
|
sf_path_str += ";" + sf_path;
|
|
}
|
|
}
|
|
if (any_path_exists) {
|
|
sf_path_str = sf_path_str.substr(1);
|
|
Mix_SetSoundFonts(sf_path_str.c_str());
|
|
} else {
|
|
Mix_SetSoundFonts(NULL);
|
|
}
|
|
}
|
|
file = open_file(filename);
|
|
Mix_Music *output = Mix_LoadMUS_RW(get_sdl_file(this->file), 0);
|
|
if (output == nullptr) {
|
|
throw std::exception();
|
|
}
|
|
Mix_PlayMusicStream(output, -1);
|
|
length = Mix_MusicDuration(output);
|
|
current_file = std::string(filename);
|
|
const char *title_tag = Mix_GetMusicTitleTag(output);
|
|
// Check for an empty string, which indicates there's no title tag.
|
|
if (title_tag[0] == '\0') {
|
|
std::filesystem::path path(current_file);
|
|
current_title = path.stem().string();
|
|
} else {
|
|
current_title = std::string(title_tag);
|
|
}
|
|
this->music = output;
|
|
streams.clear();
|
|
PlaybackStream stream;
|
|
stream.id = 0;
|
|
stream.length = Mix_MusicDuration(output);
|
|
stream.name = current_title;
|
|
streams.push_back(stream);
|
|
open = true;
|
|
}
|
|
void SDLMixerXBackend::switch_stream(int idx) { }
|
|
void SDLMixerXBackend::seek(double position) {
|
|
if (music == nullptr || file == nullptr) {
|
|
open = false;
|
|
return;
|
|
}
|
|
Mix_SetMusicPositionStream(music, position);
|
|
}
|
|
size_t SDLMixerXBackend::render(void *buf, size_t maxlen) {
|
|
if (music == nullptr || file == nullptr) {
|
|
open = false;
|
|
return 0;
|
|
}
|
|
if (maxlen > spec.size) {
|
|
maxlen = spec.size;
|
|
}
|
|
// Remove partial sample frames.
|
|
maxlen /= sizeof(float);
|
|
maxlen *= sizeof(float);
|
|
mixer(NULL, (Uint8*)buf, maxlen);
|
|
return maxlen;
|
|
}
|
|
double SDLMixerXBackend::get_position() {
|
|
if (music == nullptr || file == nullptr) {
|
|
open = false;
|
|
return 0.0;
|
|
}
|
|
return Mix_GetMusicPosition(music);
|
|
}
|
|
void SDLMixerXBackend::cleanup() {
|
|
streams.clear();
|
|
Mix_HaltMusicStream(music);
|
|
Mix_FreeMusic(music);
|
|
delete file;
|
|
file = nullptr;
|
|
Mix_Quit();
|
|
open = false;
|
|
}
|