mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 08:20:54 +01:00
Add AL2 meta + A-law decoder [Conquest of Elysium 3 (PC)]
This commit is contained in:
parent
874694bd0a
commit
c770490b3d
@ -39,6 +39,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("AIFCL", aifcl);
|
|||||||
//"aiff", //common
|
//"aiff", //common
|
||||||
VGMSTREAM_DECLARE_FILE_TYPE("AIX", aix);
|
VGMSTREAM_DECLARE_FILE_TYPE("AIX", aix);
|
||||||
VGMSTREAM_DECLARE_FILE_TYPE("AKB", akb);
|
VGMSTREAM_DECLARE_FILE_TYPE("AKB", akb);
|
||||||
|
VGMSTREAM_DECLARE_FILE_TYPE("AL2", al2);
|
||||||
VGMSTREAM_DECLARE_FILE_TYPE("AMTS", amts);
|
VGMSTREAM_DECLARE_FILE_TYPE("AMTS", amts);
|
||||||
VGMSTREAM_DECLARE_FILE_TYPE("AO", ao);
|
VGMSTREAM_DECLARE_FILE_TYPE("AO", ao);
|
||||||
VGMSTREAM_DECLARE_FILE_TYPE("AS4", as4);
|
VGMSTREAM_DECLARE_FILE_TYPE("AS4", as4);
|
||||||
|
@ -64,6 +64,7 @@ void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
|
|||||||
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
void decode_alaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
|
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
|
||||||
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
|
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int chan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decodes u-law (ITU G.711 non-linear PCM) */
|
/* decodes u-law (ITU G.711 non-linear PCM), from g711.c */
|
||||||
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||||
int i;
|
int i;
|
||||||
int32_t sample_count;
|
int32_t sample_count;
|
||||||
@ -119,6 +119,40 @@ void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* decodes a-law (ITU G.711 non-linear PCM), from g711.c */
|
||||||
|
void decode_alaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||||
|
int i;
|
||||||
|
int32_t sample_count;
|
||||||
|
int sign, segment, quantization, sample;
|
||||||
|
|
||||||
|
|
||||||
|
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||||
|
uint8_t alawbyte = read_8bit(stream->offset+i,stream->streamfile);
|
||||||
|
|
||||||
|
alawbyte ^= 0x55;
|
||||||
|
sign = (alawbyte & 0x80);
|
||||||
|
segment = (alawbyte & 0x70) >> 4; /* exponent */
|
||||||
|
quantization = alawbyte & 0x0F; /* mantissa */
|
||||||
|
|
||||||
|
sample = (quantization << 4);
|
||||||
|
switch (segment) {
|
||||||
|
case 0:
|
||||||
|
sample += 8;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sample += 0x108;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sample += 0x108;
|
||||||
|
sample <<= segment - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sample = (sign) ? sample : -sample;
|
||||||
|
|
||||||
|
outbuf[sample_count] = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian) {
|
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian) {
|
||||||
int i, sample_count;
|
int i, sample_count;
|
||||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
|
||||||
|
@ -32,6 +32,7 @@ static const char* extension_list[] = {
|
|||||||
//"aiff", //common
|
//"aiff", //common
|
||||||
"aix",
|
"aix",
|
||||||
"akb",
|
"akb",
|
||||||
|
"al2",
|
||||||
"amts", //fake extension (to be removed)
|
"amts", //fake extension (to be removed)
|
||||||
"ao", //txth/reserved [Cloudphobia (PC)]
|
"ao", //txth/reserved [Cloudphobia (PC)]
|
||||||
"as4",
|
"as4",
|
||||||
@ -410,6 +411,7 @@ static const coding_info coding_info_list[] = {
|
|||||||
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"},
|
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"},
|
||||||
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
|
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
|
||||||
{coding_ULAW, "8-bit u-Law"},
|
{coding_ULAW, "8-bit u-Law"},
|
||||||
|
{coding_ALAW, "8-bit a-Law"},
|
||||||
{coding_PCMFLOAT, "32-bit float PCM"},
|
{coding_PCMFLOAT, "32-bit float PCM"},
|
||||||
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
|
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
|
||||||
{coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"},
|
{coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"},
|
||||||
@ -890,6 +892,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_EA_SNU, "Electronic Arts SNU header"},
|
{meta_EA_SNU, "Electronic Arts SNU header"},
|
||||||
{meta_AWC, "Rockstar AWC header"},
|
{meta_AWC, "Rockstar AWC header"},
|
||||||
{meta_NSW_OPUS, ".OPUS header"},
|
{meta_NSW_OPUS, ".OPUS header"},
|
||||||
|
{meta_PC_AL2, "Illwinter Game Design AL2 raw header"},
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||||
|
@ -658,6 +658,10 @@
|
|||||||
RelativePath=".\meta\pc_adp.c"
|
RelativePath=".\meta\pc_adp.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\pc_al2.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\pc_mxst.c"
|
RelativePath=".\meta\pc_mxst.c"
|
||||||
>
|
>
|
||||||
|
@ -288,6 +288,7 @@
|
|||||||
<ClCompile Include="meta\ogl.c" />
|
<ClCompile Include="meta\ogl.c" />
|
||||||
<ClCompile Include="meta\otm.c" />
|
<ClCompile Include="meta\otm.c" />
|
||||||
<ClCompile Include="meta\p3d.c" />
|
<ClCompile Include="meta\p3d.c" />
|
||||||
|
<ClCompile Include="meta\pc_al2.c" />
|
||||||
<ClCompile Include="meta\pc_mxst.c" />
|
<ClCompile Include="meta\pc_mxst.c" />
|
||||||
<ClCompile Include="meta\pc_smp.c" />
|
<ClCompile Include="meta\pc_smp.c" />
|
||||||
<ClCompile Include="meta\pc_sob.c" />
|
<ClCompile Include="meta\pc_sob.c" />
|
||||||
|
@ -391,6 +391,9 @@
|
|||||||
<ClCompile Include="meta\p3d.c">
|
<ClCompile Include="meta\p3d.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\pc_al2.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\pc_mxst.c">
|
<ClCompile Include="meta\pc_mxst.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -684,4 +684,6 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
|
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
40
src/meta/pc_al2.c
Normal file
40
src/meta/pc_al2.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
/* AL" - headerless a-law, found in Conquest of Elysium 3 (PC) */
|
||||||
|
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset;
|
||||||
|
int loop_flag = 0, channel_count;
|
||||||
|
|
||||||
|
|
||||||
|
if ( !check_extensions(streamFile,"al2"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
channel_count = 2;
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = 22050;
|
||||||
|
vgmstream->coding_type = coding_ALAW;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = 0x01;
|
||||||
|
vgmstream->meta_type = meta_PC_AL2;
|
||||||
|
vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), channel_count, 8);
|
||||||
|
if (loop_flag) {
|
||||||
|
vgmstream->loop_start_sample = 0;
|
||||||
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_offset = 0;
|
||||||
|
|
||||||
|
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -370,6 +370,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
|||||||
init_vgmstream_ea_snu,
|
init_vgmstream_ea_snu,
|
||||||
init_vgmstream_awc,
|
init_vgmstream_awc,
|
||||||
init_vgmstream_nsw_opus,
|
init_vgmstream_nsw_opus,
|
||||||
|
init_vgmstream_pc_al2,
|
||||||
|
|
||||||
init_vgmstream_txth, /* should go at the end (lower priority) */
|
init_vgmstream_txth, /* should go at the end (lower priority) */
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
@ -982,6 +983,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
|||||||
case coding_PCM8_SB_int:
|
case coding_PCM8_SB_int:
|
||||||
case coding_PCM8_U_int:
|
case coding_PCM8_U_int:
|
||||||
case coding_ULAW:
|
case coding_ULAW:
|
||||||
|
case coding_ALAW:
|
||||||
case coding_PCMFLOAT:
|
case coding_PCMFLOAT:
|
||||||
return 1;
|
return 1;
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
@ -1141,6 +1143,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
|||||||
case coding_PCM8_SB_int:
|
case coding_PCM8_SB_int:
|
||||||
case coding_PCM8_U_int:
|
case coding_PCM8_U_int:
|
||||||
case coding_ULAW:
|
case coding_ULAW:
|
||||||
|
case coding_ALAW:
|
||||||
return 1;
|
return 1;
|
||||||
case coding_PCMFLOAT:
|
case coding_PCMFLOAT:
|
||||||
return 4;
|
return 4;
|
||||||
@ -1379,6 +1382,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
|||||||
samples_to_do);
|
samples_to_do);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case coding_ALAW:
|
||||||
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
decode_alaw(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||||
|
vgmstream->channels,vgmstream->samples_into_block,
|
||||||
|
samples_to_do);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case coding_PCMFLOAT:
|
case coding_PCMFLOAT:
|
||||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
decode_pcmfloat(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
decode_pcmfloat(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||||
|
@ -86,6 +86,7 @@ typedef enum {
|
|||||||
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */
|
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */
|
||||||
|
|
||||||
coding_ULAW, /* 8-bit u-Law (non-linear PCM) */
|
coding_ULAW, /* 8-bit u-Law (non-linear PCM) */
|
||||||
|
coding_ALAW, /* 8-bit a-Law (non-linear PCM) */
|
||||||
|
|
||||||
coding_PCMFLOAT, /* 32 bit float PCM */
|
coding_PCMFLOAT, /* 32 bit float PCM */
|
||||||
|
|
||||||
@ -352,7 +353,7 @@ typedef enum {
|
|||||||
meta_RWX, /* Air Force Delta Storm (XBOX) */
|
meta_RWX, /* Air Force Delta Storm (XBOX) */
|
||||||
meta_XWB, /* Microsoft XACT framework (Xbox, X360, Windows) */
|
meta_XWB, /* Microsoft XACT framework (Xbox, X360, Windows) */
|
||||||
meta_PS2_XA30, /* Driver - Parallel Lines (PS2) */
|
meta_PS2_XA30, /* Driver - Parallel Lines (PS2) */
|
||||||
meta_MUSC, /* Spyro Games, possibly more */
|
meta_MUSC, /* Krome PS2 games */
|
||||||
meta_MUSX_V004, /* Spyro Games, possibly more */
|
meta_MUSX_V004, /* Spyro Games, possibly more */
|
||||||
meta_MUSX_V005, /* Spyro Games, possibly more */
|
meta_MUSX_V005, /* Spyro Games, possibly more */
|
||||||
meta_MUSX_V006, /* Spyro Games, possibly more */
|
meta_MUSX_V006, /* Spyro Games, possibly more */
|
||||||
@ -627,6 +628,7 @@ typedef enum {
|
|||||||
meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */
|
meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */
|
||||||
meta_AWC, /* Rockstar AWC (GTA5, RDR) */
|
meta_AWC, /* Rockstar AWC (GTA5, RDR) */
|
||||||
meta_NSW_OPUS, /* Lego City Undercover (Switch) */
|
meta_NSW_OPUS, /* Lego City Undercover (Switch) */
|
||||||
|
meta_PC_AL2, /* Conquest of Elysium 3 (PC) */
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||||
|
Loading…
Reference in New Issue
Block a user