diff --git a/src/vgmstream.c b/src/vgmstream.c index 5eddf2d4..1ffe7afc 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -1068,15 +1068,14 @@ int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double } } -/* Decode data into sample buffer. Controls the "external" part of the decoding, - * while layouts control the "internal" part. */ -void render_vgmstream(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream) { +void render_vgmstream_internal(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { + switch (vgmstream->layout_type) { case layout_interleave: - render_vgmstream_interleave(buffer,sample_count,vgmstream); + render_vgmstream_interleave(buf, sample_count, vgmstream); break; case layout_none: - render_vgmstream_flat(buffer,sample_count,vgmstream); + render_vgmstream_flat(buf, sample_count, vgmstream); break; case layout_blocked_mxch: case layout_blocked_ast: @@ -1118,19 +1117,45 @@ void render_vgmstream(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstre case layout_blocked_vs_square: case layout_blocked_vid1: case layout_blocked_ubi_sce: - render_vgmstream_blocked(buffer,sample_count,vgmstream); + render_vgmstream_blocked(buf, sample_count, vgmstream); break; case layout_segmented: - render_vgmstream_segmented(buffer,sample_count,vgmstream); + render_vgmstream_segmented(buf, sample_count,vgmstream); break; case layout_layered: - render_vgmstream_layered(buffer,sample_count,vgmstream); + render_vgmstream_layered(buf, sample_count, vgmstream); break; default: break; } - mix_vgmstream(buffer, sample_count, vgmstream); + + mix_vgmstream(buf, sample_count, vgmstream); +} + +/* Decode data into sample buffer. Controls the "external" part of the decoding, + * while layouts control the "internal" part. */ +void render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { + + + render_vgmstream_internal(buf, sample_count, vgmstream); + + if (vgmstream->config_set) + fade_vgmstream(vgmstream, buf, sample_count); + + //todo silence if position > and not loop forever + + if (vgmstream->config_set) { + vgmstream->pstate.play_position += sample_count; + + if (vgmstream->pstate.play_position > vgmstream->pstate.play_duration) { + //if (!vgmstream->config.play_forever) { + // memset(...); + //} + vgmstream->pstate.play_position = vgmstream->pstate.play_duration; + } + } + } @@ -2544,6 +2569,18 @@ void describe_vgmstream(VGMSTREAM* vgmstream, char* desc, int length) { snprintf(temp,TEMPSIZE, "stream name: %s\n", vgmstream->stream_name); concatn(length,desc,temp); } + + if (vgmstream->config_set) { + double time_mm, time_ss, seconds; + int32_t samples = vgmstream->pstate.play_duration; + + seconds = (double)samples / vgmstream->sample_rate; + time_mm = (int)(seconds / 60.0); + time_ss = seconds - time_mm * 60.0f; + + snprintf(temp,TEMPSIZE, "play duration: %d samples (%1.0f:%06.3f seconds)\n", samples, time_mm, time_ss); + concatn(length,desc,temp); + } } diff --git a/src/vgmstream.h b/src/vgmstream.h index 63ba9a21..77a4861a 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -780,20 +780,65 @@ typedef enum { } mapping_t; typedef struct { + /* modifiers */ int play_forever; - int loop_count_set; - double loop_count; - int fade_time_set; - double fade_time; - int fade_delay_set; - double fade_delay; - int ignore_fade; + int ignore_loop; int force_loop; int really_force_loop; - int ignore_loop; + int ignore_fade; + + /* processing */ + int32_t pad_begin; + int32_t trim_begin; + int32_t target_time; + double loop_count; + int32_t trim_end; + double fade_delay; /* not in samples for backwards compatibility */ + double fade_time; + int32_t pad_end; + + /* internal flags */ + int pad_begin_set; + int trim_begin_set; + int target_time_set; + int loop_count_set; + int trim_end_set; + int fade_delay_set; + int fade_time_set; + int pad_end_set; + } play_config_t; +typedef struct { + int input_channels; + int output_channels; + + int32_t pad_begin_duration; + int32_t pad_begin_start; + int32_t pad_begin_end; + + int32_t trim_begin_duration; + int32_t trim_begin_start; + int32_t trim_begin_end; + + int32_t body_duration; + int32_t body_start; + int32_t body_end; + + int32_t fade_duration; + int32_t fade_start; + int32_t fade_end; + + int32_t pad_end_duration; + int32_t pad_end_start; + int32_t pad_end_end; + + int32_t play_duration; /* total samples that the stream lasts (after applying all config) */ + int32_t play_position; /* absolute sample where stream is */ +} play_state_t; + + /* info for a single vgmstream channel */ typedef struct { STREAMFILE* streamfile; /* file used by this channel */ @@ -879,16 +924,6 @@ typedef struct { int allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */ - /* config requests, players must read and honor these values - * (ideally internally would work as a player, but for now player must do it manually) */ - play_config_t config; - - - /* play state */ - int loop_count; /* counter of complete loops (1=looped once) */ - int loop_target; /* max loops before continuing with the stream end (loops forever if not set) */ - - /* layout/block state */ size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */ int32_t current_sample; /* sample point within the file (for loop detection) */ @@ -930,6 +965,14 @@ typedef struct { /* Same, for special layouts. layout_data + codec_data may exist at the same time. */ void* layout_data; + + /* play config/state */ + int config_set; /* current config */ + play_config_t config; /* player config (applied over decoding) */ + play_state_t pstate; /* player state (applied over decoding) */ + int loop_count; /* counter of complete loops (1=looped once) */ + int loop_target; /* max loops before continuing with the stream end (loops forever if not set) */ + } VGMSTREAM; @@ -1126,4 +1169,8 @@ void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t ou void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size); void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size); +//void pad_begin_vgmstream(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_do); +//void trim_begin_vgmstream(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_do); +//void pad_end_vgmstream(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_do); +void fade_vgmstream(VGMSTREAM* vgmstream, sample_t* buf, int samples_done); #endif