mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-20 18:35:52 +01:00
a9ee80dc59
extended .sad support git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@541 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
61 lines
1.7 KiB
C
61 lines
1.7 KiB
C
#include "coding.h"
|
|
#include "../util.h"
|
|
|
|
/* ADPCM found in NDS games using Procyon Studio Digital Sound Elements */
|
|
|
|
static const int8_t proc_coef[5][2] =
|
|
{
|
|
{0x00,0x00},
|
|
{0x3C,0x00},
|
|
{0x73,0xCC},
|
|
{0x62,0xC9},
|
|
{0x7A,0xC4},
|
|
};
|
|
|
|
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
|
int i=first_sample;
|
|
int32_t sample_count;
|
|
|
|
int framesin = first_sample/30;
|
|
|
|
uint8_t header = read_8bit(framesin*16+15+stream->offset,stream->streamfile) ^ 0x80;
|
|
int scale = 12 - (header & 0xf);
|
|
int coef_index = (header >> 4) & 0xf;
|
|
int32_t hist1 = stream->adpcm_history1_32;
|
|
int32_t hist2 = stream->adpcm_history2_32;
|
|
int32_t coef1;
|
|
int32_t coef2;
|
|
|
|
if (coef_index > 4) coef_index = 0;
|
|
coef1 = proc_coef[coef_index][0];
|
|
coef2 = proc_coef[coef_index][1];
|
|
first_sample = first_sample%30;
|
|
|
|
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
|
int sample_byte = read_8bit(framesin*16+stream->offset+i/2,stream->streamfile) ^ 0x80;
|
|
|
|
int32_t sample =
|
|
(int32_t)
|
|
(i&1?
|
|
get_high_nibble_signed(sample_byte):
|
|
get_low_nibble_signed(sample_byte)
|
|
) * 64 * 64;
|
|
if (scale < 0)
|
|
{
|
|
sample <<= -scale;
|
|
}
|
|
else
|
|
sample >>= scale;
|
|
|
|
sample = (hist1 * coef1 + hist2 * coef2 + 32) / 64 + (sample * 64);
|
|
|
|
hist2 = hist1;
|
|
hist1 = sample;
|
|
|
|
outbuf[sample_count] = clamp16((sample + 32) / 64) / 64 * 64;
|
|
}
|
|
|
|
stream->adpcm_history1_32 = hist1;
|
|
stream->adpcm_history2_32 = hist2;
|
|
}
|