mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Add mu-Law with internal interleave decoder
This is needed for blocked layout, as it can't do normal interleave. Probably could be fixed in the future to remove several superfluous _int/block decoders
This commit is contained in:
parent
98c5f0a65d
commit
2f9c16ae9b
@ -65,6 +65,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_ulaw_int(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,69 +87,83 @@ void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int chan
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int sign, segment, quantization, sample;
|
||||
static int expand_ulaw(uint8_t ulawbyte) {
|
||||
int sign, segment, quantization, new_sample;
|
||||
const int bias = 0x84;
|
||||
|
||||
ulawbyte = ~ulawbyte; /* stored in complement */
|
||||
sign = (ulawbyte & 0x80);
|
||||
segment = (ulawbyte & 0x70) >> 4; /* exponent */
|
||||
quantization = ulawbyte & 0x0F; /* mantissa */
|
||||
|
||||
new_sample = (quantization << 3) + bias; /* add bias */
|
||||
new_sample <<= segment;
|
||||
new_sample = (sign) ? (bias - new_sample) : (new_sample - bias); /* remove bias */
|
||||
|
||||
#if 0 // the above follows Sun's implementation, but this works too
|
||||
{
|
||||
static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; /* precalcs from bias */
|
||||
new_sample = exp_lut[segment] + (quantization << (segment + 3));
|
||||
if (sign != 0) new_sample = -new_sample;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new_sample;
|
||||
}
|
||||
|
||||
/* 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, sample_count;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t ulawbyte = read_8bit(stream->offset+i,stream->streamfile);
|
||||
|
||||
ulawbyte = ~ulawbyte; /* stored in complement */
|
||||
sign = (ulawbyte & 0x80);
|
||||
segment = (ulawbyte & 0x70) >> 4; /* exponent */
|
||||
quantization = ulawbyte & 0x0F; /* mantissa */
|
||||
|
||||
sample = (quantization << 3) + bias; /* add bias */
|
||||
sample <<= segment;
|
||||
sample = (sign) ? (bias - sample) : (sample - bias); /* remove bias */
|
||||
|
||||
#if 0 // the above follows Sun's implementation, but this works too
|
||||
{
|
||||
static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; /* precalcs from bias */
|
||||
sample = exp_lut[segment] + (quantization << (segment + 3));
|
||||
if (sign != 0) sample = -sample;
|
||||
}
|
||||
#endif
|
||||
|
||||
outbuf[sample_count] = sample;
|
||||
outbuf[sample_count] = expand_ulaw(ulawbyte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void decode_ulaw_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t ulawbyte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
|
||||
outbuf[sample_count] = expand_ulaw(ulawbyte);
|
||||
}
|
||||
}
|
||||
|
||||
static int expand_alaw(uint8_t alawbyte) {
|
||||
int sign, segment, quantization, new_sample;
|
||||
|
||||
alawbyte ^= 0x55;
|
||||
sign = (alawbyte & 0x80);
|
||||
segment = (alawbyte & 0x70) >> 4; /* exponent */
|
||||
quantization = alawbyte & 0x0F; /* mantissa */
|
||||
|
||||
new_sample = (quantization << 4);
|
||||
switch (segment) {
|
||||
case 0:
|
||||
new_sample += 8;
|
||||
break;
|
||||
case 1:
|
||||
new_sample += 0x108;
|
||||
break;
|
||||
default:
|
||||
new_sample += 0x108;
|
||||
new_sample <<= segment - 1;
|
||||
break;
|
||||
}
|
||||
new_sample = (sign) ? new_sample : -new_sample;
|
||||
|
||||
return new_sample;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
int i, sample_count;
|
||||
|
||||
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;
|
||||
outbuf[sample_count] = expand_alaw(alawbyte);;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,6 +423,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"},
|
||||
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave (block)"},
|
||||
{coding_ULAW, "8-bit u-Law"},
|
||||
{coding_ULAW_int, "8-bit u-Law with 1 byte interleave (block)"},
|
||||
{coding_ALAW, "8-bit a-Law"},
|
||||
{coding_PCMFLOAT, "32-bit float PCM"},
|
||||
|
||||
|
@ -1002,6 +1002,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_PCM8_SB_int:
|
||||
case coding_PCM8_U_int:
|
||||
case coding_ULAW:
|
||||
case coding_ULAW_int:
|
||||
case coding_ALAW:
|
||||
case coding_PCMFLOAT:
|
||||
return 1;
|
||||
@ -1157,6 +1158,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_PCM8_SB_int:
|
||||
case coding_PCM8_U_int:
|
||||
case coding_ULAW:
|
||||
case coding_ULAW_int:
|
||||
case coding_ALAW:
|
||||
return 1;
|
||||
case coding_PCMFLOAT:
|
||||
@ -1405,6 +1407,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_ULAW_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_ulaw_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
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,
|
||||
|
@ -80,12 +80,13 @@ typedef enum {
|
||||
coding_PCM16_int, /* 16-bit PCM with sample-level interleave (for blocks) */
|
||||
|
||||
coding_PCM8, /* 8-bit PCM */
|
||||
coding_PCM8_int, /* 8-Bit PCM with sample-level interleave (for blocks) */
|
||||
coding_PCM8_int, /* 8-bit PCM with sample-level interleave (for blocks) */
|
||||
coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */
|
||||
coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave (for blocks) */
|
||||
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave (for blocks) */
|
||||
|
||||
coding_ULAW, /* 8-bit u-Law (non-linear PCM) */
|
||||
coding_ULAW_int, /* 8-bit u-Law (non-linear PCM) with sample-level interleave (for blocks) */
|
||||
coding_ALAW, /* 8-bit a-Law (non-linear PCM) */
|
||||
|
||||
coding_PCMFLOAT, /* 32 bit float PCM */
|
||||
|
Loading…
x
Reference in New Issue
Block a user