mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-09 15:20:01 +03:00
Implement ChrLoader.LoadWavFile
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user