Add TXTH hist_offset for DSP

This commit is contained in:
bnnm 2019-09-14 12:38:49 +02:00
parent 0fe6f3c31e
commit 48d3690d81
2 changed files with 78 additions and 26 deletions

View File

@ -58,11 +58,12 @@ The above may be combined with math operations (+-*/): `(key) = (number) (op) (o
### KEYS
#### CODEC [REQUIRED]
Sets codec used to encode the data. Accepted codec strings:
Sets codec used to encode the data. Some codecs need interleave or other config
as explained below, but often will use default values. Accepted codec strings:
```
# - PSX PlayStation ADPCM
# * For many PS1/PS2/PS3 games
# * Interleave is multiple of 0x10, often +0x1000
# * Interleave is multiple of 0x10 (default), often +0x1000
# - PSX_bf PlayStation ADPCM with bad flags
# * Variation with garbage data, for rare PS2 games
# - XBOX Xbox IMA ADPCM (mono/stereo)
@ -70,18 +71,19 @@ Sets codec used to encode the data. Accepted codec strings:
# * Special interleave is multiple of 0x24 (mono) or 0x48 (stereo)
# - DSP|NGC_DSP Nintendo GameCube ADPCM
# * For many GC/Wii/3DS games
# * Interleave is multiple of 0x08, often +0x1000
# * Interleave is multiple of 0x08 (default), often +0x1000
# * Must set decoding coefficients (coef_offset/spacing/etc)
# * Should set ADPCM state (hist_offset/spacing/etc)
# - DTK|NGC_DTK Nintendo ADP/DTK ADPCM
# * For rare GC games
# - PCM16LE PCM 16-bit little endian
# * For many games (usually on PC)
# * Interleave is multiple of 0x2
# * Interleave is multiple of 0x2 (default)
# - PCM16BE PCM 16-bit big endian
# * Variation for certain consoles (GC/Wii/PS3/X360/etc)
# - PCM8 PCM 8-bit signed
# * For some games (usually on PC)
# * Interleave is multiple of 0x1
# * Interleave is multiple of 0x1 (default)
# - PCM8_U PCM 8-bit unsigned
# * Variation with modified encoding
# - PCM8_U_int PCM 8-bit unsigned (interleave block)
@ -110,13 +112,14 @@ Sets codec used to encode the data. Accepted codec strings:
# - ATRAC3 Sony ATRAC3
# * For some PS2 and PS3 games
# * Interleave (frame size) can be 0x60/0x98/0xC0 * channels [required]
# * Should set skip_samples (more than 1024 but varies)
# * Should set skip_samples (more than 1024+69 but varies)
# - ATRAC3PLUS Sony ATRAC3plus
# * For many PSP games and rare PS3 games
# * Interleave (frame size) can be: [required]
# Mono: 0x0118|0178|0230|02E8
# Stereo: 0x0118|0178|0230|02E8|03A8|0460|05D0|0748|0800
# * Should set skip_samples (more than 2048 but varies)
# 6/8 channels: multiple of one of the above
# * Should set skip_samples (more than 2048+184 but varies)
# - XMA1 Microsoft XMA1
# * For early X360 games
# - XMA2 Microsoft XMA2
@ -291,7 +294,7 @@ skip_samples = (value)
#### DSP DECODING COEFFICIENTS [REQUIRED for DSP]
DSP needs a "coefs" list to decode correctly. These are 8*2 16-bit values per channel, starting from `coef_offset`.
Usually each channel uses its own list, so we can set the separation per channel, usually 0x20 (16 values * 2 bytes). So channel N coefs are read at `coef_offset + coef_spacing * N`
Usually each channel uses its own list, so we may need to set separation per channel, usually 0x20 (16 values * 2 bytes). So channel N coefs are read at `coef_offset + coef_spacing * N`
Those 16-bit coefs can be little or big endian (usually BE), set `coef_endianness` directly or in an offset value where ´0=LE, >0=BE´.
@ -303,6 +306,22 @@ coef_endianness = BE|LE|(value)
coef_table = (string)
```
#### ADPCM STATE
Some ADPCM codecs need to set up their initial or "history" state, normally one or two 16-bit PCM samples per channel, starting from `hist_offset`.
Usually each channel uses its own state, so we may need to set separation per channel.
State values can be little or big endian (usually BE for DSP), set `hist_endianness` directly or in an offset value where ´0=LE, >0=BE´.
Normally audio starts with silence or hist samples are set to zero and can be ignored, but it does affect a bit resulting output.
Currently used by DSP.
```
hist_offset = (value)
hist_spacing = (value)
hist_endianness = BE|LE|(value)
```
#### HEADER/BODY SETTINGS
Changes internal header/body representation to external files.

View File

@ -81,6 +81,11 @@ typedef struct {
int coef_table_set;
uint8_t coef_table[0x02*16 * 16]; /* reasonable max */
int hist_set;
uint32_t hist_offset;
uint32_t hist_spacing;
uint32_t hist_big_endian;
int num_samples_data_size;
int target_subsong;
@ -378,29 +383,41 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
}
/* get coefs */
for (i = 0; i < vgmstream->channels; i++) {
{
int16_t (*read_16bit)(off_t , STREAMFILE*) = txth.coef_big_endian ? read_16bitBE : read_16bitLE;
int16_t (*get_16bit)(uint8_t * p) = txth.coef_big_endian ? get_16bitBE : get_16bitLE;
/* normal/split coefs */
if (txth.coef_mode == 0) { /* normal mode */
for (j = 0; j < 16; j++) {
int16_t coef;
if (txth.coef_table_set)
coef = get_16bit(txth.coef_table + i*txth.coef_spacing + j*2);
else
coef = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2, txth.streamHead);
vgmstream->ch[i].adpcm_coef[j] = coef;
for (i = 0; i < vgmstream->channels; i++) {
if (txth.coef_mode == 0) { /* normal coefs */
for (j = 0; j < 16; j++) {
int16_t coef;
if (txth.coef_table_set)
coef = get_16bit(txth.coef_table + i*txth.coef_spacing + j*2);
else
coef = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2, txth.streamHead);
vgmstream->ch[i].adpcm_coef[j] = coef;
}
}
else { /* split coefs */
goto fail; //IDK what is this
/*
for (j = 0; j < 8; j++) {
vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, txth.streamHead);
vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, txth.streamHead);
}
*/
}
}
else { /* split coefs */
goto fail; //IDK what is this
/*
for (j = 0; j < 8; j++) {
vgmstream->ch[i].adpcm_coef[j*2] = read_16bit(genh.coef_offset + i*genh.coef_spacing + j*2, txth.streamHead);
vgmstream->ch[i].adpcm_coef[j*2+1] = read_16bit(genh.coef_split_offset + i*genh.coef_split_spacing + j*2, txth.streamHead);
}
*/
}
/* get hist */
if (txth.hist_set) {
int16_t (*read_16bit)(off_t , STREAMFILE*) = txth.hist_big_endian ? read_16bitBE : read_16bitLE;
for (i = 0; i < vgmstream->channels; i++) {
off_t offset = txth.hist_offset + i*txth.hist_spacing;
vgmstream->ch[i].adpcm_history1_16 = read_16bit(offset + 0x00, txth.streamHead);
vgmstream->ch[i].adpcm_history2_16 = read_16bit(offset + 0x02, txth.streamHead);
}
}
@ -1051,6 +1068,22 @@ static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char
txth->coef_table_set = 1;
}
/* HIST */
else if (is_string(key,"hist_offset")) {
if (!parse_num(txth->streamHead,txth,val, &txth->hist_offset)) goto fail;
txth->hist_set = 1;
}
else if (is_string(key,"hist_spacing")) {
if (!parse_num(txth->streamHead,txth,val, &txth->hist_spacing)) goto fail;
}
else if (is_string(key,"hist_endianness")) {
if (is_string(val, "BE"))
txth->hist_big_endian = 1;
else if (is_string(val, "LE"))
txth->hist_big_endian = 0;
else if (!parse_num(txth->streamHead,txth,val, &txth->hist_big_endian)) goto fail;
}
/* SUBSONGS */
else if (is_string(key,"subsong_count")) {
if (!parse_num(txth->streamHead,txth,val, &txth->subsong_count)) goto fail;