Implement ChrLoader.LoadWavFile

This commit is contained in:
kichikuou
2022-03-25 10:49:25 +09:00
parent ba1dcd6e21
commit f725e4e830
5 changed files with 98 additions and 32 deletions
+5
View File
@@ -79,4 +79,9 @@ int bgm_get_time_length(int id);
//int wav_prepare_from_file(int id, char *filename);
//int bgm_prepare_from_file(int id, char *filename);
struct archive_data;
// Takes ownership of dfile.
int wav_prepare_from_archive_data(int id, struct archive_data *dfile);
#endif /* SYSTEM4_AUDIO_H */
+3
View File
@@ -48,10 +48,13 @@ int mixer_set_volume(int n, int volume);
int mixer_get_mute(int n, int *mute);
int mixer_set_mute(int n, int mute);
struct archive_data;
struct channel;
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);
void channel_close(struct channel *ch);
int channel_play(struct channel *ch);
int channel_stop(struct channel *ch);
+15
View File
@@ -329,3 +329,18 @@ int bgm_get_time_length(int id) { return audio_get_time_length(&bgm, id); }
//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_archive_data(struct id_pool *pool, int id, struct archive_data *dfile)
{
if (id < 0)
return 0;
struct channel *ch = channel_open_archive_data(dfile);
struct channel *old = id_pool_set(pool, id, ch);
if (old)
channel_close(old);
return !!ch;
}
int wav_prepare_from_archive_data(int id, struct archive_data *dfile) {
return audio_prepare_from_archive_data(&wav, id, dfile);
}
+43 -31
View File
@@ -465,34 +465,18 @@ static SF_VIRTUAL_IO channel_vio = {
struct channel *channel_open(enum asset_type type, int no)
{
struct channel *ch = xcalloc(1, sizeof(struct channel));
// get file from archive
ch->dfile = asset_get(type, no-1);
if (!ch->dfile) {
struct archive_data *dfile = asset_get(type, no-1);
if (!dfile) {
WARNING("Failed to load %s %d", type == ASSET_SOUND ? "WAV" : "BGM", no);
goto error;
return NULL;
}
// open file
ch->file = sf_open_virtual(&channel_vio, SFM_READ, &ch->info, ch);
if (sf_error(ch->file) != SF_ERR_NO_ERROR) {
WARNING("Failed to open %s %d: %s", type == ASSET_SOUND ? "WAV" : "BGM", no, sf_strerror(ch->file));
goto error;
struct channel *ch = channel_open_archive_data(dfile);
if (!ch) {
WARNING("Failed to open %s %d", type == ASSET_SOUND ? "WAV" : "BGM", no);
return NULL;
}
if (ch->info.channels > 2) {
WARNING("Audio file has more than 2 channels: %s %d", type == ASSET_SOUND ? "WAV" : "BGM", no);
goto error;
}
// create stream
ch->stream.userdata = ch;
ch->stream.callback = refill_stream;
ch->stream.sample.frequency = ch->info.samplerate;
ch->stream.sample.audio_format = STS_MIXER_SAMPLE_FORMAT_FLOAT;
ch->stream.sample.length = CHUNK_SIZE * 2;
ch->stream.sample.data = ch->data;
ch->voice = -1;
if (type == ASSET_SOUND) {
struct wai *wai = wai_get(no);
@@ -509,21 +493,49 @@ struct channel *channel_open(enum asset_type type, int no)
ch->loop_end = clamp(0, ch->info.frames, bgi->loop_end);
ch->loop_count = max(0, bgi->loop_count);
ch->mixer_no = clamp(0, nr_mixers, bgi->channel);
} else {
ch->volume = 100;
ch->loop_start = 0;
ch->loop_end = ch->info.frames;
ch->loop_count = 0;
ch->mixer_no = 0;
}
}
ch->no = no;
return ch;
}
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 (sf_error(ch->file) != SF_ERR_NO_ERROR) {
WARNING("sf_open_virtual failed: %s", sf_strerror(ch->file));
goto error;
}
if (ch->info.channels > 2) {
WARNING("Audio file has more than 2 channels");
goto error;
}
// create stream
ch->stream.userdata = ch;
ch->stream.callback = refill_stream;
ch->stream.sample.frequency = ch->info.samplerate;
ch->stream.sample.audio_format = STS_MIXER_SAMPLE_FORMAT_FLOAT;
ch->stream.sample.length = CHUNK_SIZE * 2;
ch->stream.sample.data = ch->data;
ch->voice = -1;
ch->volume = 100;
ch->loop_start = 0;
ch->loop_end = ch->info.frames;
ch->loop_count = 0;
ch->mixer_no = 0;
ch->no = -1;
return ch;
error:
if (ch->dfile)
archive_free_data(ch->dfile);
archive_free_data(dfile);
free(ch);
return NULL;
}
+32 -1
View File
@@ -18,6 +18,8 @@
#include <stdlib.h>
#include <string.h>
#include "system4.h"
#include "system4/archive.h"
#include "system4/cg.h"
#include "system4/file.h"
#include "system4/hashtable.h"
@@ -25,6 +27,7 @@
#include "system4/string.h"
#include "little_endian.h"
#include "audio.h"
#include "sact.h"
#include "xsystem4.h"
@@ -146,7 +149,35 @@ static bool ChrLoader_LoadCG(int sprite, int x, int y, int id, int type)
return true;
}
HLL_WARN_UNIMPLEMENTED(false, bool, ChrLoader, LoadWavFile, int nSoundChannel, int nID);
static void chr_archive_free_data(struct archive_data *data) { /* no-op */ }
static struct archive_ops chr_archive_ops = {
.free_data = chr_archive_free_data
};
static struct archive chr_archive = { .mmapped = false, .ops = &chr_archive_ops };
static bool ChrLoader_LoadWavFile(int sound_channel, int id)
{
uint8_t *data = chr_get(id);
if (!data)
return false;
size_t offset = LittleEndian_getDW(data, is_enemy(data) ? 36 : 44);
size_t size = LittleEndian_getDW(data, is_enemy(data) ? 40 : 48);
struct archive_data *dfile = xcalloc(1, sizeof(struct archive_data));
dfile->size = size;
dfile->data = data + offset;
dfile->no = id;
dfile->archive = &chr_archive;
if (!wav_prepare_from_archive_data(sound_channel, dfile)) {
WARNING("ChrLoader.LoadWavFile %d failed", id);
return false;
}
return true;
}
static bool ChrLoader_LoadSentence(int id, int type, struct string **msg)
{