mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-17 19:19:16 +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 */
|
/* 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);
|
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;
|
return vgmstream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,9 +90,25 @@ VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs) {
|
|||||||
return NULL;
|
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 */
|
/* simply allocate memory for the VGMSTREAM and its channels */
|
||||||
VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||||
VGMSTREAM * vgmstream;
|
VGMSTREAM * vgmstream;
|
||||||
|
VGMSTREAM * start_vgmstream;
|
||||||
VGMSTREAMCHANNEL * channels;
|
VGMSTREAMCHANNEL * channels;
|
||||||
VGMSTREAMCHANNEL * start_channels;
|
VGMSTREAMCHANNEL * start_channels;
|
||||||
VGMSTREAMCHANNEL * loop_channels;
|
VGMSTREAMCHANNEL * loop_channels;
|
||||||
@ -100,9 +118,18 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
|||||||
vgmstream = calloc(1,sizeof(VGMSTREAM));
|
vgmstream = calloc(1,sizeof(VGMSTREAM));
|
||||||
if (!vgmstream) return NULL;
|
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));
|
channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||||
if (!channels) {
|
if (!channels) {
|
||||||
free(vgmstream);
|
free(vgmstream);
|
||||||
|
free(start_vgmstream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vgmstream->ch = channels;
|
vgmstream->ch = channels;
|
||||||
@ -111,6 +138,7 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
|||||||
start_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
start_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||||
if (!start_channels) {
|
if (!start_channels) {
|
||||||
free(vgmstream);
|
free(vgmstream);
|
||||||
|
free(start_vgmstream);
|
||||||
free(channels);
|
free(channels);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -120,6 +148,7 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
|||||||
loop_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
loop_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
||||||
if (!loop_channels) {
|
if (!loop_channels) {
|
||||||
free(vgmstream);
|
free(vgmstream);
|
||||||
|
free(start_vgmstream);
|
||||||
free(channels);
|
free(channels);
|
||||||
free(start_channels);
|
free(start_channels);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -143,6 +172,8 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
|||||||
if (vgmstream->loop_ch) free(vgmstream->loop_ch);
|
if (vgmstream->loop_ch) free(vgmstream->loop_ch);
|
||||||
if (vgmstream->start_ch) free(vgmstream->start_ch);
|
if (vgmstream->start_ch) free(vgmstream->start_ch);
|
||||||
if (vgmstream->ch) free(vgmstream->ch);
|
if (vgmstream->ch) free(vgmstream->ch);
|
||||||
|
/* the start_vgmstream is considered just data */
|
||||||
|
if (vgmstream->start_vgmstream) free(vgmstream->start_vgmstream);
|
||||||
|
|
||||||
free(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
|
* difficult to determine when it does, and they should be zero
|
||||||
* otherwise, anyway */
|
* otherwise, anyway */
|
||||||
new_stream->interleave_block_size == opened_stream->interleave_block_size &&
|
new_stream->interleave_block_size == opened_stream->interleave_block_size &&
|
||||||
new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size &&
|
new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size) {
|
||||||
new_stream->start_block_offset == opened_stream->start_block_offset) {
|
|
||||||
/* We seem to have a usable, matching file. Merge in the second channel. */
|
/* We seem to have a usable, matching file. Merge in the second channel. */
|
||||||
VGMSTREAMCHANNEL * new_chans;
|
VGMSTREAMCHANNEL * new_chans;
|
||||||
VGMSTREAMCHANNEL * new_loop_chans = NULL;
|
VGMSTREAMCHANNEL * new_loop_chans = NULL;
|
||||||
|
@ -159,7 +159,6 @@ typedef struct {
|
|||||||
size_t interleave_block_size; /* interleave for this file */
|
size_t interleave_block_size; /* interleave for this file */
|
||||||
size_t interleave_smallblock_size; /* smaller interleave for last block */
|
size_t interleave_smallblock_size; /* smaller interleave for last block */
|
||||||
/* headered blocks */
|
/* 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) */
|
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 */
|
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 */
|
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 */
|
uint8_t xa_channel; /* Selected XA Channel */
|
||||||
int32_t xa_sector_length; /* XA block */
|
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;
|
} VGMSTREAM;
|
||||||
|
|
||||||
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
|
/* 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 */
|
* about */
|
||||||
VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs);
|
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 */
|
/* allocate a VGMSTREAM and channel stuff */
|
||||||
VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
|
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"
|
" -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\n"
|
||||||
" -E: force end-to-end looping even if file has real loop points\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);
|
,name);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -37,6 +38,7 @@ int main(int argc, char ** argv) {
|
|||||||
int i;
|
int i;
|
||||||
FILE * outfile = NULL;
|
FILE * outfile = NULL;
|
||||||
char * outfilename = NULL;
|
char * outfilename = NULL;
|
||||||
|
char * reset_outfilename = NULL;
|
||||||
int opt;
|
int opt;
|
||||||
int ignore_loop = 0;
|
int ignore_loop = 0;
|
||||||
int force_loop = 0;
|
int force_loop = 0;
|
||||||
@ -50,7 +52,7 @@ int main(int argc, char ** argv) {
|
|||||||
double fade_seconds = 10.0;
|
double fade_seconds = 10.0;
|
||||||
double fade_delay_seconds = 0.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) {
|
switch (opt) {
|
||||||
case 'o':
|
case 'o':
|
||||||
outfilename = optarg;
|
outfilename = optarg;
|
||||||
@ -89,6 +91,9 @@ int main(int argc, char ** argv) {
|
|||||||
case 'E':
|
case 'E':
|
||||||
really_force_loop = 1;
|
really_force_loop = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
reset_outfilename = optarg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
@ -161,7 +166,7 @@ int main(int argc, char ** argv) {
|
|||||||
if (!outfilename) outfilename = "dump.wav";
|
if (!outfilename) outfilename = "dump.wav";
|
||||||
outfile = fopen(outfilename,"wb");
|
outfile = fopen(outfilename,"wb");
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
fprintf(stderr,"failed to open %s for output\n",optarg);
|
fprintf(stderr,"failed to open %s for output\n",outfilename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +234,45 @@ int main(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
fwrite(buf,sizeof(sample)*s->channels,toget,outfile);
|
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);
|
close_vgmstream(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -397,32 +397,19 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
|||||||
if (seek_needed_samples != -1) {
|
if (seek_needed_samples != -1) {
|
||||||
/* reset if we need to seek backwards */
|
/* reset if we need to seek backwards */
|
||||||
if (seek_needed_samples < decode_pos_samples) {
|
if (seek_needed_samples < decode_pos_samples) {
|
||||||
VGMSTREAM * new_temp;
|
reset_vgmstream(vgmstream);
|
||||||
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);
|
|
||||||
|
|
||||||
decode_pos_samples = 0;
|
decode_pos_samples = 0;
|
||||||
decode_pos_ms = 0;
|
decode_pos_ms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode_pos_samples < seek_needed_samples) {
|
if (decode_pos_samples < seek_needed_samples) {
|
||||||
samples_to_do=seek_needed_samples-decode_pos_samples;
|
samples_to_do=seek_needed_samples-decode_pos_samples;
|
||||||
if (samples_to_do>576) samples_to_do=576;
|
if (samples_to_do>576) samples_to_do=576;
|
||||||
} else
|
} else
|
||||||
seek_needed_samples = -1;
|
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);
|
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) {
|
else if (seek_needed_samples != -1) {
|
||||||
render_vgmstream(sample_buffer,samples_to_do,vgmstream);
|
render_vgmstream(sample_buffer,samples_to_do,vgmstream);
|
||||||
input_module.outMod->Flush((int)decode_pos_ms);
|
|
||||||
|
|
||||||
decode_pos_samples+=samples_to_do;
|
decode_pos_samples+=samples_to_do;
|
||||||
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
|
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user