mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
add reset_vgmstream, which allows a much cleaner way to reset the stream for looping
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@170 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
130905dc00
commit
ce12116067
@ -78,9 +78,11 @@ VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs) {
|
||||
}
|
||||
|
||||
/* save start things so we can restart for seeking */
|
||||
/* TODO: we may need to save other things here */
|
||||
/* copy the channels */
|
||||
memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
vgmstream->start_block_offset = vgmstream->current_block_offset;
|
||||
/* copy the whole VGMSTREAM */
|
||||
memcpy(vgmstream->start_vgmstream,vgmstream,sizeof(VGMSTREAM));
|
||||
|
||||
return vgmstream;
|
||||
}
|
||||
}
|
||||
@ -88,9 +90,25 @@ VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Reset a VGMSTREAM to its state at the start of playback.
|
||||
* Note that this does not reset the constituent STREAMFILES. */
|
||||
void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||
/* copy the vgmstream back into itself */
|
||||
memcpy(vgmstream,vgmstream->start_vgmstream,sizeof(VGMSTREAM));
|
||||
|
||||
/* copy the initial channels */
|
||||
memcpy(vgmstream->ch,vgmstream->start_ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
|
||||
/* loop_ch is not zeroed here because there is a possibility of the
|
||||
* init_vgmstream_* function doing something tricky and precomputing it.
|
||||
* Otherwise hit_loop will be 0 and it will be copied over anyway when we
|
||||
* really hit the loop start. */
|
||||
}
|
||||
|
||||
/* simply allocate memory for the VGMSTREAM and its channels */
|
||||
VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||
VGMSTREAM * vgmstream;
|
||||
VGMSTREAM * start_vgmstream;
|
||||
VGMSTREAMCHANNEL * channels;
|
||||
VGMSTREAMCHANNEL * start_channels;
|
||||
VGMSTREAMCHANNEL * loop_channels;
|
||||
@ -100,9 +118,18 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||
vgmstream = calloc(1,sizeof(VGMSTREAM));
|
||||
if (!vgmstream) return NULL;
|
||||
|
||||
start_vgmstream = calloc(1,sizeof(VGMSTREAM));
|
||||
if (!start_vgmstream) {
|
||||
free(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
vgmstream->start_vgmstream = start_vgmstream;
|
||||
start_vgmstream->start_vgmstream = start_vgmstream;
|
||||
|
||||
channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||
if (!channels) {
|
||||
free(vgmstream);
|
||||
free(start_vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
vgmstream->ch = channels;
|
||||
@ -111,6 +138,7 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||
start_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||
if (!start_channels) {
|
||||
free(vgmstream);
|
||||
free(start_vgmstream);
|
||||
free(channels);
|
||||
return NULL;
|
||||
}
|
||||
@ -120,6 +148,7 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||
loop_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||
if (!loop_channels) {
|
||||
free(vgmstream);
|
||||
free(start_vgmstream);
|
||||
free(channels);
|
||||
free(start_channels);
|
||||
return NULL;
|
||||
@ -143,6 +172,8 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
if (vgmstream->loop_ch) free(vgmstream->loop_ch);
|
||||
if (vgmstream->start_ch) free(vgmstream->start_ch);
|
||||
if (vgmstream->ch) free(vgmstream->ch);
|
||||
/* the start_vgmstream is considered just data */
|
||||
if (vgmstream->start_vgmstream) free(vgmstream->start_vgmstream);
|
||||
|
||||
free(vgmstream);
|
||||
}
|
||||
@ -746,8 +777,7 @@ void try_dual_file_stereo(VGMSTREAM * opened_stream, const char * const filename
|
||||
* difficult to determine when it does, and they should be zero
|
||||
* otherwise, anyway */
|
||||
new_stream->interleave_block_size == opened_stream->interleave_block_size &&
|
||||
new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size &&
|
||||
new_stream->start_block_offset == opened_stream->start_block_offset) {
|
||||
new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size) {
|
||||
/* We seem to have a usable, matching file. Merge in the second channel. */
|
||||
VGMSTREAMCHANNEL * new_chans;
|
||||
VGMSTREAMCHANNEL * new_loop_chans = NULL;
|
||||
|
@ -159,7 +159,6 @@ typedef struct {
|
||||
size_t interleave_block_size; /* interleave for this file */
|
||||
size_t interleave_smallblock_size; /* smaller interleave for last block */
|
||||
/* headered blocks */
|
||||
off_t start_block_offset; /* first block in the file */
|
||||
off_t current_block_offset; /* start of this block (offset of block header) */
|
||||
size_t current_block_size; /* size of the block we're in now */
|
||||
off_t next_block_offset; /* offset of header of the next block */
|
||||
@ -175,6 +174,8 @@ typedef struct {
|
||||
|
||||
uint8_t xa_channel; /* Selected XA Channel */
|
||||
int32_t xa_sector_length; /* XA block */
|
||||
|
||||
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
|
||||
} VGMSTREAM;
|
||||
|
||||
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
|
||||
@ -184,6 +185,9 @@ VGMSTREAM * init_vgmstream(const char * const filename);
|
||||
* about */
|
||||
VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs);
|
||||
|
||||
/* reset a VGMSTREAM to start of stream */
|
||||
void reset_vgmstream(VGMSTREAM * vgmstream);
|
||||
|
||||
/* allocate a VGMSTREAM and channel stuff */
|
||||
VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
|
||||
|
||||
|
49
test/test.c
49
test/test.c
@ -25,6 +25,7 @@ void usage(const char * name) {
|
||||
" -x: decode and print adxencd command line to encode as ADX\n"
|
||||
" -e: force end-to-end looping\n"
|
||||
" -E: force end-to-end looping even if file has real loop points\n"
|
||||
" -r outfile2.wav: output a second time after resetting\n"
|
||||
,name);
|
||||
|
||||
}
|
||||
@ -37,6 +38,7 @@ int main(int argc, char ** argv) {
|
||||
int i;
|
||||
FILE * outfile = NULL;
|
||||
char * outfilename = NULL;
|
||||
char * reset_outfilename = NULL;
|
||||
int opt;
|
||||
int ignore_loop = 0;
|
||||
int force_loop = 0;
|
||||
@ -50,7 +52,7 @@ int main(int argc, char ** argv) {
|
||||
double fade_seconds = 10.0;
|
||||
double fade_delay_seconds = 0.0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeE")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeEr:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
outfilename = optarg;
|
||||
@ -89,6 +91,9 @@ int main(int argc, char ** argv) {
|
||||
case 'E':
|
||||
really_force_loop = 1;
|
||||
break;
|
||||
case 'r':
|
||||
reset_outfilename = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
@ -161,7 +166,7 @@ int main(int argc, char ** argv) {
|
||||
if (!outfilename) outfilename = "dump.wav";
|
||||
outfile = fopen(outfilename,"wb");
|
||||
if (!outfile) {
|
||||
fprintf(stderr,"failed to open %s for output\n",optarg);
|
||||
fprintf(stderr,"failed to open %s for output\n",outfilename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -229,7 +234,45 @@ int main(int argc, char ** argv) {
|
||||
}
|
||||
fwrite(buf,sizeof(sample)*s->channels,toget,outfile);
|
||||
}
|
||||
|
||||
|
||||
fclose(outfile); outfile = NULL;
|
||||
|
||||
if (reset_outfilename) {
|
||||
outfile = fopen(reset_outfilename,"wb");
|
||||
if (!outfile) {
|
||||
fprintf(stderr,"failed to open %s for output\n",reset_outfilename);
|
||||
return 1;
|
||||
}
|
||||
/* slap on a .wav header */
|
||||
make_wav_header((uint8_t*)buf, len, s->sample_rate, s->channels);
|
||||
fwrite(buf,1,0x2c,outfile);
|
||||
|
||||
reset_vgmstream(s);
|
||||
/* decode */
|
||||
for (i=0;i<len;i+=BUFSIZE) {
|
||||
int toget=BUFSIZE;
|
||||
if (i+BUFSIZE>len) toget=len-i;
|
||||
render_vgmstream(buf,toget,s);
|
||||
|
||||
if (s->loop_flag && fade_samples > 0) {
|
||||
int samples_into_fade = i - (len - fade_samples);
|
||||
if (samples_into_fade + toget > 0) {
|
||||
int j,k;
|
||||
for (j=0;j<toget;j++,samples_into_fade++) {
|
||||
if (samples_into_fade > 0) {
|
||||
double fadedness = (double)(fade_samples-samples_into_fade)/fade_samples;
|
||||
for (k=0;k<s->channels;k++) {
|
||||
buf[j*s->channels+k] = buf[j*s->channels+k]*fadedness;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fwrite(buf,sizeof(sample)*s->channels,toget,outfile);
|
||||
}
|
||||
fclose(outfile); outfile = NULL;
|
||||
}
|
||||
|
||||
close_vgmstream(s);
|
||||
|
||||
return 0;
|
||||
|
@ -397,32 +397,19 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
||||
if (seek_needed_samples != -1) {
|
||||
/* reset if we need to seek backwards */
|
||||
if (seek_needed_samples < decode_pos_samples) {
|
||||
VGMSTREAM * new_temp;
|
||||
VGMSTREAM * old_temp;
|
||||
|
||||
new_temp = init_vgmstream(lastfn);
|
||||
if (!new_temp) {
|
||||
PostMessage(input_module.hMainWindow, /* message dest */
|
||||
WM_WA_MPEG_EOF, /* message id */
|
||||
0,0); /* no parameters */
|
||||
return 0;
|
||||
}
|
||||
if (ignore_loop)
|
||||
new_temp->loop_flag = 0;
|
||||
|
||||
old_temp = vgmstream;
|
||||
vgmstream = new_temp;
|
||||
|
||||
close_vgmstream(old_temp);
|
||||
reset_vgmstream(vgmstream);
|
||||
|
||||
decode_pos_samples = 0;
|
||||
decode_pos_ms = 0;
|
||||
}
|
||||
|
||||
if (decode_pos_samples < seek_needed_samples) {
|
||||
samples_to_do=seek_needed_samples-decode_pos_samples;
|
||||
if (samples_to_do>576) samples_to_do=576;
|
||||
} else
|
||||
seek_needed_samples = -1;
|
||||
|
||||
input_module.outMod->Flush((int)decode_pos_ms);
|
||||
}
|
||||
|
||||
l = (samples_to_do*vgmstream->channels*2)<<(input_module.dsp_isactive()?1:0);
|
||||
@ -439,7 +426,6 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
||||
}
|
||||
else if (seek_needed_samples != -1) {
|
||||
render_vgmstream(sample_buffer,samples_to_do,vgmstream);
|
||||
input_module.outMod->Flush((int)decode_pos_ms);
|
||||
|
||||
decode_pos_samples+=samples_to_do;
|
||||
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
|
||||
|
Loading…
Reference in New Issue
Block a user