Add TXTP -t trim command to adjust stream's samples

This commit is contained in:
bnnm 2019-09-21 13:37:53 +02:00
parent 5cb5534612
commit c164549056
2 changed files with 65 additions and 10 deletions

View File

@ -224,7 +224,7 @@ music_Home.ps3.scd#C3 4
```
### Custom play settings
### Play settings
**`#l(loops)`**, **`#f(fade)`**, **`#d(fade-delay)`**, **`#i(ignore loop)`**, **`#F(ignore fade)`**, **`#E(end-to-end loop)`**
Those setting should override player's defaults if set (except "loop forever"). They are equivalent to some test.exe options.
@ -259,8 +259,29 @@ boss2_3ningumi_ver6.adx#l1.5#d1#f5
```
### Time modifications
**`#t(time)`**: trims the file so base duration (before applying loops/fades/etc) is `(time)`. If value is negative substracts `(time)` to duration. Loop end is adjusted when necessary, and ignored if value is bigger than possible (use `#l(loops)` config to extend time instead).
Time values can be `M:S(.n)` (minutes and seconds), `S.n` (seconds with dot), `0xN` (samples in hex format) or `N` (samples). Beware of the subtle difference between 10.0 (ten seconds) and 10 (ten samples).
Some segments have padding/silence at the end for some reason, that don't allow smooth transitions. You can fix it like this:
```
intro.fsb #t -1.0 #intro segment has 1 second of silence.
main.fsb
```
Similarly other games don't use loop points, but rather repeat/loops the song internally many times:
```
intro.vag #t3:20 #i #l1.0 #trim + combine with forced loops for easy fades
```
Note that if you need to remove very few samples (like 1) to get smooth transitions it may be a bug in vgmstream, consider reporting.
### Force sample rate
**`#h(sample rate)`**: for a few games that set a sample rate value in the header but actually play with other (applying some of pitch or just forcing it).
**`#h(sample rate)`**: changes sample rate to selected value (within some limits).
Needed for a few games set a sample rate value in the header but actually play with other (applying some of pitch or just forcing it).
**Super Paper Mario (Wii)**
```

View File

@ -83,13 +83,18 @@ typedef struct {
int config_ignore_fade;
int sample_rate;
int loop_install;
int loop_install_set;
int loop_end_max;
double loop_start_second;
int32_t loop_start_sample;
double loop_end_second;
int32_t loop_end_sample;
int trim_set;
double trim_second;
int32_t trim_sample;
} txtp_entry;
@ -442,7 +447,7 @@ static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current) {
if (current->sample_rate > 0)
vgmstream->sample_rate = current->sample_rate;
if (current->loop_install) {
if (current->loop_install_set) {
if (current->loop_start_second > 0 || current->loop_end_second > 0) {
current->loop_start_sample = current->loop_start_second * vgmstream->sample_rate;
current->loop_end_sample = current->loop_end_second * vgmstream->sample_rate;
@ -455,9 +460,27 @@ static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current) {
current->loop_end_sample = vgmstream->num_samples;
}
vgmstream_force_loop(vgmstream, current->loop_install, current->loop_start_sample, current->loop_end_sample);
vgmstream_force_loop(vgmstream, current->loop_install_set, current->loop_start_sample, current->loop_end_sample);
}
if (current->trim_set) {
if (current->trim_second != 0.0) {
current->trim_sample = current->trim_second * vgmstream->sample_rate;
}
if (current->trim_sample < 0) {
vgmstream->num_samples += current->trim_sample; /* trim from end (add negative) */
}
else if (vgmstream->num_samples > current->trim_sample) {
vgmstream->num_samples = current->trim_sample; /* trim to value */
}
/* readjust after triming if it went over (could check for more edge cases but eh) */
if (vgmstream->loop_end_sample > vgmstream->num_samples)
vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* add macro to mixing list */
if (current->channel_mask) {
int ch;
@ -625,7 +648,7 @@ static int get_time(const char * config, double *value_f, int32_t *value_i) {
m = sscanf(config, " %i%c%i%n", &temp_i1,&temp_c,&temp_i2,&n);
if (m == 3 && (temp_c == ':' || temp_c == '_')) {
m = sscanf(config, " %lf%c%lf%n", &temp_f1,&temp_c,&temp_f2,&n);
if (m != 3 || temp_f1 < 0.0 || temp_f1 >= 60.0 || temp_f2 < 0.0 || temp_f2 >= 60.0)
if (m != 3 || /*temp_f1 < 0.0 ||*/ temp_f1 >= 60.0 || temp_f2 < 0.0 || temp_f2 >= 60.0)
return 0;
*value_f = temp_f1 * 60.0 + temp_f2;
@ -636,7 +659,7 @@ static int get_time(const char * config, double *value_f, int32_t *value_i) {
m = sscanf(config, " %i.%i%n", &temp_i1,&temp_i2,&n);
if (m == 2) {
m = sscanf(config, " %lf%n", &temp_f1,&n);
if (m != 1 || temp_f1 < 0.0)
if (m != 1 /*|| temp_f1 < 0.0*/)
return 0;
*value_f = temp_f1;
return n;
@ -896,14 +919,20 @@ static void add_config(txtp_entry* current, txtp_entry* cfg, const char* filenam
current->sample_rate = cfg->sample_rate;
}
if (cfg->loop_install) {
current->loop_install = cfg->loop_install;
if (cfg->loop_install_set) {
current->loop_install_set = cfg->loop_install_set;
current->loop_end_max = cfg->loop_end_max;
current->loop_start_sample = cfg->loop_start_sample;
current->loop_start_second = cfg->loop_start_second;
current->loop_end_sample = cfg->loop_end_sample;
current->loop_end_second = cfg->loop_end_second;
}
if (cfg->trim_set) {
current->trim_set = cfg->trim_set;
current->trim_second = cfg->trim_second;
current->trim_sample = cfg->trim_sample;
}
}
static void parse_config(txtp_entry *cfg, char *config) {
@ -1084,12 +1113,17 @@ static void parse_config(txtp_entry *cfg, char *config) {
}
config += n;
cfg->loop_install = 1;
cfg->loop_install_set = 1;
}
//;VGM_LOG("TXTP: loop_install %i (max=%i): %i %i / %f %f\n", cfg->loop_install, cfg->loop_end_max,
// cfg->loop_start_sample, cfg->loop_end_sample, cfg->loop_start_second, cfg->loop_end_second);
}
else if (strcmp(command,"t") == 0) {
n = get_time(config, &cfg->trim_second, &cfg->trim_sample);
cfg->trim_set = (n > 0);
//;VGM_LOG("TXTP: trim %i - %f / %i\n", cfg->trim_set, cfg->trim_second, cfg->trim_sample);
}
//todo cleanup
else if (strcmp(command,"@volume") == 0) {
txtp_mix_data mix = {0};