Add TXTH codec "YMZ"

This commit is contained in:
bnnm 2022-10-09 20:29:10 +02:00
parent cc10e2e116
commit 63bc8043ab
5 changed files with 66 additions and 39 deletions

View File

@ -74,9 +74,7 @@ as explained below, but often will use default values. Accepted codec strings:
# - HEVAG Vita/PS4 ADPCM
# * For some Vita/PS4 games
# * Interleave is multiple of 0x10 (default)
# - XBOX Xbox IMA ADPCM (mono/stereo)
# * For many XBOX games, and some PC games
# * Special interleave is multiple of 0x24 (mono) or 0x48 (stereo)
#
# - DSP|NGC_DSP Nintendo GameCube ADPCM
# * For many GC/Wii/3DS/Switch games
# * Interleave is multiple of 0x08 (default), often +0x1000
@ -84,6 +82,7 @@ as explained below, but often will use default values. Accepted codec strings:
# * 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 (default)
@ -102,27 +101,43 @@ as explained below, but often will use default values. Accepted codec strings:
# - PCM_FLOAT_LE PCM 32-bit float little endian
# * For few rare games [Ikinari Maou (Switch)]
# * Interleave is multiple of 0x4 (default)
#
# - IMA IMA ADPCM (mono/stereo)
# * For some PC games, and rarely consoles
# * Special interleave is multiple of 0x1, often +0x80
# - DVI_IMA IMA ADPCM (DVI order)
# * Variation with modified encoding
# - AICA Yamaha AICA ADPCM (mono/stereo)
# * For some Dreamcast games, and some arcade (Naomi) games
# * Special interleave is multiple of 0x1
# - APPLE_IMA4 Apple Quicktime IMA ADPCM
# * For some Mac/iOS games
# - XBOX Xbox IMA ADPCM (mono/stereo)
# * For many XBOX games, and some PC games
# * Special interleave is multiple of 0x24 (mono) or 0x48 (stereo)
# - MS_IMA Microsoft IMA ADPCM
# * For some PC games
# * Interleave (frame size) varies, often multiple of 0x100 [required]
# - APPLE_IMA4 Apple Quicktime IMA ADPCM
# * For some Mac/iOS games
# - IMA_HV High Voltage's IMA ADPCM
# * For some High Voltage Software PC games [NBA Hangtime (PC), NHL Open Ice (PC)]
#
# - MSADPCM Microsoft ADPCM (mono/stereo)
# * For some PC games
# * Interleave (frame size) varies, often multiple of 0x100 [required]
#
# - AICA Yamaha AICA ADPCM (mono/stereo)
# * For some Dreamcast games, and some arcade (Naomi) games
# * Special interleave is multiple of 0x1
# - YMZ Yamaha YMZ263B/YMZ280B ADPCM (mono/stereo)
# * Variation of AICA
# * For rare arcade games [VJ: Visual & Music Slap (AC)]
# - CP_YM Capcom's Yamaha ADPCM
# * For rare Saturn games [Marvel Super Heroes vs Street Fighter (SAT)]
#
# - SDX2 Squareroot-delta-exact 8-bit DPCM
# * For many 3DO games
#
# - MPEG MPEG Audio Layer file (MP1/2/3)
# * For some games (usually PC/PS3)
# * May set skip_samples (MP2: around 240 or 480, MP3: around 1152)
#
# - ATRAC3 Sony ATRAC3
# * For some PS2 and PS3 games
# * Interleave (frame size) can be 0x60/0x98/0xC0 * channels [required]
@ -134,45 +149,45 @@ as explained below, but often will use default values. Accepted codec strings:
# Stereo: 0x0118|0178|0230|02E8|03A8|0460|05D0|0748|0800
# 6/8 channels: multiple of one of the above
# * Should set skip_samples (around 2048+184 but varies)
#
# - XMA1 Microsoft XMA1
# * For early X360 games
# - XMA2 Microsoft XMA2
# * For later X360 games
# - FFMPEG Any headered FFmpeg format
# * For uncommon games
# * May set skip_samples
#
# - AC3 AC3/SPDIF
# * For few PS2 games
# * Should set skip_samples (around 256 but varies)
# - PCFX PC-FX ADPCM
# * For many PC-FX games
# * Interleave is multiple of 0x1, often +0x8000
# * Sample rate may be ~31468/~15734/~10489/~7867
# - PCM4 PCM 4-bit signed
# * For early consoles
# - PCM4_U PCM 4-bit unsigned
# * Variation with modified encoding
# - AAC Advanced Audio Coding (raw outside .mp4)
# * For some 3DS games and many iOS games
# * Should set skip_samples (typically 1024 but varies, 2112 is also common)
# - FFMPEG Any headered FFmpeg format
# * For uncommon games
# * May set skip_samples
#
# - OKI16 OKI ADPCM with 16-bit output (not VOX/Dialogic 12-bit)
# * For rare PS2 games [Sweet Legacy (PS2), Hooligan (PS2)]
# - OKI4S OKI ADPCM with 16-bit output and adjusted tables
# * For later Konami arcade games [Gitadora (AC), Metal Gear Arcade (AC)]
# - AAC Advanced Audio Coding (raw outside .mp4)
# * For some 3DS games and many iOS games
# * Should set skip_samples (typically 1024 but varies, 2112 is also common)
# - PCFX PC-FX ADPCM
# * For many PC-FX games
# * Interleave is multiple of 0x1, often +0x8000
# * Sample rate may be ~31468/~15734/~10489/~7867
#
# - PCM4 PCM 4-bit signed
# * For early consoles
# - PCM4_U PCM 4-bit unsigned
# * Variation with modified encoding
# - TGC Tiger Game.com 4-bit ADPCM
# * For Tiger Game.com games
# - ASF Argonaut ASF ADPCM
# * For rare Argonaut games [Croc (SAT)]
# - EAXA Electronic Arts EA-XA ADPCM
# * For rare EA games [Harry Potter and the Chamber of Secrets (PC)]
# - XA CD-XA ADPCM (ISO 2048 mode1/data streams without subchannels)
# - XA CD-XA ADPCM (ISO 2048 mode1 streams without subchannel data)
# * For rare Saturn and PS2 games [Phantasy Star Collection (SAT), Fantavision (PS2), EA SAT videos]
# - XA_EA Electronic Arts XA ADPCM variation
# * For rare Saturn games [EA SAT videos]
# - CP_YM Capcom's Yamaha ADPCM
# * For rare Saturn games [Marvel Super Heroes vs Street Fighter (SAT)]
# - IMA_HV High Voltage's IMA ADPCM
# * For some High Voltage Software PC games [NBA Hangtime (PC), NHL Open Ice (PC)]
codec = (codec string)
```

View File

@ -171,7 +171,7 @@ int msadpcm_check_coefs(STREAMFILE* sf, uint32_t offset);
/* yamaha_decoder */
void decode_aica(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_aica(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
void decode_cp_ym(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_aska(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, size_t frame_size);
void decode_nxap(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

View File

@ -44,12 +44,12 @@ static void yamaha_adpcmb_expand_nibble(uint8_t byte, int shift, int32_t* hist1,
/* Yamaha AICA expand, slightly filtered vs "ACM" Yamaha ADPCM, same as Creative ADPCM
* (some info from https://github.com/vgmrips/vgmplay, https://wiki.multimedia.cx/index.php/Creative_ADPCM) */
static void yamaha_aica_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) {
static void yamaha_aica_expand_nibble(uint8_t byte, int shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) {
int code, delta, sample;
*hist1 = *hist1 * 254 / 256; /* hist filter is vital to get correct waveform but not done in many emus */
code = ((read_8bit(byte_offset,stream->streamfile) >> nibble_shift))&0xf;
code = (byte >> shift) & 0xf;
delta = (*step_size * scale_delta[code]) / 8; /* 'mul' IMA with table (not sure if part of encoder) */
sample = *hist1 + delta;
@ -108,8 +108,8 @@ static void yamaha_capcom_expand_nibble(uint8_t byte, int shift, int32_t* hist1,
*/
/* Yamaha AICA ADPCM (also used in YMZ280B with high nibble first) */
void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo) {
/* Yamaha AICA ADPCM (also used in YMZ263B/YMZ280B with high nibble first) */
void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first) {
int i, sample_count = 0;
int16_t out_sample;
int32_t hist1 = stream->adpcm_history1_16;
@ -120,14 +120,16 @@ void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
if (step_size > 0x6000) step_size = 0x6000;
for (i = first_sample; i < first_sample + samples_to_do; i++) {
off_t byte_offset = is_stereo ?
uint8_t byte;
off_t offset = is_stereo ?
stream->offset + i : /* stereo: one nibble per channel */
stream->offset + i/2; /* mono: consecutive nibbles */
int nibble_shift = is_stereo ?
(!(channel&1) ? 0:4) : /* even = low/L, odd = high/R */
(!(i&1) ? 0:4); /* low nibble first */
int shift = is_high_first ?
is_stereo ? (!(channel&1) ? 4:0) : (!(i&1) ? 4:0) : /* even = high/L, odd = low/R */
is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low/L, odd = high/L */
yamaha_aica_expand_nibble(stream, byte_offset, nibble_shift, &hist1, &step_size, &out_sample);
byte = read_u8(offset, stream->streamfile);
yamaha_aica_expand_nibble(byte, shift, &hist1, &step_size, &out_sample);
outbuf[sample_count] = out_sample;
sample_count += channelspacing;
}

View File

@ -1354,10 +1354,11 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
case coding_AICA:
case coding_AICA_int: {
int is_stereo = (vgmstream->channels > 1 && vgmstream->coding_type == coding_AICA);
int is_high_first = vgmstream->codec_config == 1;
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_aica(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch,
is_stereo);
is_stereo, is_high_first);
}
break;
}

View File

@ -51,6 +51,7 @@ typedef enum {
IMA_HV,
PCM8_SB,
HEVAG,
YMZ,
UNKNOWN = 99,
} txth_codec_t;
@ -258,6 +259,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case MPEG: coding = coding_MPEG_layer3; break; /* we later find out exactly which */
#endif
case IMA: coding = coding_IMA; break;
case YMZ:
case AICA: coding = coding_AICA; break;
case MSADPCM: coding = coding_MSADPCM; break;
case NGC_DSP: coding = coding_NGC_DSP; break;
@ -386,7 +388,12 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
vgmstream->codec_config = txth.codec_mode;
}
vgmstream->allow_dual_stereo = 1; /* AICA and PSX */
if (txth.codec == YMZ) {
vgmstream->codec_config = 1; /* CONFIG_HIGH_NIBBLE */
}
//TODO recheck and use only for needed cases
vgmstream->allow_dual_stereo = 1; /* known to be used in: PSX, AICA, YMZ */
break;
case coding_PCFX:
@ -955,6 +962,7 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) {
else if (is_string(val,"MPEG")) return MPEG;
else if (is_string(val,"IMA")) return IMA;
else if (is_string(val,"AICA")) return AICA;
else if (is_string(val,"YMZ")) return YMZ;
else if (is_string(val,"MSADPCM")) return MSADPCM;
else if (is_string(val,"NGC_DSP")) return NGC_DSP;
else if (is_string(val,"DSP")) return NGC_DSP;
@ -2129,6 +2137,7 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) {
case IMA_HV:
return ima_bytes_to_samples(bytes, txth->channels);
case AICA:
case YMZ:
case CP_YM:
return yamaha_bytes_to_samples(bytes, txth->channels);
case PCFX: