2008-05-06 05:35:37 +02:00
|
|
|
#include "coding.h"
|
2008-03-03 22:38:11 +01:00
|
|
|
#include "../util.h"
|
|
|
|
|
2019-11-02 16:10:23 +01:00
|
|
|
static const int16_t afc_coefs[16][2] = {
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 2048, 0 },
|
|
|
|
{ 0, 2048 },
|
|
|
|
{ 1024, 1024 },
|
|
|
|
{ 4096,-2048 },
|
|
|
|
{ 3584,-1536 },
|
|
|
|
{ 3072,-1024 },
|
|
|
|
{ 4608,-2560 },
|
|
|
|
{ 4200,-2248 },
|
|
|
|
{ 4800,-2300 },
|
|
|
|
{ 5120,-3072 },
|
|
|
|
{ 2048,-2048 },
|
|
|
|
{ 1024,-1024 },
|
|
|
|
{-1024, 1024 },
|
|
|
|
{-1024, 0 },
|
|
|
|
{-2048, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
void decode_ngc_afc(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
|
|
|
uint8_t frame[0x09] = {0};
|
|
|
|
off_t frame_offset;
|
|
|
|
int i, frames_in, sample_count = 0;
|
|
|
|
size_t bytes_per_frame, samples_per_frame;
|
|
|
|
int index, scale, coef1, coef2;
|
2008-03-03 22:38:11 +01:00
|
|
|
int32_t hist1 = stream->adpcm_history1_16;
|
|
|
|
int32_t hist2 = stream->adpcm_history2_16;
|
|
|
|
|
|
|
|
|
2019-11-02 16:10:23 +01:00
|
|
|
/* external interleave, mono */
|
|
|
|
bytes_per_frame = 0x09;
|
|
|
|
samples_per_frame = (bytes_per_frame - 0x01) * 2; /* always 16 */
|
|
|
|
frames_in = first_sample / samples_per_frame;
|
|
|
|
|
|
|
|
/* parse frame header */
|
|
|
|
frame_offset = stream->offset + bytes_per_frame * frames_in;
|
|
|
|
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
|
|
|
|
scale = 1 << ((frame[0] >> 4) & 0xf);
|
|
|
|
index = (frame[0] & 0xf);
|
|
|
|
coef1 = afc_coefs[index][0];
|
|
|
|
coef2 = afc_coefs[index][1];
|
|
|
|
|
|
|
|
/* decode nibbles */
|
|
|
|
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
|
|
|
uint8_t nibbles = frame[0x01 + i/2];
|
|
|
|
int32_t sample;
|
|
|
|
|
|
|
|
sample = i&1 ? /* high nibble first */
|
|
|
|
get_low_nibble_signed(nibbles) :
|
|
|
|
get_high_nibble_signed(nibbles);
|
|
|
|
sample = ((sample * scale) << 11);
|
|
|
|
sample = (sample + coef1*hist1 + coef2*hist2) >> 11;
|
|
|
|
|
|
|
|
sample = clamp16(sample);
|
2008-03-03 22:38:11 +01:00
|
|
|
|
2019-11-02 16:10:23 +01:00
|
|
|
outbuf[sample_count] = sample;
|
|
|
|
sample_count += channelspacing;
|
2008-03-03 22:38:11 +01:00
|
|
|
|
|
|
|
hist2 = hist1;
|
2019-11-02 16:10:23 +01:00
|
|
|
hist1 = sample;
|
2008-03-03 22:38:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
stream->adpcm_history1_16 = hist1;
|
|
|
|
stream->adpcm_history2_16 = hist2;
|
|
|
|
}
|