summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/sound/c352.cpp301
-rw-r--r--src/devices/sound/c352.h11
2 files changed, 198 insertions, 114 deletions
diff --git a/src/devices/sound/c352.cpp b/src/devices/sound/c352.cpp
index 38d9987d091..1240b11852b 100644
--- a/src/devices/sound/c352.cpp
+++ b/src/devices/sound/c352.cpp
@@ -18,10 +18,17 @@
#include "emu.h"
#include "c352.h"
+#include "wavwrite.h"
//#define VERBOSE 1
#include "logmacro.h"
+#define C352_LOG_PCM (0)
+
+#if C352_LOG_PCM
+#include <map>
+static std::map<uint32_t, bool> s_found_pcm;
+#endif
// device type definition
DEFINE_DEVICE_TYPE(C352, c352_device, "c352", "Namco C352")
@@ -51,134 +58,125 @@ void c352_device::rom_bank_updated()
m_stream->update();
}
-void c352_device::fetch_sample(c352_voice_t* v)
+void c352_device::fetch_sample(c352_voice_t& v)
{
- v->last_sample = v->sample;
+ v.last_sample = v.sample;
- if(v->flags & C352_FLG_NOISE)
+ if (v.flags & C352_FLG_NOISE)
{
- m_random = (m_random>>1) ^ ((-(m_random&1)) & 0xfff6);
- v->sample = m_random;
+ m_random = (m_random >> 1) ^ ((-(m_random & 1)) & 0xfff6);
+ v.sample = m_random;
}
else
{
- int8_t s;
-
- s = (int8_t)read_byte(v->pos);
+ int8_t s = (int8_t)read_byte(v.pos);
- if(v->flags & C352_FLG_MULAW)
- v->sample = m_mulawtab[s&0xff];
+ if (v.flags & C352_FLG_MULAW)
+ v.sample = m_mulawtab[s & 0xff];
else
- v->sample = s<<8;
+ v.sample = s << 8;
- uint16_t pos = v->pos&0xffff;
+ uint16_t pos = v.pos & 0xffff;
- if((v->flags & C352_FLG_LOOP) && v->flags & C352_FLG_REVERSE)
+ if ((v.flags & C352_FLG_LOOP) && v.flags & C352_FLG_REVERSE)
{
// backwards>forwards
- if((v->flags & C352_FLG_LDIR) && pos == v->wave_loop)
- v->flags &= ~C352_FLG_LDIR;
+ if ((v.flags & C352_FLG_LDIR) && pos == v.wave_loop)
+ v.flags &= ~C352_FLG_LDIR;
// forwards>backwards
- else if(!(v->flags & C352_FLG_LDIR) && pos == v->wave_end)
- v->flags |= C352_FLG_LDIR;
+ else if (!(v.flags & C352_FLG_LDIR) && pos == v.wave_end)
+ v.flags |= C352_FLG_LDIR;
- v->pos += (v->flags&C352_FLG_LDIR) ? -1 : 1;
+ v.pos += (v.flags & C352_FLG_LDIR) ? -1 : 1;
}
- else if(pos == v->wave_end)
+ else if (pos == v.wave_end)
{
- if((v->flags & C352_FLG_LINK) && (v->flags & C352_FLG_LOOP))
+ if ((v.flags & C352_FLG_LINK) && (v.flags & C352_FLG_LOOP))
{
- v->pos = (v->wave_start<<16) | v->wave_loop;
- v->flags |= C352_FLG_LOOPHIST;
+ v.pos = (v.wave_start << 16) | v.wave_loop;
+ v.flags |= C352_FLG_LOOPHIST;
}
- else if(v->flags & C352_FLG_LOOP)
+ else if (v.flags & C352_FLG_LOOP)
{
- v->pos = (v->pos&0xff0000) | v->wave_loop;
- v->flags |= C352_FLG_LOOPHIST;
+ v.pos = (v.pos & 0xff0000) | v.wave_loop;
+ v.flags |= C352_FLG_LOOPHIST;
}
else
{
- v->flags |= C352_FLG_KEYOFF;
- v->flags &= ~C352_FLG_BUSY;
- v->sample=0;
+ v.flags |= C352_FLG_KEYOFF;
+ v.flags &= ~C352_FLG_BUSY;
+ v.sample = 0;
}
}
else
{
- v->pos += (v->flags&C352_FLG_REVERSE) ? -1 : 1;
+ v.pos += (v.flags & C352_FLG_REVERSE) ? -1 : 1;
}
}
}
-void c352_device::ramp_volume(c352_voice_t* v,int ch,uint8_t val)
+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;
+ 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];
stream_sample_t *buffer_rr = outputs[3];
- c352_voice_t* v;
-
- long out[4];
- for(i=0;i<samples;i++)
+ for (int i = 0; i < samples; i++)
{
- out[0]=out[1]=out[2]=out[3]=0;
+ long out[4] = { 0, 0, 0, 0 };
- for(j=0;j<32;j++)
+ for (int j = 0; j < 32; j++)
{
+ c352_voice_t &v = m_c352_v[j];
+ int16_t s = 0;
- v = &m_c352_v[j];
- s = 0;
-
- if(v->flags & C352_FLG_BUSY)
+ if (v.flags & C352_FLG_BUSY)
{
- next_counter = v->counter+v->freq;
+ int32_t next_counter = v.counter + v.freq;
- if(next_counter & 0x10000)
+ if (next_counter & 0x10000)
{
fetch_sample(v);
}
- if((next_counter^v->counter) & 0x18000)
+ 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);
+ 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;
+ v.counter = next_counter & 0xffff;
- s = v->sample;
+ s = v.sample;
// Interpolate samples
- if((v->flags & C352_FLG_FILTER) == 0)
- s = v->last_sample + (v->counter*(v->sample-v->last_sample)>>16);
+ if ((v.flags & C352_FLG_FILTER) == 0)
+ s = v.last_sample + (v.counter * (v.sample - v.last_sample) >> 16);
}
// Left
- out[0] += (((v->flags & C352_FLG_PHASEFL) ? -s : s) * v->curr_vol[0])>>8;
- out[2] += (((v->flags & C352_FLG_PHASERL) ? -s : s) * v->curr_vol[2])>>8;
+ out[0] += (((v.flags & C352_FLG_PHASEFL) ? -s : s) * v.curr_vol[0]) >> 8;
+ out[2] += (((v.flags & C352_FLG_PHASERL) ? -s : s) * v.curr_vol[2]) >> 8;
// Right
- out[1] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[1])>>8;
- out[3] += (((v->flags & C352_FLG_PHASEFR) ? -s : s) * v->curr_vol[3])>>8;
+ out[1] += (((v.flags & C352_FLG_PHASEFR) ? -s : s) * v.curr_vol[1]) >> 8;
+ out[3] += (((v.flags & C352_FLG_PHASEFR) ? -s : s) * v.curr_vol[3]) >> 8;
}
- *buffer_fl++ = (int16_t) (out[0]>>3);
- *buffer_fr++ = (int16_t) (out[1]>>3);
- *buffer_rl++ = (int16_t) (out[2]>>3);
- *buffer_rr++ = (int16_t) (out[3]>>3);
+ *buffer_fl++ = (int16_t)(out[0] >> 3);
+ *buffer_fr++ = (int16_t)(out[1] >> 3);
+ *buffer_rl++ = (int16_t)(out[2] >> 3);
+ *buffer_rr++ = (int16_t)(out[3] >> 3);
}
}
@@ -188,19 +186,19 @@ uint16_t c352_device::read_reg16(unsigned long address)
const int reg_map[8] =
{
- offsetof(c352_voice_t,vol_f) / sizeof(uint16_t),
- offsetof(c352_voice_t,vol_r) / sizeof(uint16_t),
- offsetof(c352_voice_t,freq) / sizeof(uint16_t),
- offsetof(c352_voice_t,flags) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_bank) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_start) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_end) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_loop) / sizeof(uint16_t),
+ offsetof(c352_voice_t, vol_f) / sizeof(uint16_t),
+ offsetof(c352_voice_t, vol_r) / sizeof(uint16_t),
+ offsetof(c352_voice_t, freq) / sizeof(uint16_t),
+ offsetof(c352_voice_t, flags) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_bank) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_start) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_end) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_loop) / sizeof(uint16_t),
};
- if(address < 0x100)
- return *((uint16_t*)&m_c352_v[address/8]+reg_map[address%8]);
- else if(address == 0x200)
+ 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;
@@ -214,48 +212,135 @@ void c352_device::write_reg16(unsigned long address, unsigned short val)
const int reg_map[8] =
{
- offsetof(c352_voice_t,vol_f) / sizeof(uint16_t),
- offsetof(c352_voice_t,vol_r) / sizeof(uint16_t),
- offsetof(c352_voice_t,freq) / sizeof(uint16_t),
- offsetof(c352_voice_t,flags) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_bank) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_start) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_end) / sizeof(uint16_t),
- offsetof(c352_voice_t,wave_loop) / sizeof(uint16_t),
+ offsetof(c352_voice_t, vol_f) / sizeof(uint16_t),
+ offsetof(c352_voice_t, vol_r) / sizeof(uint16_t),
+ offsetof(c352_voice_t, freq) / sizeof(uint16_t),
+ offsetof(c352_voice_t, flags) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_bank) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_start) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_end) / sizeof(uint16_t),
+ offsetof(c352_voice_t, wave_loop) / sizeof(uint16_t),
};
- int i;
-
- if(address < 0x100)
+ if (address < 0x100)
{
- *((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;
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 (int i = 0; i < 32; i++)
{
- if(m_c352_v[i].flags & C352_FLG_KEYON)
+ if (m_c352_v[i].flags & C352_FLG_KEYON)
{
- m_c352_v[i].pos = (m_c352_v[i].wave_bank<<16) | m_c352_v[i].wave_start;
+ m_c352_v[i].pos = (m_c352_v[i].wave_bank << 16) | m_c352_v[i].wave_start;
m_c352_v[i].sample = 0;
m_c352_v[i].last_sample = 0;
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);
+ m_c352_v[i].flags &= ~(C352_FLG_KEYON | C352_FLG_LOOPHIST);
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;
+
+#if C352_LOG_PCM
+ if (!(m_c352_v[i].flags & C352_FLG_NOISE))
+ {
+ std::map<uint32_t, bool>::iterator iter = s_found_pcm.find(m_c352_v[i].pos);
+ if (iter != s_found_pcm.end())
+ {
+ return;
+ }
+
+ s_found_pcm[m_c352_v[i].pos] = true;
+
+ char filebuf[256];
+ snprintf(filebuf, 256, "c352_%08x.wav", m_c352_v[i].pos);
+ wav_file *file = wav_open(filebuf, m_stream->sample_rate(), 1);
+ if (file != nullptr)
+ {
+ c352_voice_t &v = m_c352_v[i];
+ uint32_t pos = v.pos;
+ uint32_t flags = v.flags;
+ uint32_t counter = v.counter;
+ int16_t sample = 0;
+
+ while (pos != v.wave_end && !(flags & C352_FLG_KEYOFF))
+ {
+ int32_t next_counter = counter + v.freq;
+
+ if (next_counter & 0x10000)
+ {
+ counter = next_counter & 0xffff;
+
+ int8_t s = (int8_t)read_byte(pos);
+
+ if (v.flags & C352_FLG_MULAW)
+ sample = m_mulawtab[s & 0xff];
+ else
+ sample = s << 8;
+
+ uint16_t subpos = pos & 0xffff;
+
+ if ((flags & C352_FLG_LOOP) && flags & C352_FLG_REVERSE)
+ {
+ // backwards>forwards
+ if ((flags & C352_FLG_LDIR) && subpos == v.wave_loop)
+ flags &= ~C352_FLG_LDIR;
+ // forwards>backwards
+ else if (!(flags & C352_FLG_LDIR) && subpos == v.wave_end)
+ flags |= C352_FLG_LDIR;
+
+ pos += (flags & C352_FLG_LDIR) ? -1 : 1;
+ }
+ else if (subpos == v.wave_end)
+ {
+ if ((flags & C352_FLG_LINK) && (flags & C352_FLG_LOOP))
+ {
+ pos = (v.wave_start << 16) | v.wave_loop;
+ flags |= C352_FLG_LOOPHIST;
+ }
+ else if (flags & C352_FLG_LOOP)
+ {
+ pos = (pos & 0xff0000) | v.wave_loop;
+ if (flags & C352_FLG_LOOPHIST)
+ {
+ flags |= C352_FLG_KEYOFF;
+ }
+ flags |= C352_FLG_LOOPHIST;
+ }
+ else
+ {
+ flags |= C352_FLG_KEYOFF;
+ flags &= ~C352_FLG_BUSY;
+ sample = 0;
+ }
+ }
+ else
+ {
+ pos += (flags & C352_FLG_REVERSE) ? -1 : 1;
+ }
+ }
+
+ counter = next_counter & 0xffff;
+
+ wav_add_data_16(file, &sample, 1);
+ }
+
+ wav_close(file);
+ }
+ }
+#endif
}
- if(m_c352_v[i].flags & C352_FLG_KEYOFF)
+ 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;
}
}
@@ -273,33 +358,31 @@ void c352_device::device_clock_changed()
void c352_device::device_start()
{
- int i;
-
m_sample_rate_base = clock() / m_divider;
m_stream = machine().sound().stream_alloc(*this, 0, 4, m_sample_rate_base);
// generate mulaw table (Output similar to namco's VC emulator)
int j = 0;
- for(int i=0;i<128;i++)
+ for (int i = 0; i < 128; i++)
{
- m_mulawtab[i] = j<<5;
- if(i < 16)
+ m_mulawtab[i] = j << 5;
+ if (i < 16)
j += 1;
- else if(i < 24)
+ else if (i < 24)
j += 2;
- else if(i < 48)
+ else if (i < 48)
j += 4;
- else if(i < 100)
+ else if (i < 100)
j += 8;
else
j += 16;
}
- for(int i=0;i<128;i++)
- m_mulawtab[i+128] = (~m_mulawtab[i])&0xffe0;
+ for (int i = 0; i < 128; i++)
+ m_mulawtab[i + 128] = (~m_mulawtab[i]) & 0xffe0;
// register save state info
- for (i = 0; i < 32; i++)
+ for (int i = 0; i < 32; i++)
{
save_item(NAME(m_c352_v[i].pos), i);
save_item(NAME(m_c352_v[i].counter), i);
@@ -322,7 +405,7 @@ void c352_device::device_start()
void c352_device::device_reset()
{
// clear all channels states
- memset(m_c352_v, 0, sizeof(c352_voice_t)*32);
+ memset(m_c352_v, 0, sizeof(c352_voice_t) * 32);
// init noise generator
m_random = 0x1234;
@@ -331,7 +414,7 @@ void c352_device::device_reset()
READ16_MEMBER( c352_device::read )
{
- return(read_reg16(offset));
+ return read_reg16(offset);
}
WRITE16_MEMBER( c352_device::write )
diff --git a/src/devices/sound/c352.h b/src/devices/sound/c352.h
index 1900f58cbe2..9a97dd78622 100644
--- a/src/devices/sound/c352.h
+++ b/src/devices/sound/c352.h
@@ -44,7 +44,8 @@ protected:
virtual void rom_bank_updated() override;
private:
- enum {
+ enum
+ {
C352_FLG_BUSY = 0x8000, // channel is busy
C352_FLG_KEYON = 0x4000, // Keyon
C352_FLG_KEYOFF = 0x2000, // Keyoff
@@ -64,8 +65,8 @@ private:
C352_FLG_REVERSE = 0x0001 // play sample backwards
};
- struct c352_voice_t {
-
+ struct c352_voice_t
+ {
uint32_t pos;
uint32_t counter;
@@ -86,8 +87,8 @@ private:
};
- void fetch_sample(c352_voice_t* v);
- void ramp_volume(c352_voice_t* v,int ch,uint8_t val);
+ 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);