mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Fix PC-FX ADPCM frequency behavior (#6213)
* Fix PC-FX ADPCM frequency behavior but it's still noisy and imperfect; Add imperfect_features for this. huc6230.cpp : Fix ADPCM frequency, Make ADPCM less louder, Fix naming related to patents, Fix stream sample rate related to PSG output rate, Add notes huc6272.cpp : Fix ADPCM frequency * huc6230.cpp : Fix spacing * huc6272.cpp : Add patent for reference * huc6230.cpp, huc6272.cpp : Add patent for reference
This commit is contained in:
parent
ca4bb0e084
commit
606d3a0c4d
@ -2,15 +2,17 @@
|
||||
// copyright-holders:cam900
|
||||
/*
|
||||
Hudson HuC6230 SoundBox
|
||||
HuC6280 PSG with ADPCM
|
||||
PSG part of HuC6280 with ADPCM
|
||||
|
||||
TODO:
|
||||
- Volume is linear?
|
||||
- Make it actually working
|
||||
- Implement CDDA Volume
|
||||
- Implement/Correct VCA (Voltage Controlled Amplifier) behavior
|
||||
|
||||
Related patent:
|
||||
- https://patents.google.com/patent/US5692099
|
||||
- https://patents.google.com/patent/US6453286
|
||||
- https://patents.google.com/patent/US5548655A
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -33,8 +35,8 @@ void huc6230_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
||||
if (!channel->m_playing)
|
||||
continue;
|
||||
|
||||
outputs[0][i] = clamp(outputs[0][i] + ((channel->m_output * channel->m_lvol) >> 2), -32768, 32767);
|
||||
outputs[1][i] = clamp(outputs[1][i] + ((channel->m_output * channel->m_rvol) >> 2), -32768, 32767);
|
||||
outputs[0][i] = clamp(outputs[0][i] + ((channel->m_output * channel->m_lvol) >> 3), -32768, 32767);
|
||||
outputs[1][i] = clamp(outputs[1][i] + ((channel->m_output * channel->m_rvol) >> 3), -32768, 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,19 +85,19 @@ WRITE8_MEMBER( huc6230_device::write )
|
||||
}
|
||||
else if (offset < 0x16)
|
||||
{
|
||||
m_cdda_lvol = data & 0x3f;
|
||||
m_cdda_cb(0, m_cdda_lvol);
|
||||
m_pcm_lvol = data & 0x3f;
|
||||
m_vca_cb(0, m_pcm_lvol);
|
||||
}
|
||||
else if (offset < 0x17)
|
||||
{
|
||||
m_cdda_rvol = data & 0x3f;
|
||||
m_cdda_cb(1, m_cdda_rvol);
|
||||
m_pcm_rvol = data & 0x3f;
|
||||
m_vca_cb(1, m_pcm_rvol);
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(huc6230_device::adpcm_timer)
|
||||
{
|
||||
int frq = (1 << m_adpcm_freq);
|
||||
const unsigned frq = (1 << m_adpcm_freq);
|
||||
for (int adpcm = 0; adpcm < 2; adpcm++)
|
||||
{
|
||||
adpcm_channel *channel = &m_adpcm_channel[adpcm];
|
||||
@ -113,7 +115,7 @@ TIMER_CALLBACK_MEMBER(huc6230_device::adpcm_timer)
|
||||
channel->m_pos++;
|
||||
channel->m_input = m_adpcm_update_cb[adpcm]();
|
||||
|
||||
if (channel->m_pos > frq)
|
||||
if (channel->m_pos >= frq)
|
||||
{
|
||||
channel->m_pos = 0;
|
||||
channel->m_prev_sample = channel->m_curr_sample;
|
||||
@ -143,10 +145,10 @@ huc6230_device::huc6230_device(const machine_config &mconfig, const char *tag, d
|
||||
, m_stream(nullptr)
|
||||
, m_psg(*this, "psg")
|
||||
, m_adpcm_freq(0)
|
||||
, m_cdda_lvol(0)
|
||||
, m_cdda_rvol(0)
|
||||
, m_pcm_lvol(0)
|
||||
, m_pcm_rvol(0)
|
||||
, m_adpcm_update_cb{{*this}, {*this}}
|
||||
, m_cdda_cb(*this)
|
||||
, m_vca_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -169,9 +171,9 @@ void huc6230_device::device_start()
|
||||
for (auto &cb : m_adpcm_update_cb)
|
||||
cb.resolve_safe(0);
|
||||
|
||||
m_cdda_cb.resolve_safe();
|
||||
m_vca_cb.resolve_safe();
|
||||
|
||||
m_stream = machine().sound().stream_alloc(*this, 2, 2, clock() / 96);
|
||||
m_stream = machine().sound().stream_alloc(*this, 2, 2, clock() / 6);
|
||||
m_adpcm_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(huc6230_device::adpcm_timer),this));
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
@ -196,13 +198,13 @@ void huc6230_device::device_start()
|
||||
save_item(NAME(m_adpcm_channel[i].m_input), i);
|
||||
}
|
||||
save_item(NAME(m_adpcm_freq));
|
||||
save_item(NAME(m_cdda_lvol));
|
||||
save_item(NAME(m_cdda_rvol));
|
||||
save_item(NAME(m_pcm_lvol));
|
||||
save_item(NAME(m_pcm_rvol));
|
||||
}
|
||||
|
||||
void huc6230_device::device_clock_changed()
|
||||
{
|
||||
m_stream->set_sample_rate(clock() / 96);
|
||||
m_stream->set_sample_rate(clock() / 6);
|
||||
attotime adpcm_period = clocks_to_attotime(682);
|
||||
m_adpcm_timer->adjust(adpcm_period, 0, adpcm_period);
|
||||
}
|
||||
|
@ -11,10 +11,12 @@
|
||||
class huc6230_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; } // Incorrect ADPCM
|
||||
|
||||
huc6230_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <unsigned N> auto adpcm_update_cb() { return m_adpcm_update_cb[N].bind(); }
|
||||
auto cdda_cb() { return m_cdda_cb.bind(); }
|
||||
auto vca_callback() { return m_vca_cb.bind(); }
|
||||
|
||||
// write only
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
@ -48,13 +50,13 @@ private:
|
||||
required_device<c6280_device> m_psg;
|
||||
adpcm_channel m_adpcm_channel[2];
|
||||
uint32_t m_adpcm_freq;
|
||||
uint32_t m_cdda_lvol;
|
||||
uint32_t m_cdda_rvol;
|
||||
uint32_t m_pcm_lvol;
|
||||
uint32_t m_pcm_rvol;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(adpcm_timer);
|
||||
|
||||
devcb_read8 m_adpcm_update_cb[2];
|
||||
devcb_write8 m_cdda_cb;
|
||||
devcb_write8 m_vca_cb;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(HuC6230, huc6230_device)
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
ADPCM related patents:
|
||||
- https://patents.google.com/patent/US5692099
|
||||
- https://patents.google.com/patent/US6453286
|
||||
- https://patents.google.com/patent/US5548655A
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -497,9 +499,9 @@ uint8_t huc6272_device::adpcm_update(int chan)
|
||||
if (!m_adpcm.playing[chan])
|
||||
return 0;
|
||||
|
||||
int rate = (1 << m_adpcm.rate);
|
||||
const unsigned rate = (1 << m_adpcm.rate);
|
||||
m_adpcm.pos[chan]++;
|
||||
if (m_adpcm.pos[chan] > rate)
|
||||
if (m_adpcm.pos[chan] >= rate)
|
||||
{
|
||||
if (m_adpcm.input[chan] == -1)
|
||||
{
|
||||
@ -541,6 +543,7 @@ uint8_t huc6272_device::adpcm_update(int chan)
|
||||
if (m_adpcm.nibble[chan] >= 28)
|
||||
m_adpcm.input[chan] = -1;
|
||||
}
|
||||
m_adpcm.pos[chan] = 0;
|
||||
}
|
||||
|
||||
return (m_adpcm.input[chan] >> m_adpcm.nibble[chan]) & 0xf;
|
||||
|
@ -27,6 +27,8 @@ class huc6272_device : public device_t,
|
||||
public device_memory_interface
|
||||
{
|
||||
public:
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND | feature::GRAPHICS; } // Incorrect ADPCM and Graphics
|
||||
|
||||
// construction/destruction
|
||||
huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
|
@ -455,7 +455,7 @@ void pcfx_state::pcfx(machine_config &config)
|
||||
huc6230_device &huc6230(HuC6230(config, "huc6230", XTAL(21'477'272)));
|
||||
huc6230.adpcm_update_cb<0>().set("huc6272", FUNC(huc6272_device::adpcm_update_0));
|
||||
huc6230.adpcm_update_cb<1>().set("huc6272", FUNC(huc6272_device::adpcm_update_1));
|
||||
huc6230.cdda_cb().set("huc6272", FUNC(huc6272_device::cdda_update));
|
||||
huc6230.vca_callback().set("huc6272", FUNC(huc6272_device::cdda_update));
|
||||
huc6230.add_route(0, "lspeaker", 1.0);
|
||||
huc6230.add_route(1, "rspeaker", 1.0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user