mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
C352: implement volume ramping, rewrite mulaw algorithm
- implement volume ramping behavior and confirmed with recording of real hardware (Tekken 3) - rewrote mulaw algorithm. This is not quite perfect yet but is closer to recordings and sounds a bit clearer (example: Time Crisis)
This commit is contained in:
parent
1184004e2c
commit
bbce1673c0
@ -72,14 +72,18 @@ void c352_device::fetch_sample(c352_voice_t* v)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int8_t s;
|
int8_t s, s2;
|
||||||
|
|
||||||
s = (int8_t)read_byte(v->pos);
|
s = (int8_t)read_byte(v->pos);
|
||||||
|
|
||||||
|
v->sample = s<<8;
|
||||||
if(v->flags & C352_FLG_MULAW)
|
if(v->flags & C352_FLG_MULAW)
|
||||||
v->sample = m_mulaw_table[(uint8_t)s];
|
{
|
||||||
else
|
s2 = (s&0x7f)>>4;
|
||||||
v->sample = s<<8;
|
|
||||||
|
v->sample = ((s2*s2)<<4) - (~(s2<<1)) * (s&0x0f);
|
||||||
|
v->sample = (s&0x80) ? (~v->sample)<<5 : v->sample<<5;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t pos = v->pos&0xffff;
|
uint16_t pos = v->pos&0xffff;
|
||||||
|
|
||||||
@ -120,11 +124,18 @@ void c352_device::fetch_sample(c352_voice_t* v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void c352_device::ramp_volume(c352_voice_t* v,int ch,uint8_t val)
|
||||||
|
{
|
||||||
|
int16_t vol_delta = v->curr_vol[ch] - val;
|
||||||
|
if(vol_delta != 0)
|
||||||
|
v->curr_vol[ch] += (vol_delta>0) ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i,j;
|
int i,j;
|
||||||
int16_t s;
|
int16_t s;
|
||||||
|
int32_t next_counter;
|
||||||
stream_sample_t *buffer_fl = outputs[0];
|
stream_sample_t *buffer_fl = outputs[0];
|
||||||
stream_sample_t *buffer_fr = outputs[1];
|
stream_sample_t *buffer_fr = outputs[1];
|
||||||
stream_sample_t *buffer_rl = outputs[2];
|
stream_sample_t *buffer_rl = outputs[2];
|
||||||
@ -145,13 +156,22 @@ void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
|
|||||||
|
|
||||||
if(v->flags & C352_FLG_BUSY)
|
if(v->flags & C352_FLG_BUSY)
|
||||||
{
|
{
|
||||||
v->counter += v->freq;
|
next_counter = v->counter+v->freq;
|
||||||
|
|
||||||
if(v->counter > 0x10000)
|
if(next_counter & 0x10000)
|
||||||
{
|
{
|
||||||
v->counter &= 0xffff;
|
|
||||||
fetch_sample(v);
|
fetch_sample(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((next_counter^v->counter) & 0x18000)
|
||||||
|
{
|
||||||
|
ramp_volume(v,0,v->vol_f>>8);
|
||||||
|
ramp_volume(v,1,v->vol_f&0xff);
|
||||||
|
ramp_volume(v,2,v->vol_r>>8);
|
||||||
|
ramp_volume(v,3,v->vol_r&0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
v->counter = next_counter&0xffff;
|
||||||
|
|
||||||
s = v->sample;
|
s = v->sample;
|
||||||
|
|
||||||
@ -161,12 +181,12 @@ void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
out[0] += ((v->flags & C352_FLG_PHASEFL) ? -s * (v->vol_f>>8) : s * (v->vol_f>>8))>>8;
|
out[0] += (((v->flags & C352_FLG_PHASEFL) ? -s : s) * v->curr_vol[0])>>8;
|
||||||
out[2] += ((v->flags & C352_FLG_PHASERL) ? -s * (v->vol_r>>8) : s * (v->vol_r>>8))>>8;
|
out[2] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[2])>>8;
|
||||||
|
|
||||||
// Right
|
// Right
|
||||||
out[1] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_f&0xff) : s * (v->vol_f&0xff))>>8;
|
out[1] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[1])>>8;
|
||||||
out[3] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_r&0xff) : s * (v->vol_r&0xff))>>8;
|
out[3] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[3])>>8;
|
||||||
}
|
}
|
||||||
|
|
||||||
*buffer_fl++ = (int16_t) (out[0]>>3);
|
*buffer_fl++ = (int16_t) (out[0]>>3);
|
||||||
@ -174,8 +194,6 @@ void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
|
|||||||
*buffer_rl++ = (int16_t) (out[2]>>3);
|
*buffer_rl++ = (int16_t) (out[2]>>3);
|
||||||
*buffer_rr++ = (int16_t) (out[3]>>3);
|
*buffer_rr++ = (int16_t) (out[3]>>3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t c352_device::read_reg16(unsigned long address)
|
uint16_t c352_device::read_reg16(unsigned long address)
|
||||||
@ -196,6 +214,8 @@ uint16_t c352_device::read_reg16(unsigned long address)
|
|||||||
|
|
||||||
if(address < 0x100)
|
if(address < 0x100)
|
||||||
return *((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]);
|
return *((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]);
|
||||||
|
else if(address == 0x200)
|
||||||
|
return m_control;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -222,11 +242,13 @@ void c352_device::write_reg16(unsigned long address, unsigned short val)
|
|||||||
|
|
||||||
if(address < 0x100)
|
if(address < 0x100)
|
||||||
{
|
{
|
||||||
//printf("w %04lx,%04x, %d\n", address, val, reg_map[address&7]);
|
|
||||||
*((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]) = val;
|
*((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]) = val;
|
||||||
}
|
}
|
||||||
else if(address == 0x200)
|
else if(address == 0x200)
|
||||||
|
{
|
||||||
m_control = val;
|
m_control = val;
|
||||||
|
logerror("C352 control register write: %04x\n",val);
|
||||||
|
}
|
||||||
else if(address == 0x202) // execute keyons/keyoffs
|
else if(address == 0x202) // execute keyons/keyoffs
|
||||||
{
|
{
|
||||||
for(i=0;i<32;i++)
|
for(i=0;i<32;i++)
|
||||||
@ -237,16 +259,18 @@ void c352_device::write_reg16(unsigned long address, unsigned short val)
|
|||||||
|
|
||||||
m_c352_v[i].sample = 0;
|
m_c352_v[i].sample = 0;
|
||||||
m_c352_v[i].last_sample = 0;
|
m_c352_v[i].last_sample = 0;
|
||||||
m_c352_v[i].counter = 0x10000;
|
m_c352_v[i].counter = 0xffff;
|
||||||
|
|
||||||
m_c352_v[i].flags |= C352_FLG_BUSY;
|
m_c352_v[i].flags |= C352_FLG_BUSY;
|
||||||
m_c352_v[i].flags &= ~(C352_FLG_KEYON|C352_FLG_LOOPHIST);
|
m_c352_v[i].flags &= ~(C352_FLG_KEYON|C352_FLG_LOOPHIST);
|
||||||
|
|
||||||
//printf("voice %d : pos= %08x\n",i,m_c352_v[i].pos);
|
m_c352_v[i].curr_vol[0] = m_c352_v[i].curr_vol[1] = 0;
|
||||||
|
m_c352_v[i].curr_vol[2] = m_c352_v[i].curr_vol[3] = 0;
|
||||||
}
|
}
|
||||||
else if(m_c352_v[i].flags & C352_FLG_KEYOFF)
|
else if(m_c352_v[i].flags & C352_FLG_KEYOFF)
|
||||||
{
|
{
|
||||||
m_c352_v[i].flags &= ~(C352_FLG_BUSY|C352_FLG_KEYOFF);
|
m_c352_v[i].flags &= ~(C352_FLG_BUSY|C352_FLG_KEYOFF);
|
||||||
|
m_c352_v[i].counter = 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,27 +288,11 @@ void c352_device::device_clock_changed()
|
|||||||
void c352_device::device_start()
|
void c352_device::device_start()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double x_max = 32752.0;
|
|
||||||
double y_max = 127.0;
|
|
||||||
double u = 10.0;
|
|
||||||
|
|
||||||
m_sample_rate_base = clock() / m_divider;
|
m_sample_rate_base = clock() / m_divider;
|
||||||
|
|
||||||
m_stream = machine().sound().stream_alloc(*this, 0, 4, m_sample_rate_base);
|
m_stream = machine().sound().stream_alloc(*this, 0, 4, m_sample_rate_base);
|
||||||
|
|
||||||
// generate mulaw table for mulaw format samples
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
double y = (double) (i & 0x7f);
|
|
||||||
double x = (exp (y / y_max * log (1.0 + u)) - 1.0) * x_max / u;
|
|
||||||
|
|
||||||
if (i & 0x80)
|
|
||||||
{
|
|
||||||
x = -x;
|
|
||||||
}
|
|
||||||
m_mulaw_table[i] = (uint16_t)x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// register save state info
|
// register save state info
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
@ -294,6 +302,7 @@ void c352_device::device_start()
|
|||||||
save_item(NAME(m_c352_v[i].last_sample), i);
|
save_item(NAME(m_c352_v[i].last_sample), i);
|
||||||
save_item(NAME(m_c352_v[i].vol_f), i);
|
save_item(NAME(m_c352_v[i].vol_f), i);
|
||||||
save_item(NAME(m_c352_v[i].vol_r), i);
|
save_item(NAME(m_c352_v[i].vol_r), i);
|
||||||
|
save_item(NAME(m_c352_v[i].curr_vol), i);
|
||||||
save_item(NAME(m_c352_v[i].freq), i);
|
save_item(NAME(m_c352_v[i].freq), i);
|
||||||
save_item(NAME(m_c352_v[i].flags), i);
|
save_item(NAME(m_c352_v[i].flags), i);
|
||||||
save_item(NAME(m_c352_v[i].wave_bank), i);
|
save_item(NAME(m_c352_v[i].wave_bank), i);
|
||||||
@ -303,7 +312,6 @@ void c352_device::device_start()
|
|||||||
}
|
}
|
||||||
save_item(NAME(m_random));
|
save_item(NAME(m_random));
|
||||||
save_item(NAME(m_control));
|
save_item(NAME(m_control));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void c352_device::device_reset()
|
void c352_device::device_reset()
|
||||||
@ -325,7 +333,6 @@ WRITE16_MEMBER( c352_device::write )
|
|||||||
{
|
{
|
||||||
if (mem_mask == 0xffff)
|
if (mem_mask == 0xffff)
|
||||||
{
|
{
|
||||||
//printf("%04x: %04x\n", offset, data);
|
|
||||||
write_reg16(offset, data);
|
write_reg16(offset, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -81,6 +81,8 @@ private:
|
|||||||
|
|
||||||
uint16_t vol_f;
|
uint16_t vol_f;
|
||||||
uint16_t vol_r;
|
uint16_t vol_r;
|
||||||
|
uint8_t curr_vol[4];
|
||||||
|
|
||||||
uint16_t freq;
|
uint16_t freq;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
|
|
||||||
@ -95,12 +97,12 @@ private:
|
|||||||
int m_divider;
|
int m_divider;
|
||||||
|
|
||||||
c352_voice_t m_c352_v[32];
|
c352_voice_t m_c352_v[32];
|
||||||
int16_t m_mulaw_table[256];
|
|
||||||
|
|
||||||
uint16_t m_random;
|
uint16_t m_random;
|
||||||
uint16_t m_control; // control flags, purpose unknown.
|
uint16_t m_control; // control flags, purpose unknown.
|
||||||
|
|
||||||
void fetch_sample(c352_voice_t* v);
|
void fetch_sample(c352_voice_t* v);
|
||||||
|
void ramp_volume(c352_voice_t* v,int ch,uint8_t val);
|
||||||
|
|
||||||
unsigned short read_reg16(unsigned long address);
|
unsigned short read_reg16(unsigned long address);
|
||||||
void write_reg16(unsigned long address, unsigned short val);
|
void write_reg16(unsigned long address, unsigned short val);
|
||||||
|
Loading…
Reference in New Issue
Block a user