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