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:
halleyscometsw 2008-05-19 03:58:15 +00:00
parent 130905dc00
commit ce12116067
4 changed files with 89 additions and 26 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}
@ -230,6 +235,44 @@ 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;

View File

@ -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;