test.exe: add "-F" option to loop + play stream's end instead of fading

This commit is contained in:
bnnm 2017-05-18 19:55:00 +02:00
parent 2c1dafa1a0
commit 9488ba32c7
3 changed files with 60 additions and 19 deletions

View File

@ -869,12 +869,31 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
free(vgmstream);
}
/* calculate samples based on player's config */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream) {
if (vgmstream->loop_flag) {
return vgmstream->loop_start_sample+(vgmstream->loop_end_sample-vgmstream->loop_start_sample)*looptimes+(fadedelayseconds+fadeseconds)*vgmstream->sample_rate;
} else return vgmstream->num_samples;
if (fadeseconds < 0) { /* a bit hack-y to avoid signature change */
/* Continue playing the file normally after looping, instead of fading.
* Most files cut abruply after the loop, but some do have proper endings.
* With looptimes = 1 this option should give the same output vs loop disabled */
int loop_count = (int)looptimes; /* no half loops allowed */
vgmstream->loop_target = loop_count;
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * loop_count
+ (vgmstream->num_samples - vgmstream->loop_end_sample);
}
else {
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * looptimes
+ (fadedelayseconds + fadeseconds) * vgmstream->sample_rate;
}
}
else {
return vgmstream->num_samples;
}
}
/* decode data into sample buffer */
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
switch (vgmstream->layout_type) {
case layout_interleave:
@ -1788,13 +1807,21 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST
return samples_to_do;
}
/* return 1 if we just looped */
/* loop if end sample is reached, and return 1 if we did loop */
int vgmstream_do_loop(VGMSTREAM * vgmstream) {
/*if (vgmstream->loop_flag) return 0;*/
/*if (!vgmstream->loop_flag) return 0;*/
/* is this the loop end? */
/* is this the loop end? = new loop, continue from loop_start_sample */
if (vgmstream->current_sample==vgmstream->loop_end_sample) {
/* disable looping if target count reached and continue normally
* (only needed with the "play stream end after looping N times" option enabled) */
vgmstream->loop_count++;
if (vgmstream->loop_target && vgmstream->loop_target == vgmstream->loop_count) {
vgmstream->loop_flag = 0; /* could be improved but works ok */
return 0;
}
/* against everything I hold sacred, preserve adpcm
* history through loop for certain types */
if (vgmstream->meta_type == meta_DSP_STD ||

View File

@ -728,8 +728,6 @@ typedef struct {
off_t next_block_offset; /* offset of header of the next block */
int block_count; /* count of "semi" block in total block */
int hit_loop; /* have we seen the loop yet? */
/* loop layout (saved values) */
int32_t loop_sample; /* saved from current_sample, should be loop_start_sample... */
int32_t loop_samples_into_block;/* saved from samples_into_block */
@ -737,6 +735,12 @@ typedef struct {
size_t loop_block_size; /* saved from current_block_size */
off_t loop_next_block_offset; /* saved from next_block_offset */
/* loop internals */
int hit_loop; /* have we seen the loop yet? */
/* counters for "loop + play end of the stream instead of fading" (not used/needed otherwise) */
int loop_count; /* number of complete loops (1=looped once) */
int loop_target; /* max loops before continuing with the stream end */
/* decoder specific */
int codec_endian; /* little/big endian marker; name is left vague but usually means big endian */

View File

@ -36,7 +36,7 @@ void usage(const char * name) {
"Options:\n"
" -o outfile.wav: name of output .wav file, default is dump.wav\n"
" -l loop count: loop count, default 2.0\n"
" -f fade time: fade time (seconds), default 10.0\n"
" -f fade time: fade time (seconds) after N loops, default 10.0\n"
" -d fade delay: fade delay (seconds, default 0.0\n"
" -i: ignore looping information and play the whole stream once\n"
" -p: output to stdout (for piping into another program)\n"
@ -46,11 +46,12 @@ void usage(const char * name) {
" -x: decode and print adxencd command line to encode as ADX\n"
" -g: decode and print oggenc command line to encode as OGG\n"
" -b: decode and print batch variable commands\n"
" -L: append a smpl chunk and create a looping wav\n"
" -L: append a smpl chunk and create a looping wav\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"
" -2 N: only output the Nth (first is 0) set of stereo channels\n"
" -F: don't fade after N loops and play the rest of the stream\n"
,name);
}
@ -73,15 +74,16 @@ int main(int argc, char ** argv) {
int metaonly = 0;
int adxencd = 0;
int oggenc = 0;
int lwav = 0;
int lwav = 0;
int batchvar = 0;
int only_stereo = -1;
double loop_count = 2.0;
double fade_seconds = 10.0;
double fade_delay_seconds = 0.0;
int32_t bytecount;
int fade_ignore = 0;
int32_t bytecount;
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeLEr:gb2:")) != -1) {
while ((opt = getopt(argc, argv, "o:l:f:d:ipPcmxeLEFr:gb2:")) != -1) {
switch (opt) {
case 'o':
outfilename = optarg;
@ -127,14 +129,17 @@ int main(int argc, char ** argv) {
really_force_loop = 1;
break;
case 'L':
lwav = 1;
break;
lwav = 1;
break;
case 'r':
reset_outfilename = optarg;
break;
case '2':
only_stereo = atoi(optarg);
break;
case 'F':
fade_ignore = 1;
break;
default:
usage(argv[0]);
return 1;
@ -263,6 +268,11 @@ int main(int argc, char ** argv) {
return 1;
}
/* signal ignore fade for get_vgmstream_play_samples */
if (loop_count && fade_ignore) {
fade_seconds = -1.0;
}
len = get_vgmstream_play_samples(loop_count,fade_seconds,fade_delay_seconds,s);
if (!play && !adxencd && !oggenc && !batchvar) printf("samples to play: %d (%.4lf seconds)\n",len,(double)len/s->sample_rate);
fade_samples = fade_seconds * s->sample_rate;
@ -273,10 +283,10 @@ int main(int argc, char ** argv) {
} else {
make_wav_header((uint8_t*)buf, len, s->sample_rate, s->channels);
}
if (lwav && s->loop_flag) { // Adding space for smpl chunk at end
if (lwav && s->loop_flag) { // Adding space for smpl chunk at end
bytecount = get_32bitLE((uint8_t*)buf + 4);
put_32bitLE((uint8_t*)buf + 4, bytecount + 0x44);
}
}
fwrite(buf,1,0x2c,outfile);
/* decode forever */
@ -325,9 +335,9 @@ int main(int argc, char ** argv) {
}
}
if (lwav && s->loop_flag) { // Writing smpl chuck
make_smpl_chunk((uint8_t*)buf, s->loop_start_sample, s->loop_end_sample);
fwrite(buf,1,0x44,outfile);
if (lwav && s->loop_flag) { // Writing smpl chuck
make_smpl_chunk((uint8_t*)buf, s->loop_start_sample, s->loop_end_sample);
fwrite(buf,1,0x44,outfile);
}
fclose(outfile); outfile = NULL;