cleanup: misc renames

This commit is contained in:
bnnm 2023-05-15 16:14:29 +02:00
parent 4e5631e630
commit 0746a89210
13 changed files with 73 additions and 72 deletions

View File

@ -122,7 +122,7 @@ Very simplified it goes like this:
- layout prepares samples and offsets to read from the stream *[render_vgmstream_(layout)]*
- decoder reads and decodes bytes into PCM samples *[decode_vgmstream_(coding)]*
- player plays those samples, asks to fill sample buffer again, repeats (until total_samples)
- layout moves offsets back to loop_start when loop_end is reached *[vgmstream_do_loop]*
- layout moves offsets back to loop_start when loop_end is reached *[decode_do_loop]*
- player closes the VGMSTREAM once the stream is finished
vgsmtream's main code (located in src) may be considered "libvgmstream", and plugins interface it through vgmstream.h, mainly the part commented as "vgmstream public API". There isn't a clean external API at the moment, this may be improved later.
@ -201,10 +201,10 @@ If the decoder needs to keep state between calls it may use the VGMSTREAM for co
Adding a new decoder involves:
- *src/coding/(decoder-name).c*: create `decode_x` function that decodes stream data into the passed sample buffer. If the codec requires custom internals it may need `init/reset/seek/free_x`, or other helper functions.
- *src/coding/coding.h*: define decoder's functions and type
- *src/decode.c: get_vgmstream_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples)
- *src/decode.c: get_vgmstream_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way.
- *src/decode.c: decode_get_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples)
- *src/decode.c: decode_get_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way.
- *src/decode.c: decode_vgmstream*: call `decode_x`, possibly once per channel if the decoder works with a channel at a time.
- *src/decode.c: add handling in `reset/seek/free_codec` if needed
- *src/decode.c: add handling in `reset/seek/decode_free` if needed
- *src/formats.c*: add coding type description
- *src/libvgmstream.vcproj/vcxproj/filters*: add to compile new (decoder-name).c parser in VS
- if the codec depends on a external library don't forget to mark parts with: *#ifdef VGM_USE_X ... #endif*

View File

