From 1f0fc09294155ee3bb584c8654bb58d7a201671b Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 10 Aug 2024 13:11:16 +0900 Subject: [PATCH] Implement SoundFilePlayer HLL Using this, Widenyo plays user-provided BGM files in the SaveData/MusicData directory. --- include/audio.h | 4 +- include/mixer.h | 1 + src/audio.c | 16 +++++- src/audio_mixer.c | 58 ++++++++++++++----- src/hll/SoundFilePlayer.c | 118 +++++++++++++++++++++++++++++++------- subprojects/libsys4 | 2 +- 6 files changed, 158 insertions(+), 41 deletions(-) diff --git a/include/audio.h b/include/audio.h index 257361e..23bc1d5 100644 --- a/include/audio.h +++ b/include/audio.h @@ -80,8 +80,8 @@ int wav_get_time_length(int id); int bgm_get_time_length(int id); int wav_get_group_num(int id); //int bgm_get_group_num(int id); -//int wav_prepare_from_file(int id, char *filename); -//int bgm_prepare_from_file(int id, char *filename); +int wav_prepare_from_file(int id, char *filename); +int bgm_prepare_from_file(int id, char *filename); int wav_get_group_num_from_data_num(int no); diff --git a/include/mixer.h b/include/mixer.h index d73509f..e9149a1 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -61,6 +61,7 @@ enum asset_type; struct channel *channel_open(enum asset_type type, int no); // Takes ownership of dfile. struct channel *channel_open_archive_data(struct archive_data *dfile); +struct channel *channel_open_file(const char *path); void channel_close(struct channel *ch); int channel_play(struct channel *ch); int channel_stop(struct channel *ch); diff --git a/src/audio.c b/src/audio.c index 6d0d320..fee9b48 100644 --- a/src/audio.c +++ b/src/audio.c @@ -377,8 +377,20 @@ int wav_get_group_num(int id) return wav_get_group_num_from_data_num(no); } //int bgm_get_group_num(int channel); -//int wav_prepare_from_file(int channel, char *filename); -//int bgm_prepare_from_file(int channel, char *filename); + +static int audio_prepare_from_file(struct id_pool *pool, int id, char *filename) +{ + if (id < 0) + return 0; + struct channel *ch = channel_open_file(filename); + struct channel *old = id_pool_set(pool, id, ch); + if (old) + channel_close(old); + return !!ch; +} + +int wav_prepare_from_file(int id, char *filename) { return audio_prepare_from_file(&wav, id, filename); } +int bgm_prepare_from_file(int id, char *filename) { return audio_prepare_from_file(&bgm, id, filename); } static int audio_prepare_from_archive_data(struct id_pool *pool, int id, struct archive_data *dfile) { diff --git a/src/audio_mixer.c b/src/audio_mixer.c index b644f41..4d90a09 100644 --- a/src/audio_mixer.c +++ b/src/audio_mixer.c @@ -22,6 +22,7 @@ #include "system4.h" #include "system4/archive.h" +#include "system4/utfsjis.h" #include "asset_manager.h" #include "audio.h" @@ -534,20 +535,15 @@ struct channel *channel_open(enum asset_type type, int no) return ch; } -struct channel *channel_open_archive_data(struct archive_data *dfile) +static bool init_channel(struct channel *ch) { - struct channel *ch = xcalloc(1, sizeof(struct channel)); - ch->dfile = dfile; - - // open file - ch->file = sf_open_virtual(&channel_vio, SFM_READ, &ch->info, ch); if (sf_error(ch->file) != SF_ERR_NO_ERROR) { WARNING("sf_open_virtual failed: %s", sf_strerror(ch->file)); - goto error; + return false; } if (ch->info.channels > 2) { WARNING("Audio file has more than 2 channels"); - goto error; + return false; } // create stream @@ -566,19 +562,53 @@ struct channel *channel_open_archive_data(struct archive_data *dfile) ch->mixer_no = 0; ch->no = -1; - return ch; + return true; +} -error: - archive_free_data(dfile); - free(ch); - return NULL; +struct channel *channel_open_archive_data(struct archive_data *dfile) +{ + struct channel *ch = xcalloc(1, sizeof(struct channel)); + ch->dfile = dfile; + + // open file + ch->file = sf_open_virtual(&channel_vio, SFM_READ, &ch->info, ch); + + if (!init_channel(ch)) { + archive_free_data(dfile); + if (ch->file) + sf_close(ch->file); + free(ch); + return NULL; + } + return ch; +} + +struct channel *channel_open_file(const char *path) +{ + struct channel *ch = xcalloc(1, sizeof(struct channel)); +#ifdef _WIN32 + wchar_t *wpath = utf8_to_wchar(path); + ch->file = sf_wchar_open(wpath, SFM_READ, &ch->info); + free(wpath); +#else + ch->file = sf_open(path, SFM_READ, &ch->info); +#endif + + if (!init_channel(ch)) { + if (ch->file) + sf_close(ch->file); + free(ch); + return NULL; + } + return ch; } void channel_close(struct channel *ch) { channel_stop(ch); sf_close(ch->file); - archive_free_data(ch->dfile); + if (ch->dfile) + archive_free_data(ch->dfile); free(ch); } diff --git a/src/hll/SoundFilePlayer.c b/src/hll/SoundFilePlayer.c index b21f6e4..aa76777 100644 --- a/src/hll/SoundFilePlayer.c +++ b/src/hll/SoundFilePlayer.c @@ -14,30 +14,104 @@ * along with this program; if not, see . */ -#include "hll.h" +#include -//bool SoundFilePlayer_Load(struct string *FileName); -//void SoundFilePlayer_Release(void); -//bool SoundFilePlayer_Play(int PlayCount); -HLL_WARN_UNIMPLEMENTED(false, bool, SoundFilePlayer, Stop, void); -//bool SoundFilePlayer_IsPlay(void); -//int SoundFilePlayer_GetDuration(void); -//int SoundFilePlayer_GetPosition(void); -//bool SoundFilePlayer_BeginFadeVolume(int Volume, int Time); -//bool SoundFilePlayer_StopFadeVolume(void); -//bool SoundFilePlayer_IsFadeVolume(void); -//bool SoundFilePlayer_Update(void); +#include "system4/string.h" + +#include "audio.h" +#include "hll.h" +#include "xsystem4.h" + +static int channel = -1; + +static bool SoundFilePlayer_Load(struct string *file_name) +{ + if (channel >= 0) + bgm_unprepare(channel); + + channel = bgm_get_unused_channel(); + char *path = unix_path(file_name->text); + if (!bgm_prepare_from_file(channel, path)) { + WARNING("Cannot load %s", display_utf0(path)); + channel = -1; + } + free(path); + return channel >= 0; +} + +static void SoundFilePlayer_Release(void) +{ + if (channel >= 0) { + bgm_unprepare(channel); + channel = -1; + } +} + +static bool SoundFilePlayer_Play(int play_count) +{ + if (channel < 0) + return false; + bgm_set_loop_count(channel, play_count); + bgm_play(channel); + return true; +} + +static bool SoundFilePlayer_Stop(void) +{ + if (channel < 0) + return false; + bgm_stop(channel); + return true; +} + +static bool SoundFilePlayer_IsPlay(void) +{ + return channel >= 0 && bgm_is_playing(channel); +} + +static int SoundFilePlayer_GetDuration(void) +{ + return channel >= 0 ? bgm_get_length(channel) : 0; +} + +static int SoundFilePlayer_GetPosition(void) +{ + return channel >= 0 ? bgm_get_pos(channel) : 0; +} + +static bool SoundFilePlayer_BeginFadeVolume(int volume, int time) +{ + if (channel < 0) + return false; + bgm_fade(channel, time, volume, false); + return true; +} + +static bool SoundFilePlayer_StopFadeVolume(void) +{ + if (channel < 0) + return false; + bgm_stop_fade(channel); + return true; +} + +static bool SoundFilePlayer_IsFadeVolume(void) +{ + return channel >= 0 && bgm_is_fading(channel); +} + +HLL_QUIET_UNIMPLEMENTED(true, bool, SoundFilePlayer, Update, void); HLL_LIBRARY(SoundFilePlayer, - HLL_TODO_EXPORT(Load, SoundFilePlayer_Load), - HLL_TODO_EXPORT(Release, SoundFilePlayer_Release), - HLL_TODO_EXPORT(Play, SoundFilePlayer_Play), + HLL_EXPORT(Load, SoundFilePlayer_Load), + HLL_EXPORT(Release, SoundFilePlayer_Release), + HLL_EXPORT(Play, SoundFilePlayer_Play), HLL_EXPORT(Stop, SoundFilePlayer_Stop), - HLL_TODO_EXPORT(IsPlay, SoundFilePlayer_IsPlay), - HLL_TODO_EXPORT(GetDuration, SoundFilePlayer_GetDuration), - HLL_TODO_EXPORT(GetPosition, SoundFilePlayer_GetPosition), - HLL_TODO_EXPORT(BeginFadeVolume, SoundFilePlayer_BeginFadeVolume), - HLL_TODO_EXPORT(StopFadeVolume, SoundFilePlayer_StopFadeVolume), - HLL_TODO_EXPORT(IsFadeVolume, SoundFilePlayer_IsFadeVolume), - HLL_TODO_EXPORT(Update, SoundFilePlayer_Update) + HLL_EXPORT(IsPlay, SoundFilePlayer_IsPlay), + HLL_EXPORT(GetDuration, SoundFilePlayer_GetDuration), + HLL_EXPORT(GetPosition, SoundFilePlayer_GetPosition), + HLL_EXPORT(BeginFadeVolume, SoundFilePlayer_BeginFadeVolume), + HLL_EXPORT(StopFadeVolume, SoundFilePlayer_StopFadeVolume), + HLL_EXPORT(IsFadeVolume, SoundFilePlayer_IsFadeVolume), + HLL_EXPORT(Update, SoundFilePlayer_Update) ); diff --git a/subprojects/libsys4 b/subprojects/libsys4 index a0e8e61..07efd63 160000 --- a/subprojects/libsys4 +++ b/subprojects/libsys4 @@ -1 +1 @@ -Subproject commit a0e8e6142fa92d1d3b2ddd1d68492db65034ef28 +Subproject commit 07efd63c62a74ecde8145bf0084bc9e9dfa8c476