Add TXTP silence entry

This commit is contained in:
bnnm 2020-08-15 20:04:50 +02:00
parent e4ed26e703
commit f5a9e5d06a
2 changed files with 77 additions and 1 deletions

View File

@ -235,6 +235,30 @@ loop_mode = keep
``` ```
### Silent files
You can put `?.` in an entry to make a silent (non-existing) file. By default takes channels and sample rate of nearby files, can be combined with regular commands to configure.
```
intro.adx
?.silence #b 3.0 # 3 seconds of silence
loop.adx
```
It also doubles as a quick "silence this file" while keeping the same structure, for complex cases. The `.` can actually be anywhere after `?`, but must appear before commands to function correctly.
```
layer1a.adx
?layer1b.adx
group = -L2
?layer2a.adx
layer2b.adx
group = -L2
group = -S2
```
Most of the time you can do the same with `#p`/`#P` padding commands or `#@volume 0.0`. This is mainly for complex engines that combine silent entries in twisted ways. You can't silence `group` with `?group` though since they aren't considered "entries".
## TXTP COMMANDS ## TXTP COMMANDS
You can set file commands by adding multiple `#(command)` after the name. `#(space)(anything)` is considered a comment and ignored, as well as any command not understood. You can set file commands by adding multiple `#(command)` after the name. `#(space)(anything)` is considered a comment and ignored, as well as any command not understood.

View File

@ -66,6 +66,7 @@ typedef struct {
typedef struct { typedef struct {
/* main entry */ /* main entry */
char filename[TXTP_LINE_MAX]; char filename[TXTP_LINE_MAX];
int silent;
/* TXTP settings (applied at the end) */ /* TXTP settings (applied at the end) */
int range_start; int range_start;
@ -206,9 +207,46 @@ static void clean_txtp(txtp_header* txtp, int fail) {
/* ENTRIES */ /* ENTRIES */
/*******************************************************************************/ /*******************************************************************************/
static int parse_silents(txtp_header* txtp) {
int i;
int channels = 0;
int sample_rate = 0;
int32_t num_samples = 0;
/* silents use same channels as close files */
for (i = 0; i < txtp->vgmstream_count; i++) {
if (!txtp->entry[i].silent) {
channels = txtp->vgmstream[i]->channels;
sample_rate = txtp->vgmstream[i]->sample_rate;
break;
}
}
/* actually open silents */
for (i = 0; i < txtp->vgmstream_count; i++) {
if (!txtp->entry[i].silent)
continue;
txtp->vgmstream[i] = init_vgmstream_silence(channels, sample_rate, num_samples);
if (!txtp->vgmstream[i]) goto fail;
apply_settings(txtp->vgmstream[i], &txtp->entry[i]);
}
return 1;
fail:
return 0;
}
static int is_silent(txtp_entry* entry) {
/* should also contain "." in the filename for commands with seconds ("1.0") to work */
return entry->filename[0] == '?';
}
/* open all entries and apply settings to resulting VGMSTREAMs */ /* open all entries and apply settings to resulting VGMSTREAMs */
static int parse_entries(txtp_header* txtp, STREAMFILE* sf) { static int parse_entries(txtp_header* txtp, STREAMFILE* sf) {
int i; int i;
int has_silents = 0;
if (txtp->entry_count == 0) if (txtp->entry_count == 0)
@ -222,7 +260,16 @@ static int parse_entries(txtp_header* txtp, STREAMFILE* sf) {
/* open all entry files first as they'll be modified by modes */ /* open all entry files first as they'll be modified by modes */
for (i = 0; i < txtp->vgmstream_count; i++) { for (i = 0; i < txtp->vgmstream_count; i++) {
STREAMFILE* temp_sf = open_streamfile_by_filename(sf, txtp->entry[i].filename); STREAMFILE* temp_sf = NULL;
/* silent entry ignore */
if (is_silent(&txtp->entry[i])) {
txtp->entry[i].silent = 1;
has_silents = 1;
continue;
}
temp_sf = open_streamfile_by_filename(sf, txtp->entry[i].filename);
if (!temp_sf) { if (!temp_sf) {
VGM_LOG("TXTP: cannot open streamfile for %s\n", txtp->entry[i].filename); VGM_LOG("TXTP: cannot open streamfile for %s\n", txtp->entry[i].filename);
goto fail; goto fail;
@ -239,6 +286,11 @@ static int parse_entries(txtp_header* txtp, STREAMFILE* sf) {
apply_settings(txtp->vgmstream[i], &txtp->entry[i]); apply_settings(txtp->vgmstream[i], &txtp->entry[i]);
} }
if (has_silents) {
if (!parse_silents(txtp))
goto fail;
}
return 1; return 1;
fail: fail:
return 0; return 0;