Implement playing sound effects in libretro builds

This commit is contained in:
刘皓 2025-02-05 12:36:45 -05:00
parent 1c4d65e02e
commit 8ed8c5c984
No known key found for this signature in database
GPG key ID: 7901753DB465B711
5 changed files with 181 additions and 17 deletions

View file

@ -36,21 +36,37 @@ namespace mkxp_sandbox {
wasm_ptr_t filename;
int32_t volume;
int32_t pitch;
double pos;
int32_t track;
bool have_track;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
volume = 100;
pitch = 100;
pos = 0.0;
have_track = false;
SANDBOX_AWAIT_AND_SET(filename, rb_string_value_cstr, (VALUE *)(**sb() + argv));
if (argc >= 2) {
SANDBOX_AWAIT_AND_SET(volume, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
if (argc >= 3) {
SANDBOX_AWAIT_AND_SET(pitch, rb_num2int, ((VALUE *)(**sb() + argv))[2]);
if (argc >= 4) {
SANDBOX_AWAIT_AND_SET(pos, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]);
if (argc >= 5) {
SANDBOX_AWAIT_AND_SET(track, rb_num2int, ((VALUE *)(**sb() + argv))[4]);
have_track = true;
}
}
}
}
mkxp_retro::audio->bgmPlay((const char *)(**sb() + filename), volume, pitch);
if (have_track) {
mkxp_retro::audio->bgmPlay((const char *)(**sb() + filename), volume, pitch, pos, track);
} else {
mkxp_retro::audio->bgmPlay((const char *)(**sb() + filename), volume, pitch, pos);
}
}
return SANDBOX_NIL;
@ -65,6 +81,113 @@ namespace mkxp_sandbox {
return SANDBOX_NIL;
}
static VALUE bgs_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
wasm_ptr_t filename;
int32_t volume;
int32_t pitch;
double pos;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
volume = 100;
pitch = 100;
pos = 0.0;
SANDBOX_AWAIT_AND_SET(filename, rb_string_value_cstr, (VALUE *)(**sb() + argv));
if (argc >= 2) {
SANDBOX_AWAIT_AND_SET(volume, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
if (argc >= 3) {
SANDBOX_AWAIT_AND_SET(pitch, rb_num2int, ((VALUE *)(**sb() + argv))[2]);
if (argc >= 4) {
SANDBOX_AWAIT_AND_SET(pos, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]);
}
}
}
mkxp_retro::audio->bgsPlay((const char *)(**sb() + filename), volume, pitch, pos);
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE bgs_stop(VALUE self) {
mkxp_retro::audio->bgsStop();
return SANDBOX_NIL;
}
static VALUE me_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
wasm_ptr_t filename;
int32_t volume;
int32_t pitch;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
volume = 100;
pitch = 100;
SANDBOX_AWAIT_AND_SET(filename, rb_string_value_cstr, (VALUE *)(**sb() + argv));
if (argc >= 2) {
SANDBOX_AWAIT_AND_SET(volume, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
if (argc >= 3) {
SANDBOX_AWAIT_AND_SET(pitch, rb_num2int, ((VALUE *)(**sb() + argv))[2]);
}
}
mkxp_retro::audio->mePlay((const char *)(**sb() + filename), volume, pitch);
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE me_stop(VALUE self) {
mkxp_retro::audio->meStop();
return SANDBOX_NIL;
}
static VALUE se_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_COROUTINE(coro,
wasm_ptr_t filename;
int32_t volume;
int32_t pitch;
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
volume = 100;
pitch = 100;
SANDBOX_AWAIT_AND_SET(filename, rb_string_value_cstr, (VALUE *)(**sb() + argv));
if (argc >= 2) {
SANDBOX_AWAIT_AND_SET(volume, rb_num2int, ((VALUE *)(**sb() + argv))[1]);
if (argc >= 3) {
SANDBOX_AWAIT_AND_SET(pitch, rb_num2int, ((VALUE *)(**sb() + argv))[2]);
}
}
mkxp_retro::audio->sePlay((const char *)(**sb() + filename), volume, pitch);
}
return SANDBOX_NIL;
}
)
return sb()->bind<struct coro>()()(argc, argv, self);
}
static VALUE se_stop(VALUE self) {
mkxp_retro::audio->seStop();
return SANDBOX_NIL;
}
VALUE module;
void operator()() {
@ -76,15 +199,15 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_pos", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_volume", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgm_set_volume", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_play", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_stop", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_play", (VALUE (*)(ANYARGS))bgs_play, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_stop", (VALUE (*)(ANYARGS))bgs_stop, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_fade", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "bgs_pos", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "me_play", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "me_stop", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "me_play", (VALUE (*)(ANYARGS))me_play, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "me_stop", (VALUE (*)(ANYARGS))me_stop, 0);
SANDBOX_AWAIT(rb_define_module_function, module, "me_fade", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "se_play", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "se_stop", (VALUE (*)(ANYARGS))todo, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "se_play", (VALUE (*)(ANYARGS))se_play, -1);
SANDBOX_AWAIT(rb_define_module_function, module, "se_stop", (VALUE (*)(ANYARGS))se_stop, 0);
}
}
)

