mirror of https://github.com/inolen/redream.git
phase actually has 18 fractional bits, not 10
This commit is contained in:
parent
2e1524a259
commit
ff3aa7c551
|
@ -34,14 +34,18 @@ DEFINE_AGGREGATE_COUNTER(aica_samples);
|
|||
#define AICA_REG_LO(addr, mask) (((addr)&0x3) == 0)
|
||||
#define AICA_REG_HI(addr, mask) ((((addr)&0x3) != 0) || ((mask) != 0xff))
|
||||
|
||||
/* phase increment has 10 fractional bits */
|
||||
#define AICA_PHASE_FRC_BITS 10
|
||||
#define AICA_BASE_FREQ (1 << AICA_PHASE_FRC_BITS)
|
||||
/* phase increment has 18 fractional bits */
|
||||
#define AICA_PHASE_FRAC_BITS 18
|
||||
#define AICA_PHASE_BASE (1 << AICA_PHASE_FRAC_BITS)
|
||||
|
||||
/* ADPCM decoding constants */
|
||||
#define ADPCM_QUANT_MIN 0x7f
|
||||
#define ADPCM_QUANT_MAX 0x6000
|
||||
|
||||
/* work with samples as 64-bit ints to avoid dealing with overflow issues
|
||||
during intermediate steps */
|
||||
typedef int64_t sample_t;
|
||||
|
||||
/* amplitude / frequency envelope generator state */
|
||||
struct aica_eg_state {
|
||||
int state;
|
||||
|
@ -61,21 +65,20 @@ struct aica_channel {
|
|||
/* base address in host memory of sound data */
|
||||
uint8_t *base;
|
||||
|
||||
/* how much to step the sound source each sample */
|
||||
uint32_t phaseinc;
|
||||
|
||||
/* current position in the sound source */
|
||||
int phase;
|
||||
/* fractional remainder after phase increment */
|
||||
uint32_t phasefrc;
|
||||
int phasefrc;
|
||||
/* amount to step the sound source each sample */
|
||||
int phaseinc;
|
||||
|
||||
int pos;
|
||||
/* previous sample state */
|
||||
sample_t prev_sample;
|
||||
sample_t prev_quant;
|
||||
|
||||
/* signals the the current channel has looped */
|
||||
int looped;
|
||||
|
||||
/* previous sample state */
|
||||
int32_t prev_sample;
|
||||
int32_t prev_quant;
|
||||
|
||||
/*struct aica_eg_state aeg;
|
||||
struct aica_eg_state feg;*/
|
||||
};
|
||||
|
@ -110,8 +113,8 @@ struct aica {
|
|||
};
|
||||
|
||||
/* approximated lookup tables for MVOL / TL scaling */
|
||||
static int32_t mvol_scale[16];
|
||||
static int32_t tl_scale[256];
|
||||
static sample_t mvol_scale[16];
|
||||
static sample_t tl_scale[256];
|
||||
|
||||
static char *aica_fmt_names[] = {
|
||||
"PCMS16", /* AICA_FMT_PCMS16 */
|
||||
|
@ -160,7 +163,7 @@ static void aica_init_tables() {
|
|||
}
|
||||
|
||||
/* a 32-bit int is used for the scale, leaving 15 bits for the fraction */
|
||||
mvol_scale[i] = (int32_t)((1 << 15) / pow(2.0f, (15 - i) / 2.0f));
|
||||
mvol_scale[i] = (sample_t)((1 << 15) / pow(2.0f, (15 - i) / 2.0f));
|
||||
}
|
||||
|
||||
/* each channel's TL register adjusts the output level based on the table:
|
||||
|
@ -181,25 +184,25 @@ static void aica_init_tables() {
|
|||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
/* a 32-bit int is used for the scale, leaving 15 bits for the fraction */
|
||||
tl_scale[i] = (int32_t)((1 << 15) / pow(2.0f, i / 16.0f));
|
||||
tl_scale[i] = (sample_t)((1 << 15) / pow(2.0f, i / 16.0f));
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t aica_adjust_master_volume(struct aica *aica, int32_t in) {
|
||||
int32_t y = mvol_scale[aica->common_data->MVOL];
|
||||
static inline sample_t aica_adjust_master_volume(struct aica *aica, sample_t in) {
|
||||
sample_t y = mvol_scale[aica->common_data->MVOL];
|
||||
/* truncate fraction */
|
||||
return (in * y) >> 15;
|
||||
}
|
||||
|
||||
static inline int32_t aica_adjust_channel_volume(struct aica_channel *ch,
|
||||
int32_t in) {
|
||||
int32_t y = tl_scale[ch->data->TL];
|
||||
static inline sample_t aica_adjust_channel_volume(struct aica_channel *ch,
|
||||
sample_t in) {
|
||||
sample_t y = tl_scale[ch->data->TL];
|
||||
/* truncate fraction */
|
||||
return (in * y) >> 15;
|
||||
}
|
||||
|
||||
static void aica_decode_adpcm(int32_t data, int32_t prev, int32_t prev_quant,
|
||||
int32_t *next, int32_t *next_quant) {
|
||||
static void aica_decode_adpcm(sample_t data, sample_t prev, sample_t prev_quant,
|
||||
sample_t *next, sample_t *next_quant) {
|
||||
/* the decoded value (n) = (1 - 2 * l4) * (l3 + l2/2 + l1/4 + 1/8) * quantized
|
||||
width (n) + decoded value (n - 1)
|
||||
|
||||
|
@ -217,7 +220,7 @@ static void aica_decode_adpcm(int32_t data, int32_t prev, int32_t prev_quant,
|
|||
1 1 1 15
|
||||
|
||||
the final value is a signed 16-bit value and must be clamped as such */
|
||||
static int32_t adpcm_scale[8] = {1, 3, 5, 7, 9, 11, 13, 15};
|
||||
static sample_t adpcm_scale[8] = {1, 3, 5, 7, 9, 11, 13, 15};
|
||||
|
||||
int l4 = data >> 3;
|
||||
int l321 = data & 0x7;
|
||||
|
@ -242,7 +245,7 @@ static void aica_decode_adpcm(int32_t data, int32_t prev, int32_t prev_quant,
|
|||
1 1 1 2.3984375 (614 / 256)
|
||||
|
||||
the quantized width's min value is 127, and its max value is 24576 */
|
||||
static int32_t adpcm_rate[8] = {230, 230, 230, 230, 307, 409, 512, 614};
|
||||
static sample_t adpcm_rate[8] = {230, 230, 230, 230, 307, 409, 512, 614};
|
||||
|
||||
*next_quant = (prev_quant * adpcm_rate[l321]) >> 8;
|
||||
*next_quant = CLAMP(*next_quant, ADPCM_QUANT_MIN, ADPCM_QUANT_MAX);
|
||||
|
@ -426,7 +429,7 @@ static void aica_rtc_timer(void *data) {
|
|||
}
|
||||
|
||||
static float aica_channel_hz(struct aica_channel *ch) {
|
||||
return (AICA_SAMPLE_FREQ * ch->phaseinc) / (float)AICA_BASE_FREQ;
|
||||
return (AICA_SAMPLE_FREQ * ch->phaseinc) / (float)AICA_PHASE_BASE;
|
||||
}
|
||||
|
||||
static float aica_channel_duration(struct aica_channel *ch) {
|
||||
|
@ -434,16 +437,18 @@ static float aica_channel_duration(struct aica_channel *ch) {
|
|||
return ch->data->LEA / hz;
|
||||
}
|
||||
|
||||
static uint32_t aica_channel_phaseinc(struct aica_channel *ch) {
|
||||
/* by default, step a single sample at a time */
|
||||
uint32_t phaseinc = AICA_BASE_FREQ;
|
||||
static int aica_channel_phaseinc(struct aica_channel *ch) {
|
||||
/* by default, increment by one sample per step */
|
||||
int phaseinc = AICA_PHASE_BASE;
|
||||
|
||||
/* FNS represents the fractional phase increment, used to linearly
|
||||
interpolate between samples */
|
||||
phaseinc |= ch->data->FNS;
|
||||
/* FNS represents the fractional phase increment, used to linearly interpolate
|
||||
between samples. note, the phase increment has 18 total fractional bits,
|
||||
but FNS is only 10 bits enabling lowest octave (which causes a right shift
|
||||
by 8) to still have 10 bits for interpolation */
|
||||
phaseinc |= ch->data->FNS << 8;
|
||||
|
||||
/* OCT represents a full octave pitch shift in two's complement, ranging
|
||||
from -8 to +7 */
|
||||
/* OCT represents a full octave pitch shift in two's complement, ranging from
|
||||
-8 to +7 */
|
||||
uint32_t oct = ch->data->OCT;
|
||||
if (oct & 0x8) {
|
||||
phaseinc >>= (16 - oct);
|
||||
|
@ -480,9 +485,9 @@ static void aica_channel_key_on(struct aica *aica, struct aica_channel *ch) {
|
|||
|
||||
ch->active = 1;
|
||||
ch->base = aica_channel_base(aica, ch);
|
||||
ch->phaseinc = aica_channel_phaseinc(ch);
|
||||
ch->phase = 0;
|
||||
ch->phasefrc = 0;
|
||||
ch->pos = 0;
|
||||
ch->phaseinc = aica_channel_phaseinc(ch);
|
||||
ch->looped = 0;
|
||||
ch->prev_sample = 0;
|
||||
ch->prev_quant = ADPCM_QUANT_MIN;
|
||||
|
@ -513,7 +518,7 @@ static void aica_channel_key_on_execute(struct aica *aica,
|
|||
ch->data->KYONEX = 0;
|
||||
}
|
||||
|
||||
static int32_t aica_channel_step(struct aica *aica, struct aica_channel *ch) {
|
||||
static sample_t aica_channel_step(struct aica *aica, struct aica_channel *ch) {
|
||||
if (!ch->active) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -522,29 +527,29 @@ static int32_t aica_channel_step(struct aica *aica, struct aica_channel *ch) {
|
|||
|
||||
/* the data returned is a signed 16-bit PCM data, but signed 32-bit values are
|
||||
used intermediately to avoid dealing with overflows until the end */
|
||||
int32_t next_sample = 0;
|
||||
int32_t next_quant = 0;
|
||||
sample_t next_sample = 0;
|
||||
sample_t next_quant = 0;
|
||||
|
||||
/* step the stream */
|
||||
ch->phasefrc += ch->phaseinc;
|
||||
|
||||
while (ch->phasefrc >= AICA_BASE_FREQ) {
|
||||
while (ch->phasefrc >= AICA_PHASE_BASE) {
|
||||
if (ch->data->SSCTL) {
|
||||
LOG_WARNING("SSCTL input not supported");
|
||||
} else {
|
||||
switch (ch->data->PCMS) {
|
||||
case AICA_FMT_PCMS16: {
|
||||
next_sample = *(int16_t *)&ch->base[ch->pos << 1];
|
||||
next_sample = *(int16_t *)&ch->base[ch->phase << 1];
|
||||
} break;
|
||||
|
||||
case AICA_FMT_PCMS8: {
|
||||
next_sample = *(int8_t *)&ch->base[ch->pos] << 8;
|
||||
next_sample = *(int8_t *)&ch->base[ch->phase] << 8;
|
||||
} break;
|
||||
|
||||
case AICA_FMT_ADPCM:
|
||||
case AICA_FMT_ADPCM_STREAM: {
|
||||
int shift = (ch->pos & 1) << 2;
|
||||
int32_t data = (ch->base[ch->pos >> 1] >> shift) & 0xf;
|
||||
int shift = (ch->phase & 1) << 2;
|
||||
sample_t data = (ch->base[ch->phase >> 1] >> shift) & 0xf;
|
||||
aica_decode_adpcm(data, ch->prev_sample, ch->prev_quant, &next_sample,
|
||||
&next_quant);
|
||||
} break;
|
||||
|
@ -557,23 +562,23 @@ static int32_t aica_channel_step(struct aica *aica, struct aica_channel *ch) {
|
|||
|
||||
ch->prev_sample = next_sample;
|
||||
ch->prev_quant = next_quant;
|
||||
ch->phasefrc -= AICA_BASE_FREQ;
|
||||
ch->pos++;
|
||||
ch->phasefrc -= AICA_PHASE_BASE;
|
||||
ch->phase++;
|
||||
}
|
||||
|
||||
/* interpolate sample */
|
||||
int32_t result = ch->prev_sample * (AICA_BASE_FREQ - ch->phasefrc);
|
||||
sample_t result = ch->prev_sample * (AICA_PHASE_BASE - ch->phasefrc);
|
||||
result += next_sample * ch->phasefrc;
|
||||
result >>= AICA_PHASE_FRC_BITS;
|
||||
result >>= AICA_PHASE_FRAC_BITS;
|
||||
|
||||
/* shift to DECAY1 once starting the loop */
|
||||
if (ch->data->LPSLNK && ch->pos >= ch->data->LSA) {
|
||||
if (ch->data->LPSLNK && ch->phase >= ch->data->LSA) {
|
||||
LOG_WARNING("EG not currently supported");
|
||||
}
|
||||
|
||||
/* check if the current position in the sound source has passed the loop end
|
||||
position */
|
||||
if (ch->pos >= ch->data->LEA) {
|
||||
if (ch->phase >= ch->data->LEA) {
|
||||
ch->looped = 1;
|
||||
|
||||
LOG_AICA("aica_channel_step [%d] looped", ch->id);
|
||||
|
@ -585,7 +590,7 @@ static int32_t aica_channel_step(struct aica *aica, struct aica_channel *ch) {
|
|||
|
||||
case AICA_LOOP_FORWARD: {
|
||||
/* restart channel at loop start address */
|
||||
ch->pos = ch->data->LSA;
|
||||
ch->phase = ch->data->LSA;
|
||||
|
||||
/* in ADPCM streaming mode, the loop is a ring buffer. don't reset the
|
||||
decoding state in this case */
|
||||
|
@ -605,12 +610,12 @@ static void aica_generate_frames(struct aica *aica) {
|
|||
int16_t buffer[AICA_BATCH_SIZE * 2];
|
||||
|
||||
for (int frame = 0; frame < AICA_BATCH_SIZE; frame++) {
|
||||
int32_t l = 0;
|
||||
int32_t r = 0;
|
||||
sample_t l = 0;
|
||||
sample_t r = 0;
|
||||
|
||||
for (int i = 0; i < AICA_NUM_CHANNELS; i++) {
|
||||
struct aica_channel *ch = &aica->channels[i];
|
||||
int32_t s = aica_channel_step(aica, ch);
|
||||
sample_t s = aica_channel_step(aica, ch);
|
||||
l += aica_adjust_channel_volume(ch, s);
|
||||
r += aica_adjust_channel_volume(ch, s);
|
||||
}
|
||||
|
@ -705,7 +710,7 @@ static uint32_t aica_common_reg_read(struct aica *aica, uint32_t addr,
|
|||
|
||||
case 0x14: { /* CA */
|
||||
struct aica_channel *ch = &aica->channels[aica->common_data->MSLC];
|
||||
aica->common_data->CA = ch->pos;
|
||||
aica->common_data->CA = ch->phase;
|
||||
} break;
|
||||
|
||||
case 0x90: { /* TIMA, TACTL */
|
||||
|
|
Loading…
Reference in New Issue