Skip to content

Commit

Permalink
Port emulation of The Voice
Browse files Browse the repository at this point in the history
Standalone O2EM can emulate The Voice expansion module using wav sound
samples that the user must place in a specific folder, similarly to
what happens with the bios. The libretro port of O2EM, however, didn't
include The Voice support, as the corresponding code was simply
disabled.

This commit ports The Voice emulation to work in a libretro context,
using libretro-common's own mixer to load and play the sound samples,
which should be placed in a 'voice' folder under the usual 'System'
folder.
  • Loading branch information
gdeOo committed May 22, 2021
1 parent b333353 commit 82b4313
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 124 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ WARNINGS := -Wall \
-fno-strict-overflow
endif

FLAGS += -D__LIBRETRO__ $(WARNINGS)
FLAGS += -D__LIBRETRO__ -DHAVE_RWAV $(WARNINGS)

CFLAGS += $(FLAGS)

Expand Down
22 changes: 21 additions & 1 deletion Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,27 @@ SOURCES_C := \
$(CORE_DIR)/src/vkeyb/ui.c \
$(CORE_DIR)/src/vkeyb/vkeyb.c \
$(CORE_DIR)/src/vkeyb/vkeyb_config.c \
$(CORE_DIR)/src/vkeyb/vkeyb_layout.c
$(CORE_DIR)/src/vkeyb/vkeyb_layout.c \
$(LIBRETRO_COMM_DIR)/audio/audio_mixer.c \
$(LIBRETRO_COMM_DIR)/audio/conversion/float_to_s16.c \
$(LIBRETRO_COMM_DIR)/audio/resampler/audio_resampler.c \
$(LIBRETRO_COMM_DIR)/audio/resampler/drivers/sinc_resampler.c \
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
$(LIBRETRO_COMM_DIR)/features/features_cpu.c \
$(LIBRETRO_COMM_DIR)/file/config_file.c \
$(LIBRETRO_COMM_DIR)/file/config_file_userdata.c \
$(LIBRETRO_COMM_DIR)/file/file_path.c \
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
$(LIBRETRO_COMM_DIR)/formats/wav/rwav.c \
$(LIBRETRO_COMM_DIR)/lists/string_list.c \
$(LIBRETRO_COMM_DIR)/memmap/memalign.c \
$(LIBRETRO_COMM_DIR)/streams/file_stream.c \
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
$(LIBRETRO_COMM_DIR)/time/rtime.c \
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c

ifeq ($(DEBUG),1)
SOURCES_C += $(CORE_DIR)/src/debug.c
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ libretro-o2em

Port of O2EM to libretro.

Place "o2rom.bin" (required) in your RetroArch/libretro "System Directory" folder.
Place "o2rom.bin" (required) in your RetroArch/libretro "System Directory" folder.

If you wish to use The Voice emulation, unzip the voice samples into a folder named "voice" under your RetroArch/libretro "System Directory" folder. There are two sets of voice samples: mainsamp.zip, which are the main voice samples, and sidsamp.zip which are the samples used by the game Sid the Spellbinder. You only need the latter if you want voice in that specific game.
45 changes: 34 additions & 11 deletions libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@

#include "wrapalleg.h"

#include <audio/audio_mixer.h>
#include <audio/conversion/float_to_s16.h>
#include <file/file_path.h>
#include <retro_miscellaneous.h>

static retro_log_printf_t log_cb;
static retro_video_refresh_t video_cb;
static retro_input_poll_t input_poll_cb;
Expand Down Expand Up @@ -110,7 +115,7 @@ struct ButtonsState
// Last state of the buttons for joypad 1
struct ButtonsState last_btn_state = { false, false, false, false,
false, false,
false, false };
false, false };

void retro_set_environment(retro_environment_t cb)
{
Expand Down Expand Up @@ -613,6 +618,22 @@ static void upate_audio(void)
}
}

if (get_voice_status())
{
float fbuf[SOUND_BUFFER_LEN * 2 * sizeof(float)];
int16_t ibuf[SOUND_BUFFER_LEN * 2 * sizeof(int16_t)];

memset(fbuf, 0, length * 2 * sizeof(float));
audio_mixer_mix(fbuf, length, audio_volume / 100.0, true);
convert_float_to_s16(ibuf, fbuf, length * 2);

for (int i = 0; i < length; i++)
{
audioOutBuffer[i*2] += ibuf[i*2];
audioOutBuffer[i*2 + 1] += ibuf[i*2 + 1];
}
}

audio_batch_cb(audioOutBuffer, length);
}

Expand Down Expand Up @@ -895,7 +916,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code)

bool retro_load_game(const struct retro_game_info *info)
{
char bios_file_path[256];
char bios_file_path[PATH_MAX_LENGTH];
const char *full_path, *system_directory_c;
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
struct retro_input_descriptor desc[] = {
Expand Down Expand Up @@ -952,14 +973,7 @@ bool retro_load_game(const struct retro_game_info *info)
}
else
{
#ifdef _WIN32
char slash = '\\';
#else
char slash = '/';
#endif

snprintf(bios_file_path, sizeof(bios_file_path), "%s%c%s", system_directory_c, slash, bios_file);

fill_pathname_join(bios_file_path, system_directory_c, bios_file, PATH_MAX_LENGTH);
if (!does_file_exist(bios_file_path))
{
if (log_cb)
Expand Down Expand Up @@ -1022,7 +1036,14 @@ bool retro_load_game(const struct retro_game_info *info)
if (!load_cart(full_path))
return false;

//if (app_data.voice) load_voice_samples(path2);
if (app_data.voice)
{
audio_mixer_init(44100);

char voice_path[PATH_MAX_LENGTH];
fill_pathname_join(voice_path, system_directory_c, "voice", PATH_MAX_LENGTH);
init_voice(voice_path);
}

init_display();

Expand Down Expand Up @@ -1275,6 +1296,8 @@ void retro_deinit(void)
free(mbmp_prev);
mbmp_prev = NULL;
}

audio_mixer_done();
}

void retro_reset(void)
Expand Down

0 comments on commit 82b4313

Please sign in to comment.