View file

@ -44,9 +44,9 @@ struct AudioPrivate
AudioStream bgs;
AudioStream me;
#ifndef MKXPZ_RETRO
SoundEmitter se;
#ifndef MKXPZ_RETRO
SyncPoint &syncPoint;
#endif // MKXPZ_RETRO
@ -429,16 +429,12 @@ void Audio::sePlay(const char *filename,
int volume,
int pitch)
{
#ifndef MKXPZ_RETRO
p->se.play(filename, volume, pitch);
#endif // MKXPZ_RETRO
}
void Audio::seStop()
{
#ifndef MKXPZ_RETRO
p->se.stop();
#endif // MKXPZ_RETRO
}
void Audio::setupMidi()

View file

@ -26,7 +26,7 @@
#include <vector>
#include <sndfile.hh>
static SF_VIRTUAL_IO sfvirtual = {
SF_VIRTUAL_IO sfvirtual = {
.get_filelen = [](void *handle) {
#ifdef MKXPZ_RETRO
PHYSFS_Stat stat;

View file

@ -28,7 +28,9 @@
#include "util.h"
#include "debugwriter.h"
#ifndef MKXPZ_RETRO
#ifdef MKXPZ_RETRO
# include <sndfile.hh>
#else
# include <SDL_sound.h>
#endif // MKXPZ_RETRO
@ -90,9 +92,17 @@ arrayPushBack(std::vector<size_t> &array, size_t size, size_t index)
array[size-1] = v;
}
#ifdef MKXPZ_RETRO
SoundEmitter::SoundEmitter()
#else
SoundEmitter::SoundEmitter(const Config &conf)
#endif // MKXPZ_RETRO
: bufferBytes(0),
#ifdef MKXPZ_RETRO
srcCount(6), // TODO: get from config
#else
srcCount(conf.SE.sourceCount),
#endif // MKXPZ_RETRO
alSrcs(srcCount),
atchBufs(srcCount),
srcPrio(srcCount)
@ -202,29 +212,60 @@ struct SoundOpenHandler : FileSystem::OpenHandler
#endif // MKXPZ_RETRO
const char *ext
) {
#ifndef MKXPZ_RETRO
#ifdef MKXPZ_RETRO
extern SF_VIRTUAL_IO sfvirtual;
SndfileHandle handle(sfvirtual, ops.get());
#else
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
#endif // MKXPZ_RETRO
#ifdef MKXPZ_RETRO
if (handle.error())
#else
if (!sample)
#endif // MKXPZ_RETRO
{
#ifndef MKXPZ_RETRO
SDL_RWclose(&ops);
#endif // MKXPZ_RETRO
return false;
}
/* Do all of the decoding in the handler so we don't have
* to keep the source ops around */
#ifdef MKXPZ_RETRO
uint8_t sampleSize = 2;
uint32_t sampleCount = handle.frames();
#else
uint32_t decBytes = Sound_DecodeAll(sample);
uint8_t sampleSize = formatSampleSize(sample->actual.format);
uint32_t sampleCount = decBytes / sampleSize;
#endif // MKXPZ_RETRO
buffer = new SoundBuffer;
buffer->bytes = sampleSize * sampleCount;
ALenum alFormat = chooseALFormat(sampleSize, sample->actual.channels);
ALenum alFormat = chooseALFormat(
sampleSize,
#ifdef MKXPZ_RETRO
handle.channels()
#else
sample->actual.channels
#endif // MKXPZ_RETRO
);
#ifdef MKXPZ_RETRO
int16_t *buf = (int16_t *)std::malloc(buffer->bytes);
if (buf == NULL) {
return false;
}
handle.read(buf, sampleCount);
AL::Buffer::uploadData(buffer->alBuffer, alFormat, buf,
buffer->bytes, handle.samplerate());
std::free(buf);
#else
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sample->buffer,
buffer->bytes, sample->actual.rate);
Sound_FreeSample(sample);
#endif // MKXPZ_RETRO

View file

@ -49,7 +49,11 @@ struct SoundEmitter
/* Indices of sources, sorted by priority (lowest first) */
std::vector<size_t> srcPrio;
#ifdef MKXPZ_RETRO
SoundEmitter();
#else
SoundEmitter(const Config &conf);
#endif // MKXPZ_RETRO
~SoundEmitter();
void play(const std::string &filename,