@ -8,7 +8,7 @@
/* custom codec handling, not exactly "decode" stuff but here to simplify adding new codecs */
void free_codec(VGMSTREAM* vgmstream) {
void decode_free(VGMSTREAM* vgmstream) {
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type == coding_OGG_VORBIS) {
@ -119,7 +119,7 @@ void free_codec(VGMSTREAM* vgmstream) {
}
void seek_codec(VGMSTREAM* vgmstream) {
void decode_seek(VGMSTREAM* vgmstream) {
if (vgmstream->coding_type == coding_CIRCUS_VQ) {
seek_circus_vq(vgmstream->codec_data, vgmstream->loop_current_sample);
}
@ -213,7 +213,7 @@ void seek_codec(VGMSTREAM* vgmstream) {
}
void reset_codec(VGMSTREAM* vgmstream) {
void decode_reset(VGMSTREAM* vgmstream) {
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type == coding_OGG_VORBIS) {
@ -325,7 +325,7 @@ void reset_codec(VGMSTREAM* vgmstream) {
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
/* Value returned here is the max (or less) that vgmstream will ask a decoder per
* "decode_x" call. Decoders with variable samples per frame or internal discard
* may return 0 here and handle arbitrary samples_to_do values internally
@ -555,7 +555,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
}
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
int decode_get_frame_size(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_SILENCE:
return 0;
@ -747,21 +747,21 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
}
/* In NDS IMA the frame size is the block size, so the last one is short */
int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream) {
int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return (vgmstream->interleave_last_block_size-4)*2;
default:
return get_vgmstream_samples_per_frame(vgmstream);
return decode_get_samples_per_frame(vgmstream);
}
}
int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream) {
int decode_get_shortframe_size(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return vgmstream->interleave_last_block_size;
default:
return get_vgmstream_frame_size(vgmstream);
return decode_get_frame_size(vgmstream);
}
}
@ -1488,7 +1488,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
/* Calculate number of consecutive samples we can decode. Takes into account hitting
* a loop start or end, or going past a single frame. */
int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) {
int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) {
int samples_to_do;
int samples_left_this_block;
@ -1521,7 +1521,7 @@ int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, V
/* Detect loop start and save values, or detect loop end and restore (loop back).
* Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM* vgmstream) {
int decode_do_loop(VGMSTREAM* vgmstream) {
/*if (!vgmstream->loop_flag) return 0;*/
/* is this the loop end? = new loop, continue from loop_start_sample */
@ -1557,7 +1557,7 @@ int vgmstream_do_loop(VGMSTREAM* vgmstream) {
* - loop_ch[] is copied to ch[] (with custom value)
* - then codec will use ch[]'s offset
* regular codecs may use copied loop_ch[] offset without issue */
seek_codec(vgmstream);
decode_seek(vgmstream);
/* restore! */
memcpy(vgmstream->ch, vgmstream->loop_ch, sizeof(VGMSTREAMCHANNEL) * vgmstream->channels);

View File

@ -3,30 +3,30 @@
#include "../vgmstream.h"
void free_codec(VGMSTREAM* vgmstream);
void seek_codec(VGMSTREAM* vgmstream);
void reset_codec(VGMSTREAM* vgmstream);
void decode_free(VGMSTREAM* vgmstream);
void decode_seek(VGMSTREAM* vgmstream);
void decode_reset(VGMSTREAM* vgmstream);
/* Decode samples into the buffer. Assume that we have written samples_written into the
* buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer);
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM* vgmstream);
int decode_do_loop(VGMSTREAM* vgmstream);
/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);
int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream);
int decode_get_samples_per_frame(VGMSTREAM* vgmstream);
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM* vgmstream);
int decode_get_frame_size(VGMSTREAM* vgmstream);
/* In NDS IMA the frame size is the block size, but last one is shorter */
int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream);
int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream);
int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream);
int decode_get_shortframe_size(VGMSTREAM* vgmstream);
#endif

View File

@ -222,7 +222,7 @@ void setup_state_vgmstream(VGMSTREAM* vgmstream) {
/*****************************************************************************/
void free_layout(VGMSTREAM* vgmstream) {
void render_free(VGMSTREAM* vgmstream) {
if (vgmstream->layout_type == layout_segmented) {
free_layout_segmented(vgmstream->layout_data);
@ -233,7 +233,7 @@ void free_layout(VGMSTREAM* vgmstream) {
}
}
void reset_layout(VGMSTREAM* vgmstream) {
void render_reset(VGMSTREAM* vgmstream) {
if (vgmstream->layout_type == layout_segmented) {
reset_layout_segmented(vgmstream->layout_data);

View File

@ -3,8 +3,8 @@
#include "../vgmstream.h"
void free_layout(VGMSTREAM* vgmstream);
void reset_layout(VGMSTREAM* vgmstream);
void render_free(VGMSTREAM* vgmstream);
void render_reset(VGMSTREAM* vgmstream);
int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream);

View File

@ -14,7 +14,7 @@ static void seek_force_loop(VGMSTREAM* vgmstream, int loop_count) {
/* pretend decoder reached loop end so state is set to loop start */
vgmstream->loop_count = loop_count - 1; /* seeking to first loop must become ++ > 0 */
vgmstream->current_sample = vgmstream->loop_end_sample;
vgmstream_do_loop(vgmstream);
decode_do_loop(vgmstream);
}
static void seek_force_decode(VGMSTREAM* vgmstream, int samples) {

View File

@ -116,7 +116,7 @@ static const char* extension_list[] = {
"bk2",
"bkr", //txth/reserved [P.N.03 (GC), Viewtiful Joe (GC)]
"blk",
"bmdx",
"bmdx", //fake extension (to be removed?)
"bms",
"bnk",
"bnm",

View File

@ -11,13 +11,13 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
int samples_written = 0;
int frame_size, samples_per_frame, samples_this_block;
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = 0;
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -28,11 +28,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, readjust back to loop start values */
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -54,7 +54,7 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
break;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
@ -74,11 +74,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
block_update(vgmstream->next_block_offset,vgmstream);
/* update since these may change each block */
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;

View File

@ -9,19 +9,19 @@ void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vg
int samples_written = 0;
int samples_per_frame, samples_this_block;
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = vgmstream->num_samples; /* do all samples if possible */
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping */
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -19,20 +19,20 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
/* setup */
{
int frame_size_d = get_vgmstream_frame_size(vgmstream);
samples_per_frame_d = get_vgmstream_samples_per_frame(vgmstream);
int frame_size_d = decode_get_frame_size(vgmstream);
samples_per_frame_d = decode_get_samples_per_frame(vgmstream);
if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail;
samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d;
}
if (has_interleave_first) {
int frame_size_f = get_vgmstream_frame_size(vgmstream);
samples_per_frame_f = get_vgmstream_samples_per_frame(vgmstream); //todo samples per shortframe
int frame_size_f = decode_get_frame_size(vgmstream);
samples_per_frame_f = decode_get_samples_per_frame(vgmstream); //todo samples per shortframe
if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail;
samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f;
}
if (has_interleave_last) {
int frame_size_l = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame_l = get_vgmstream_samples_per_shortframe(vgmstream);
int frame_size_l = decode_get_shortframe_size(vgmstream);
samples_per_frame_l = decode_get_samples_per_shortframe(vgmstream);
if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail;
samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l;
}
@ -62,7 +62,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, restore standard interleave sizes */
if (has_interleave_first &&
@ -83,7 +83,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -25,12 +25,12 @@ void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM*
int layer, ch;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below) */
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
@ -105,7 +105,7 @@ void loop_layout_layered(VGMSTREAM* vgmstream, int32_t loop_sample) {
* calls to do_loop work (used in seek_vgmstream) */
if (data->layers[layer]->loop_flag) { /* mixing looping and non-looping layers is allowed */
data->layers[layer]->current_sample = data->layers[layer]->loop_end_sample; /* forces do loop */
vgmstream_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */
decode_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */
}
else {
/* needed when mixing non-looping layers and installing loop externally */

View File

@ -34,7 +34,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below, changes segments/state) */
samples_this_block = vgmstream_get_samples(data->segments[data->current_segment]);
mixing_info(data->segments[data->current_segment], NULL, &current_channels);
@ -60,7 +60,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, sample_count, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, sample_count, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */

View File

@ -13,11 +13,12 @@
#include "base/render.h"
#include "base/mixing.h"
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM* (*init_vgmstream_function)(STREAMFILE*));
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function);
/* list of metadata parser functions that will recognize files, used on init */
VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_adx,
init_vgmstream_brstm,
init_vgmstream_brwav,
@ -563,25 +564,25 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
#endif
};
#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
static const int init_vgmstream_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions);
/*****************************************************************************/
/* INIT/META */
/*****************************************************************************/
#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
/* internal version with all parameters */
static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
int i, fcns_count;
if (!sf)
return NULL;
fcns_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions);
/* try a series of formats, see which works */
for (i = 0; i < fcns_count; i++) {
for (int i = 0; i < init_vgmstream_count; i++) {
init_vgmstream_t init_vgmstream_function = init_vgmstream_functions[i];
/* call init function and see if valid VGMSTREAM was returned */
VGMSTREAM* vgmstream = (init_vgmstream_functions[i])(sf);
VGMSTREAM* vgmstream = init_vgmstream_function(sf);
if (!vgmstream)
continue;
@ -614,7 +615,7 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
/* test if candidate for dual stereo */
if (vgmstream->channels == 1 && vgmstream->allow_dual_stereo == 1) {
try_dual_file_stereo(vgmstream, sf, init_vgmstream_functions[i]);
try_dual_file_stereo(vgmstream, sf, init_vgmstream_function);
}
/* clean as loops are readable metadata but loop fields may contain garbage
@ -714,9 +715,9 @@ void reset_vgmstream(VGMSTREAM* vgmstream) {
* Otherwise hit_loop will be 0 and it will be copied over anyway when we
* really hit the loop start. */
reset_codec(vgmstream);
decode_reset(vgmstream);
reset_layout(vgmstream);
render_reset(vgmstream);
/* note that this does not reset the constituent STREAMFILES
* (vgmstream->ch[N].streamfiles' internal state, like internal offset, though shouldn't matter) */
@ -737,7 +738,7 @@ VGMSTREAM* allocate_vgmstream(int channel_count, int loop_flag) {
* - ch: config+state per channel, also modified by those
* - start_vgmstream: vgmstream clone copied on init_vgmstream and restored on reset_vgmstream
* - start_ch: ch clone copied on init_vgmstream and restored on reset_vgmstream
* - loop_ch: ch clone copied on loop start and restored on loop end (vgmstream_do_loop)
* - loop_ch: ch clone copied on loop start and restored on loop end (decode_do_loop)
* - codec/layout_data: custom state for complex codecs or layouts, handled externally
*
* Here we only create the basic structs to be filled, and only after init_vgmstream it
@ -799,10 +800,10 @@ void close_vgmstream(VGMSTREAM* vgmstream) {
if (!vgmstream)
return;
free_codec(vgmstream);
decode_free(vgmstream);
vgmstream->codec_data = NULL;
free_layout(vgmstream);
render_free(vgmstream);
vgmstream->layout_data = NULL;
@ -915,7 +916,7 @@ void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target) {
/* See if there is a second file which may be the second channel, given an already opened mono vgmstream.
* If a suitable file is found, open it and change opened_vgmstream to a stereo vgmstream. */
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM*(*init_vgmstream_function)(STREAMFILE*)) {
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function) {
/* filename search pairs for dual file stereo */
static const char* const dfs_pairs[][2] = {
{"L","R"}, /* most common in .dsp and .vag */