diff options
Diffstat (limited to 'src/devices/sound/rf5c400.cpp')
-rw-r--r-- | src/devices/sound/rf5c400.cpp | 275 |
1 files changed, 123 insertions, 152 deletions
diff --git a/src/devices/sound/rf5c400.cpp b/src/devices/sound/rf5c400.cpp index df355b5a03c..39440c66991 100644 --- a/src/devices/sound/rf5c400.cpp +++ b/src/devices/sound/rf5c400.cpp @@ -20,19 +20,27 @@ #include "emu.h" #include "rf5c400.h" -static int volume_table[256]; -static double pan_table[0x64]; - -/* envelope parameter (experimental) */ -#define ENV_AR_SPEED 0.1 -#define ENV_MIN_AR 0x02 -#define ENV_MAX_AR 0x80 -#define ENV_DR_SPEED 2.0 -#define ENV_MIN_DR 0x20 -#define ENV_MAX_DR 0x73 -#define ENV_RR_SPEED 0.7 -#define ENV_MIN_RR 0x20 -#define ENV_MAX_RR 0x54 +namespace { + +int volume_table[256]; +double pan_table[0x64]; + +void init_static_tables() +{ + // init volume/pan tables + double max = 255.0; + for (int i = 0; i < 256; i++) { + volume_table[i] = uint16_t(max); + max /= pow(10.0, double((4.5 / (256.0 / 16.0)) / 20)); + } + for (int i = 0; i < 0x48; i++) { + pan_table[i] = sqrt(double(0x47 - i)) / sqrt(double(0x47)); + } + for (int i = 0x48; i < 0x64; i++) { + pan_table[i] = 0.0; + } +} + /* PCM type */ enum @@ -52,9 +60,62 @@ enum PHASE_RELEASE }; +} // anonymous namespace + // device type definition -const device_type RF5C400 = device_creator<rf5c400_device>; +DEFINE_DEVICE_TYPE(RF5C400, rf5c400_device, "rf5c400", "Ricoh RF5C400") + + +rf5c400_device::envelope_tables::envelope_tables() +{ + std::fill(std::begin(m_ar), std::end(m_ar), 0.0); + std::fill(std::begin(m_dr), std::end(m_dr), 0.0); + std::fill(std::begin(m_rr), std::end(m_rr), 0.0); +} + +void rf5c400_device::envelope_tables::init(uint32_t clock) +{ + /* envelope parameter (experimental) */ + static constexpr double ENV_AR_SPEED = 0.1; + static constexpr int ENV_MIN_AR = 0x02; + static constexpr int ENV_MAX_AR = 0x80; + static constexpr double ENV_DR_SPEED = 2.0; + static constexpr int ENV_MIN_DR = 0x20; + static constexpr int ENV_MAX_DR = 0x73; + static constexpr double ENV_RR_SPEED = 0.7; + static constexpr int ENV_MIN_RR = 0x20; + static constexpr int ENV_MAX_RR = 0x54; + + double r; + + // attack + r = 1.0 / (ENV_AR_SPEED * (clock / 384)); + for (int i = 0; i < ENV_MIN_AR; i++) + m_ar[i] = 1.0; + for (int i = ENV_MIN_AR; i < ENV_MAX_AR; i++) + m_ar[i] = r * (ENV_MAX_AR - i) / (ENV_MAX_AR - ENV_MIN_AR); + for (int i = ENV_MAX_AR; i < 0x9f; i++) + m_ar[i] = 0.0; + + // decay + r = -5.0 / (ENV_DR_SPEED * (clock / 384)); + for (int i = 0; i < ENV_MIN_DR; i++) + m_dr[i] = r; + for (int i = ENV_MIN_DR; i < ENV_MAX_DR; i++) + m_dr[i] = r * (ENV_MAX_DR - i) / (ENV_MAX_DR - ENV_MIN_DR); + for (int i = ENV_MAX_DR; i < 0x9f; i++) + m_dr[i] = 0.0; + + // release + r = -5.0 / (ENV_RR_SPEED * (clock / 384)); + for (int i = 0; i < ENV_MIN_RR; i++) + m_rr[i] = r; + for (int i = ENV_MIN_RR; i < ENV_MAX_RR; i++) + m_rr[i] = r * (ENV_MAX_RR - i) / (ENV_MAX_RR - ENV_MIN_RR); + for (int i = ENV_MAX_RR; i < 0x9f; i++) + m_rr[i] = 0.0; +} //************************************************************************** @@ -66,14 +127,12 @@ const device_type RF5C400 = device_creator<rf5c400_device>; //------------------------------------------------- rf5c400_device::rf5c400_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, RF5C400, "RF5C400", tag, owner, clock, "rf5c400", __FILE__), - device_sound_interface(mconfig, *this), - m_rom(*this, DEVICE_SELF), - m_stream(nullptr) + : device_t(mconfig, RF5C400, tag, owner, clock) + , device_sound_interface(mconfig, *this) + , m_rom(*this, DEVICE_SELF) + , m_stream(nullptr) + , m_env_tables() { - memset(m_env_ar_table, 0, sizeof(double)*0x9f); - memset(m_env_dr_table, 0, sizeof(double)*0x9f); - memset(m_env_rr_table, 0, sizeof(double)*0x9f); } @@ -84,7 +143,45 @@ rf5c400_device::rf5c400_device(const machine_config &mconfig, const char *tag, d void rf5c400_device::device_start() { - rf5c400_init_chip(); + init_static_tables(); + m_env_tables.init(clock()); + + // init channel info + for (rf5c400_channel &chan : m_channels) + { + chan.env_phase = PHASE_NONE; + chan.env_level = 0.0; + chan.env_step = 0.0; + chan.env_scale = 1.0; + } + + for (int i = 0; i < ARRAY_LENGTH(m_channels); i++) + { + save_item(NAME(m_channels[i].startH), i); + save_item(NAME(m_channels[i].startL), i); + save_item(NAME(m_channels[i].freq), i); + save_item(NAME(m_channels[i].endL), i); + save_item(NAME(m_channels[i].endHloopH), i); + save_item(NAME(m_channels[i].loopL), i); + save_item(NAME(m_channels[i].pan), i); + save_item(NAME(m_channels[i].effect), i); + save_item(NAME(m_channels[i].volume), i); + save_item(NAME(m_channels[i].attack), i); + save_item(NAME(m_channels[i].decay), i); + save_item(NAME(m_channels[i].release), i); + save_item(NAME(m_channels[i].cutoff), i); + save_item(NAME(m_channels[i].pos), i); + save_item(NAME(m_channels[i].step), i); + save_item(NAME(m_channels[i].keyon), i); + save_item(NAME(m_channels[i].env_phase), i); + save_item(NAME(m_channels[i].env_level), i); + save_item(NAME(m_channels[i].env_step), i); + save_item(NAME(m_channels[i].env_scale), i); + } + + m_stream = stream_alloc(0, 2, clock() / 384); + + m_rommask = m_rom.length() - 1; } //------------------------------------------------- @@ -167,8 +264,7 @@ void rf5c400_device::sound_stream_update(sound_stream &stream, stream_sample_t * } else { - env_step = - m_env_dr_table[decode80(channel->decay >> 8)]; + env_step = m_env_tables.dr(*channel); } env_rstep = env_step * channel->env_scale; } @@ -217,130 +313,7 @@ void rf5c400_device::sound_stream_update(sound_stream &stream, stream_sample_t * /*****************************************************************************/ -uint8_t rf5c400_device::decode80(uint8_t val) -{ - if (val & 0x80) - { - val = (val & 0x7f) + 0x1f; - } - - return val; -} - -void rf5c400_device::rf5c400_init_chip() -{ - int i; - - // init volume table - { - double max=255.0; - for (i = 0; i < 256; i++) { - volume_table[i]=(uint16_t)max; - max /= pow(10.0,(double)((4.5/(256.0/16.0))/20)); - } - for(i = 0; i < 0x48; i++) { - pan_table[i] = sqrt( (double)(0x47 - i) ) / sqrt( (double)0x47 ); - } - for(i = 0x48; i < 0x64; i++) { - pan_table[i] = 0.0; - } - } - - // init envelope table - { - double r; - - // attack - r = 1.0 / (ENV_AR_SPEED * (clock() / 384)); - for (i = 0; i < ENV_MIN_AR; i++) - { - m_env_ar_table[i] = 1.0; - } - for (i = ENV_MIN_AR; i < ENV_MAX_AR; i++) - { - m_env_ar_table[i] = - r * (ENV_MAX_AR - i) / (ENV_MAX_AR - ENV_MIN_AR); - } - for (i = ENV_MAX_AR; i < 0x9f; i++) - { - m_env_ar_table[i] = 0.0; - } - - // decay - r = -5.0 / (ENV_DR_SPEED * (clock() / 384)); - for (i = 0; i < ENV_MIN_DR; i++) - { - m_env_dr_table[i] = r; - } - for (i = ENV_MIN_DR; i < ENV_MAX_DR; i++) - { - m_env_dr_table[i] = - r * (ENV_MAX_DR - i) / (ENV_MAX_DR - ENV_MIN_DR); - } - for (i = ENV_MAX_DR; i < 0x9f; i++) - { - m_env_dr_table[i] = 0.0; - } - - // release - r = -5.0 / (ENV_RR_SPEED * (clock() / 384)); - for (i = 0; i < ENV_MIN_RR; i++) - { - m_env_rr_table[i] = r; - } - for (i = ENV_MIN_RR; i < ENV_MAX_RR; i++) - { - m_env_rr_table[i] = - r * (ENV_MAX_RR - i) / (ENV_MAX_RR - ENV_MIN_RR); - } - for (i = ENV_MAX_RR; i < 0x9f; i++) - { - m_env_rr_table[i] = 0.0; - } - } - - // init channel info - for (i = 0; i < 32; i++) - { - m_channels[i].env_phase = PHASE_NONE; - m_channels[i].env_level = 0.0; - m_channels[i].env_step = 0.0; - m_channels[i].env_scale = 1.0; - } - - for (i = 0; i < ARRAY_LENGTH(m_channels); i++) - { - save_item(NAME(m_channels[i].startH), i); - save_item(NAME(m_channels[i].startL), i); - save_item(NAME(m_channels[i].freq), i); - save_item(NAME(m_channels[i].endL), i); - save_item(NAME(m_channels[i].endHloopH), i); - save_item(NAME(m_channels[i].loopL), i); - save_item(NAME(m_channels[i].pan), i); - save_item(NAME(m_channels[i].effect), i); - save_item(NAME(m_channels[i].volume), i); - save_item(NAME(m_channels[i].attack), i); - save_item(NAME(m_channels[i].decay), i); - save_item(NAME(m_channels[i].release), i); - save_item(NAME(m_channels[i].cutoff), i); - save_item(NAME(m_channels[i].pos), i); - save_item(NAME(m_channels[i].step), i); - save_item(NAME(m_channels[i].keyon), i); - save_item(NAME(m_channels[i].env_phase), i); - save_item(NAME(m_channels[i].env_level), i); - save_item(NAME(m_channels[i].env_step), i); - save_item(NAME(m_channels[i].env_scale), i); - } - - m_stream = stream_alloc(0, 2, clock()/384); - - m_rommask = m_rom.length() - 1; -} - - -/*****************************************************************************/ - -static uint16_t rf5c400_status = 0; +static uint16_t rf5c400_status = 0; // a static one of these for all instances of the chip? how does that work? READ16_MEMBER( rf5c400_device::rf5c400_r ) { switch(offset) @@ -388,8 +361,7 @@ WRITE16_MEMBER( rf5c400_device::rf5c400_w ) m_channels[ch].env_phase = PHASE_ATTACK; m_channels[ch].env_level = 0.0; - m_channels[ch].env_step = - m_env_ar_table[decode80(m_channels[ch].attack >> 8)]; + m_channels[ch].env_step = m_env_tables.ar(m_channels[ch]); break; case 0x40: if (m_channels[ch].env_phase != PHASE_NONE) @@ -401,8 +373,7 @@ WRITE16_MEMBER( rf5c400_device::rf5c400_w ) } else { - m_channels[ch].env_step = - m_env_rr_table[decode80(m_channels[ch].release >> 8)]; + m_channels[ch].env_step = m_env_tables.rr(m_channels[ch]); } } break; |