looper/backends/playback/sdl_mixer_x/sdl_mixer_x.cpp

107 lines
3.2 KiB
C++
Raw Normal View History

2024-08-08 13:12:37 -07:00
#include "sdl_mixer_x.hpp"
#include <filesystem>
#include "file_backend.hpp"
#include <stddef.h>
2024-09-16 15:05:53 -07:00
#include <log.hpp>
2024-08-08 13:12:37 -07:00
#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);
}
}
2024-09-16 15:05:53 -07:00
DEBUG.writefln("Opening file: %s", filename);
2024-08-08 13:12:37 -07:00
file = open_file(filename);
2024-09-16 15:05:53 -07:00
DEBUG.writeln("Loading file...");
2024-08-08 13:12:37 -07:00
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;
}