mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +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
|
||||
VGMSTREAM_DECLARE_FILE_TYPE("AIX", aix);
|
||||
VGMSTREAM_DECLARE_FILE_TYPE("AKB", akb);
|
||||
VGMSTREAM_DECLARE_FILE_TYPE("AL2", al2);
|
||||
VGMSTREAM_DECLARE_FILE_TYPE("AMTS", amts);
|
||||
VGMSTREAM_DECLARE_FILE_TYPE("AO", ao);
|
||||
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(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);
|
||||
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) {
|
||||
int i;
|
||||
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) {
|
||||
int i, sample_count;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
|
||||
|
@ -32,6 +32,7 @@ static const char* extension_list[] = {
|
||||
//"aiff", //common
|
||||
"aix",
|
||||
"akb",
|
||||
"al2",
|
||||
"amts", //fake extension (to be removed)
|
||||
"ao", //txth/reserved [Cloudphobia (PC)]
|
||||
"as4",
|
||||
@ -410,6 +411,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"},
|
||||
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
|
||||
{coding_ULAW, "8-bit u-Law"},
|
||||
{coding_ALAW, "8-bit a-Law"},
|
||||
{coding_PCMFLOAT, "32-bit float PCM"},
|
||||
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
|
||||
{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_AWC, "Rockstar AWC header"},
|
||||
{meta_NSW_OPUS, ".OPUS header"},
|
||||
{meta_PC_AL2, "Illwinter Game Design AL2 raw header"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||
|
@ -658,6 +658,10 @@
|
||||
RelativePath=".\meta\pc_adp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\pc_al2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\pc_mxst.c"
|
||||
>
|
||||
|
@ -288,6 +288,7 @@
|
||||
<ClCompile Include="meta\ogl.c" />
|
||||
<ClCompile Include="meta\otm.c" />
|
||||
<ClCompile Include="meta\p3d.c" />
|
||||
<ClCompile Include="meta\pc_al2.c" />
|
||||
<ClCompile Include="meta\pc_mxst.c" />
|
||||
<ClCompile Include="meta\pc_smp.c" />
|
||||
<ClCompile Include="meta\pc_sob.c" />
|
||||
|
@ -391,6 +391,9 @@
|
||||
<ClCompile Include="meta\p3d.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\pc_al2.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\pc_mxst.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -684,4 +684,6 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile);
|
||||
|
||||
#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_awc,
|
||||
init_vgmstream_nsw_opus,
|
||||
init_vgmstream_pc_al2,
|
||||
|
||||
init_vgmstream_txth, /* should go at the end (lower priority) */
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
@ -982,6 +983,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_PCM8_SB_int:
|
||||
case coding_PCM8_U_int:
|
||||
case coding_ULAW:
|
||||
case coding_ALAW:
|
||||
case coding_PCMFLOAT:
|
||||
return 1;
|
||||
#ifdef VGM_USE_VORBIS
|
||||
@ -1141,6 +1143,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_PCM8_SB_int:
|
||||
case coding_PCM8_U_int:
|
||||
case coding_ULAW:
|
||||
case coding_ALAW:
|
||||
return 1;
|
||||
case coding_PCMFLOAT:
|
||||
return 4;
|
||||
@ -1379,6 +1382,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
samples_to_do);
|
||||
}
|
||||
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:
|
||||
for (chan=0;chan<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_ULAW, /* 8-bit u-Law (non-linear PCM) */
|
||||
coding_ALAW, /* 8-bit a-Law (non-linear PCM) */
|
||||
|
||||
coding_PCMFLOAT, /* 32 bit float PCM */
|
||||
|
||||
@ -352,7 +353,7 @@ typedef enum {
|
||||
meta_RWX, /* Air Force Delta Storm (XBOX) */
|
||||
meta_XWB, /* Microsoft XACT framework (Xbox, X360, Windows) */
|
||||
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_V005, /* 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_AWC, /* Rockstar AWC (GTA5, RDR) */
|
||||
meta_NSW_OPUS, /* Lego City Undercover (Switch) */
|
||||
meta_PC_AL2, /* Conquest of Elysium 3 (PC) */
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||
|
Loading…
Reference in New Issue
Block a user