mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
Created a mame sound device for netlist. Fixed an issue causing wild oscillations. Currently, pong has sample code for using the sound device. Uncomment "TEST_SOUND" in pong.c to hear a constant sound from a 7400 multivibrator. Sound is still WIP, but the proof of concept has been done. [Couriersud]
This commit is contained in:
parent
1af170a360
commit
a1b3437fc4
@ -56,6 +56,7 @@
|
||||
|
||||
const device_type NETLIST_CORE = &device_creator<netlist_mame_device_t>;
|
||||
const device_type NETLIST_CPU = &device_creator<netlist_mame_cpu_device_t>;
|
||||
const device_type NETLIST_SOUND = &device_creator<netlist_mame_sound_device_t>;
|
||||
const device_type NETLIST_ANALOG_INPUT = &device_creator<netlist_mame_analog_input_t>;
|
||||
const device_type NETLIST_LOGIC_INPUT = &device_creator<netlist_mame_logic_input_t>;
|
||||
|
||||
@ -187,7 +188,7 @@ void netlist_mame_device_t::device_start()
|
||||
|
||||
// register additional devices
|
||||
|
||||
m_setup->factory().register_device<nld_analog_callback>( "NETDEV_CALLBACK", "nld_analog_callback", "-");
|
||||
nl_register_devices();
|
||||
|
||||
m_setup_func(*m_setup);
|
||||
|
||||
@ -351,6 +352,12 @@ void netlist_mame_cpu_device_t::device_start()
|
||||
m_icountptr = &m_icount;
|
||||
}
|
||||
|
||||
|
||||
void netlist_mame_cpu_device_t::nl_register_devices()
|
||||
{
|
||||
setup().factory().register_device<nld_analog_callback>( "NETDEV_CALLBACK", "nld_analog_callback", "-");
|
||||
}
|
||||
|
||||
ATTR_COLD UINT64 netlist_mame_cpu_device_t::execute_clocks_to_cycles(UINT64 clocks) const
|
||||
{
|
||||
return clocks;
|
||||
@ -404,3 +411,73 @@ ATTR_HOT void netlist_mame_cpu_device_t::execute_run()
|
||||
update_time_x();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_mame_sound_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_mame_sound_device_t::netlist_mame_sound_device_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: netlist_mame_device_t(mconfig, NETLIST_CPU, "Netlist sound device", tag, owner, clock, "netlist_sound", __FILE__),
|
||||
device_sound_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void netlist_mame_sound_device_t::device_start()
|
||||
{
|
||||
netlist_mame_device_t::device_start();
|
||||
|
||||
LOG_DEV_CALLS(("device_start %s\n", tag()));
|
||||
|
||||
netlist_list_t<nld_sound *> outdevs = netlist().get_device_list<nld_sound *>();
|
||||
if (outdevs.count() == 0)
|
||||
fatalerror("No output devices");
|
||||
|
||||
m_num_outputs = outdevs.count();
|
||||
m_num_inputs = 0;
|
||||
|
||||
/* resort channels */
|
||||
for (int i=0; i < MAX_OUT; i++) m_out[i] = NULL;
|
||||
for (int i=0; i < m_num_outputs; i++)
|
||||
{
|
||||
int chan = outdevs[i]->m_channel.Value();
|
||||
if (chan < 0 || chan >= MAX_OUT || chan >= outdevs.count())
|
||||
fatalerror("illegal channel number");
|
||||
m_out[chan] = outdevs[i];
|
||||
m_out[chan]->m_sample = netlist_time::from_hz(clock());
|
||||
m_out[chan]->m_buffer = NULL;
|
||||
}
|
||||
|
||||
/* initialize the stream(s) */
|
||||
m_stream = machine().sound().stream_alloc(*this, m_num_inputs, m_num_outputs, clock());
|
||||
|
||||
}
|
||||
|
||||
void netlist_mame_sound_device_t::nl_register_devices()
|
||||
{
|
||||
setup().factory().register_device<nld_sound>( "NETDEV_SOUND_OUT", "nld_sound", "+CHAN");
|
||||
}
|
||||
|
||||
|
||||
void netlist_mame_sound_device_t::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
for (int i=0; i < m_num_outputs; i++)
|
||||
{
|
||||
m_out[i]->m_buffer = outputs[i];
|
||||
}
|
||||
|
||||
netlist_time cur = netlist().time();
|
||||
|
||||
//printf("current time %f\n", netlist().time().as_double());
|
||||
|
||||
netlist().process_queue(netlist_time::from_raw(m_div) * samples);
|
||||
|
||||
cur += (netlist_time::from_raw(m_div) * samples);
|
||||
|
||||
for (int i=0; i < m_num_outputs; i++)
|
||||
{
|
||||
m_out[i]->sound_update(cur);
|
||||
m_out[i]->buffer_reset(cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,13 +56,6 @@
|
||||
|
||||
// MAME specific configuration
|
||||
|
||||
#define MCFG_NETLIST_ADD(_tag, _setup, _clock ) \
|
||||
MCFG_DEVICE_ADD(_tag, NETLIST_CPU, _clock) \
|
||||
MCFG_NETLIST_SETUP(_setup)
|
||||
|
||||
#define MCFG_NETLIST_REPLACE(_tag, _setup) \
|
||||
MCFG_DEVICE_REPLACE(_tag, NETLIST_CPU, NETLIST_CLOCK) \
|
||||
MCFG_NETLIST_SETUP(_setup)
|
||||
|
||||
#define MCFG_NETLIST_SETUP(_setup) \
|
||||
netlist_mame_device_t::static_set_constructor(*device, NETLIST_NAME(_setup));
|
||||
@ -102,6 +95,11 @@
|
||||
#define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \
|
||||
void _name(const double data, const attotime &time)
|
||||
|
||||
#define NETDEV_SOUND_OUT(_name, _v) \
|
||||
NET_REGISTER_DEV(sound, _name) \
|
||||
NETDEV_PARAM(_name.CHAN, _v)
|
||||
|
||||
|
||||
class netlist_mame_device_t;
|
||||
|
||||
class netlist_mame_t : public netlist_base_t
|
||||
@ -155,7 +153,11 @@ public:
|
||||
int m_icount;
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
// Custom to netlist ...
|
||||
|
||||
virtual void nl_register_devices() { };
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_stop();
|
||||
@ -205,7 +207,11 @@ public:
|
||||
static void static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &));
|
||||
|
||||
protected:
|
||||
// netlist_mame_device_t
|
||||
virtual void nl_register_devices();
|
||||
|
||||
// device_t overrides
|
||||
|
||||
//virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
//virtual void device_stop();
|
||||
@ -259,6 +265,51 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class nld_sound;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_mame_sound_device_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
class netlist_mame_sound_device_t : public netlist_mame_device_t,
|
||||
public device_sound_interface
|
||||
{
|
||||
public:
|
||||
|
||||
// construction/destruction
|
||||
netlist_mame_sound_device_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~netlist_mame_sound_device_t() {}
|
||||
|
||||
static void static_set_constructor(device_t &device, void (*setup_func)(netlist_setup_t &));
|
||||
|
||||
// device_sound_interface overrides
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
|
||||
protected:
|
||||
// netlist_mame_device_t
|
||||
virtual void nl_register_devices();
|
||||
|
||||
// device_t overrides
|
||||
|
||||
//virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
//virtual void device_stop();
|
||||
//virtual void device_reset();
|
||||
//virtual void device_post_load();
|
||||
//virtual void device_pre_save();
|
||||
//virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
private:
|
||||
|
||||
static const int MAX_OUT = 10;
|
||||
nld_sound *m_out[MAX_OUT];
|
||||
sound_stream *m_stream;
|
||||
int m_num_inputs;
|
||||
int m_num_outputs;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// netlist_mame_sub_interface
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -407,6 +458,8 @@ public:
|
||||
ATTR_COLD void start()
|
||||
{
|
||||
register_input("IN", m_in);
|
||||
register_param("CHAN", m_channel, 0);
|
||||
m_sample = netlist_time::from_hz(1); //sufficiently big enough
|
||||
}
|
||||
|
||||
ATTR_COLD void reset()
|
||||
@ -414,13 +467,11 @@ public:
|
||||
m_cur = 0;
|
||||
m_last_pos = 0;
|
||||
m_last_buffer = netlist_time::zero;
|
||||
m_sample = netlist_time::zero; // FIXME: divide by zero
|
||||
}
|
||||
|
||||
ATTR_HOT void sound_update()
|
||||
ATTR_HOT void sound_update(const netlist_time upto)
|
||||
{
|
||||
netlist_time current = netlist().time();
|
||||
int pos = (current - m_last_buffer) / m_sample;
|
||||
int pos = (upto - m_last_buffer) / m_sample;
|
||||
if (pos >= BUFSIZE)
|
||||
netlist().error("sound %s: exceeded BUFSIZE\n", name().cstr());
|
||||
while (m_last_pos < pos )
|
||||
@ -432,23 +483,32 @@ public:
|
||||
ATTR_HOT void update()
|
||||
{
|
||||
double val = INPANALOG(m_in);
|
||||
sound_update();
|
||||
m_cur = val;
|
||||
sound_update(netlist().time());
|
||||
m_cur = val * 1000;
|
||||
}
|
||||
|
||||
ATTR_HOT void buffer_reset(netlist_time upto)
|
||||
{
|
||||
m_last_pos = 0;
|
||||
m_last_buffer = upto;
|
||||
}
|
||||
|
||||
netlist_param_int_t m_channel;
|
||||
stream_sample_t *m_buffer;
|
||||
netlist_time m_sample;
|
||||
|
||||
private:
|
||||
netlist_analog_input_t m_in;
|
||||
netlist_time m_sample;
|
||||
double m_cur;
|
||||
stream_sample_t m_cur;
|
||||
int m_last_pos;
|
||||
netlist_time m_last_buffer;
|
||||
stream_sample_t m_buffer[BUFSIZE];
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type NETLIST_CORE;
|
||||
extern const device_type NETLIST_CPU;
|
||||
extern const device_type NETLIST_SOUND;
|
||||
extern const device_type NETLIST_ANALOG_INPUT;
|
||||
extern const device_type NETLIST_LOGIC_INPUT;
|
||||
|
||||
|
@ -153,6 +153,19 @@ ATTR_HOT inline bool netlist_matrix_solver_t::solve()
|
||||
|
||||
m_resched = false;
|
||||
|
||||
if (USE_ALTERNATE_SCHEDULING)
|
||||
{
|
||||
netlist_time now = owner().netlist().time();
|
||||
netlist_time delta = now - m_last_step;
|
||||
if (delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
m_last_step = now;
|
||||
step(delta);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dynamic())
|
||||
{
|
||||
int this_resched;
|
||||
@ -202,6 +215,10 @@ ATTR_HOT void netlist_matrix_solver_t::schedule()
|
||||
// update_inputs();
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_matrix_solver_t::reset()
|
||||
{
|
||||
m_last_step = netlist_time::zero;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// solver
|
||||
@ -272,6 +289,8 @@ NETLIB_START(solver)
|
||||
NETLIB_RESET(solver)
|
||||
{
|
||||
m_last_step = netlist_time::zero;
|
||||
for (int i = 0; i < m_mat_solvers.count(); i++)
|
||||
m_mat_solvers[i]->reset();
|
||||
}
|
||||
|
||||
|
||||
@ -300,7 +319,11 @@ NETLIB_UPDATE(solver)
|
||||
bool global_resched = false;
|
||||
bool this_resched[100];
|
||||
|
||||
if (delta >= m_inc)
|
||||
if (delta < m_inc)
|
||||
do_full = true; // we have been called between updates
|
||||
|
||||
//FIXME: make this a parameter
|
||||
if (!USE_ALTERNATE_SCHEDULING && delta >= netlist_time::from_nsec(5)) // always update capacitors
|
||||
{
|
||||
NL_VERBOSE_OUT(("Step!\n"));
|
||||
/* update all terminals for new time step */
|
||||
@ -309,8 +332,7 @@ NETLIB_UPDATE(solver)
|
||||
{
|
||||
(*e)->step(delta);
|
||||
}
|
||||
} else
|
||||
do_full = true; // we have been called inbetween updates
|
||||
}
|
||||
|
||||
|
||||
#if HAS_OPENMP && USE_OPENMP
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; }
|
||||
|
||||
ATTR_HOT inline const NETLIB_NAME(solver) &owner() const;
|
||||
ATTR_COLD void reset();
|
||||
|
||||
double m_accuracy;
|
||||
double m_convergence_factor;
|
||||
@ -57,6 +58,7 @@ private:
|
||||
netlist_core_terminal_t::list_t m_inps;
|
||||
dev_list_t m_steps;
|
||||
bool m_resched;
|
||||
netlist_time m_last_step;
|
||||
|
||||
NETLIB_NAME(solver) *m_owner;
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ NETLIB_START(C)
|
||||
|
||||
NETLIB_UPDATE_PARAM(C)
|
||||
{
|
||||
//step_time(1e-9);
|
||||
step_time(1.0/48000.0);
|
||||
}
|
||||
|
||||
NETLIB_UPDATE(C)
|
||||
|
@ -1067,6 +1067,19 @@ public:
|
||||
|
||||
ATTR_COLD void error(const char *format, ...) const;
|
||||
|
||||
template<class _C>
|
||||
netlist_list_t<_C> get_device_list()
|
||||
{
|
||||
netlist_list_t<_C> tmp;
|
||||
for (tagmap_devices_t::entry_t *entry = m_devices.first(); entry != NULL; entry = m_devices.next(entry))
|
||||
{
|
||||
_C dev = dynamic_cast<_C>(entry->object());
|
||||
if (dev != NULL)
|
||||
tmp.add(dev);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
tagmap_devices_t m_devices;
|
||||
netlist_net_t::list_t m_nets;
|
||||
|
||||
|
@ -20,6 +20,8 @@ TODO:
|
||||
#include "video/fixfreq.h"
|
||||
#include "astring.h"
|
||||
|
||||
//#define TEST_SOUND
|
||||
|
||||
/*
|
||||
* H count width to 512
|
||||
* Reset at 1C6 = 454
|
||||
@ -705,6 +707,34 @@ static NETLIST_START(pong_fast)
|
||||
|
||||
NETLIST_END()
|
||||
|
||||
#ifdef TESTSOUND
|
||||
static NETLIST_START(test)
|
||||
|
||||
/*
|
||||
* Astable multivibrator using two 7400 gates (or inverters)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard stuff */
|
||||
|
||||
NETDEV_SOLVER(Solver)
|
||||
NETDEV_PARAM(Solver.FREQ, 48000)
|
||||
|
||||
// astable NAND Multivibrator
|
||||
NETDEV_R(R1, 1000)
|
||||
NETDEV_C(C1, 1e-6)
|
||||
TTL_7400_NAND(n1,R1.1,R1.1)
|
||||
TTL_7400_NAND(n2,R1.2,R1.2)
|
||||
NET_C(n1.Q, R1.2)
|
||||
NET_C(n2.Q, C1.1)
|
||||
NET_C(C1.2, R1.1)
|
||||
|
||||
NETDEV_SOUND_OUT(CH0, 0)
|
||||
NET_C(CH0.IN, n2.Q)
|
||||
|
||||
NETLIST_END()
|
||||
#endif
|
||||
|
||||
void pong_state::machine_start()
|
||||
{
|
||||
}
|
||||
@ -758,8 +788,9 @@ INPUT_PORTS_END
|
||||
static MACHINE_CONFIG_START( pong, pong_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
//MCFG_NETLIST_ADD("maincpu", pong, MASTER_CLOCK * 8)
|
||||
MCFG_NETLIST_ADD("maincpu", pong, NETLIST_CLOCK)
|
||||
MCFG_DEVICE_ADD("maincpu", NETLIST_CPU, NETLIST_CLOCK)
|
||||
MCFG_NETLIST_SETUP(pong)
|
||||
|
||||
MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr0", "ic_b9_R.R")
|
||||
MCFG_NETLIST_ANALOG_INPUT_MULT_OFFSET(1.0 / 100.0 * RES_K(50), RES_K(56) )
|
||||
MCFG_NETLIST_ANALOG_INPUT("maincpu", "vr1", "ic_a9_R.R")
|
||||
@ -782,6 +813,12 @@ static MACHINE_CONFIG_START( pong, pong_state )
|
||||
MCFG_SOUND_ADD("dac", DAC, 48000)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
|
||||
#ifdef TEST_SOUND
|
||||
MCFG_SOUND_ADD("snd_test", NETLIST_SOUND, 24000)
|
||||
MCFG_NETLIST_SETUP(test)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
#endif
|
||||
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( pongf, pong )
|
||||
|
Loading…
Reference in New Issue
Block a user