diff --git a/src/devices/sound/c352.cpp b/src/devices/sound/c352.cpp index c3b40b04e62..2fd094379a7 100644 --- a/src/devices/sound/c352.cpp +++ b/src/devices/sound/c352.cpp @@ -72,14 +72,18 @@ void c352_device::fetch_sample(c352_voice_t* v) } else { - int8_t s; + int8_t s, s2; s = (int8_t)read_byte(v->pos); + v->sample = s<<8; if(v->flags & C352_FLG_MULAW) - v->sample = m_mulaw_table[(uint8_t)s]; - else - v->sample = s<<8; + { + s2 = (s&0x7f)>>4; + + 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; @@ -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) { - int i,j; int16_t s; + int32_t next_counter; stream_sample_t *buffer_fl = outputs[0]; stream_sample_t *buffer_fr = outputs[1]; 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) { - v->counter += v->freq; + next_counter = v->counter+v->freq; - if(v->counter > 0x10000) + if(next_counter & 0x10000) { - v->counter &= 0xffff; 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; @@ -161,12 +181,12 @@ void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **in } // Left - out[0] += ((v->flags & C352_FLG_PHASEFL) ? -s * (v->vol_f>>8) : s * (v->vol_f>>8))>>8; - out[2] += ((v->flags & C352_FLG_PHASERL) ? -s * (v->vol_r>>8) : s * (v->vol_r>>8))>>8; + out[0] += (((v->flags & C352_FLG_PHASEFL) ? -s : s) * v->curr_vol[0])>>8; + out[2] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[2])>>8; // Right - out[1] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_f&0xff) : s * (v->vol_f&0xff))>>8; - out[3] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_r&0xff) : s * (v->vol_r&0xff))>>8; + out[1] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[1])>>8; + out[3] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[3])>>8; } *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_rr++ = (int16_t) (out[3]>>3); } - - } 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) return *((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]); + else if(address == 0x200) + return m_control; else return 0; @@ -222,11 +242,13 @@ void c352_device::write_reg16(unsigned long address, unsigned short val) 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; } else if(address == 0x200) + { m_control = val; + logerror("C352 control register write: %04x\n",val); + } else if(address == 0x202) // execute keyons/keyoffs { 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].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_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) { 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() { int i; - double x_max = 32752.0; - double y_max = 127.0; - double u = 10.0; - + m_sample_rate_base = clock() / m_divider; 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 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].vol_f), 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].flags), 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_control)); - } void c352_device::device_reset() @@ -325,7 +333,6 @@ WRITE16_MEMBER( c352_device::write ) { if (mem_mask == 0xffff) { - //printf("%04x: %04x\n", offset, data); write_reg16(offset, data); } else diff --git a/src/devices/sound/c352.h b/src/devices/sound/c352.h index 63d4e71b8f2..9c32438d5a3 100644 --- a/src/devices/sound/c352.h +++ b/src/devices/sound/c352.h @@ -81,6 +81,8 @@ private: uint16_t vol_f; uint16_t vol_r; + uint8_t curr_vol[4]; + uint16_t freq; uint16_t flags; @@ -95,12 +97,12 @@ private: int m_divider; c352_voice_t m_c352_v[32]; - int16_t m_mulaw_table[256]; uint16_t m_random; uint16_t m_control; // control flags, purpose unknown. 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); void write_reg16(unsigned long address, unsigned short val);