summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Couriersud <couriersud@users.noreply.github.com>2009-08-29 18:30:19 +0000
committer Couriersud <couriersud@users.noreply.github.com>2009-08-29 18:30:19 +0000
commit68d94c232d309bee7ba83f600e5e26e40581aedc (patch)
treecbc13932ef6c0d4fae8a791ed4fb174a3db26dd1
parent98a7eb3c8dc359be36e7a3fa7d902997d72df900 (diff)
discrete sound system
- some more "list-ification" - No more constraints on number of input and output nodes - input nodes now make use of a context Some of these changes are needed to introduce "internally buffered" input nodes going forward. These will use an internal stream to buffer all inputs so that stream_update will always calculate 20ms of samples.
-rw-r--r--src/emu/sound/disc_inp.c68
-rw-r--r--src/emu/sound/discrete.c111
-rw-r--r--src/emu/sound/discrete.h28
3 files changed, 120 insertions, 87 deletions
diff --git a/src/emu/sound/disc_inp.c b/src/emu/sound/disc_inp.c
index 52882a8d8fc..8258d6b3fd4 100644
--- a/src/emu/sound/disc_inp.c
+++ b/src/emu/sound/disc_inp.c
@@ -31,6 +31,18 @@ struct dss_adjustment_context
double scale;
};
+struct dss_input_context
+{
+ stream_sample_t *ptr; /* current in ptr for stream */
+ UINT8 data; /* data written */
+ double gain; /* node gain */
+ double offset; /* node offset */
+ UINT8 is_stream;
+ UINT8 is_buffered;
+ UINT32 stream_in_number;
+ UINT32 stream_out_number;
+};
+
INLINE discrete_info *get_safe_token(const device_config *device)
{
assert(device != NULL);
@@ -50,14 +62,14 @@ READ8_DEVICE_HANDLER(discrete_sound_r)
/* Read the node input value if allowed */
if (node)
{
- UINT8 *node_data = (UINT8 *)node->context;
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
/* Bring the system up to now */
stream_update(info->discrete_stream);
if ((node->module->type >= DSS_INPUT_DATA) && (node->module->type <= DSS_INPUT_PULSE))
{
- data = *node_data;
+ data = context->data;
}
}
else
@@ -75,8 +87,7 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
/* Update the node input value if it's a proper input node */
if (node)
{
- UINT8 *node_data = (UINT8 *)node->context;
- UINT8 last_data = *node_data;
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
UINT8 new_data = 0;
switch (node->module->type)
@@ -93,15 +104,15 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
break;
}
- if (last_data != new_data)
+ if (context->data != new_data)
{
/* Bring the system up to now */
stream_update(info->discrete_stream);
- *node_data = new_data;
+ context->data = new_data;
/* Update the node output here so we don't have to do it each step */
- node->output[0] = *node_data * DSS_INPUT__GAIN + DSS_INPUT__OFFSET;
+ node->output[0] = new_data * context->gain + context->offset;
}
}
else
@@ -217,33 +228,38 @@ static DISCRETE_RESET(dss_constant)
************************************************************************/
static DISCRETE_RESET(dss_input)
{
- UINT8 *node_data = (UINT8 *)node->context;
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
+
+ context->is_buffered = FALSE;
+ context->is_stream = FALSE;
+ context->gain = DSS_INPUT__GAIN;
+ context->offset = DSS_INPUT__OFFSET;
switch (node->module->type)
{
case DSS_INPUT_DATA:
- *node_data = DSS_INPUT__INIT;
+ context->data = DSS_INPUT__INIT;
break;
case DSS_INPUT_LOGIC:
case DSS_INPUT_PULSE:
- *node_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
+ context->data = (DSS_INPUT__INIT == 0) ? 0 : 1;
break;
case DSS_INPUT_NOT:
- *node_data = (DSS_INPUT__INIT == 0) ? 1 : 0;
+ context->data = (DSS_INPUT__INIT == 0) ? 1 : 0;
break;
}
- node->output[0] = *node_data * DSS_INPUT__GAIN + DSS_INPUT__OFFSET;
+ node->output[0] = context->data * context->gain + context->offset;
}
static DISCRETE_STEP(dss_input_pulse)
{
- UINT8 *node_data = (UINT8 *)node->context;
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
/* Set a valid output */
- node->output[0] = *node_data;
+ node->output[0] = context->data;
/* Reset the input to default for the next cycle */
/* node order is now important */
- *node_data = DSS_INPUT__INIT;
+ context->data = DSS_INPUT__INIT;
}
@@ -263,13 +279,12 @@ static DISCRETE_STEP(dss_input_pulse)
static DISCRETE_STEP(dss_input_stream)
{
/* the context pointer is set to point to the current input stream data in discrete_stream_update */
- stream_sample_t **ptr = (stream_sample_t **)node->context;
- stream_sample_t *data = *ptr;
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
- if (data)
+ if (context->ptr)
{
- node->output[0] = (*data) * DSS_INPUT_STREAM__GAIN + DSS_INPUT_STREAM__OFFSET;
- (*ptr)++;
+ node->output[0] = (*context->ptr) * context->gain + context->offset;
+ context->ptr++;
}
else
node->output[0] = 0;
@@ -277,8 +292,13 @@ static DISCRETE_STEP(dss_input_stream)
static DISCRETE_RESET(dss_input_stream)
{
- int istream = DSS_INPUT_STREAM__STREAM;
- /* we will use the node's context pointer to point to the input stream data */
- assert(istream < node->info->discrete_input_streams);
- node->context = (discrete_info *) &node->info->input_stream_data[istream];
+ struct dss_input_context *context = (struct dss_input_context *)node->context;
+
+ assert(DSS_INPUT_STREAM__STREAM < linked_list_count(node->info->input_list));
+ context->is_buffered = FALSE;
+ context->is_stream = TRUE;
+ context->stream_in_number = DSS_INPUT_STREAM__STREAM;
+ context->gain = DSS_INPUT_STREAM__GAIN;
+ context->offset = DSS_INPUT_STREAM__OFFSET;
+ context->ptr = NULL;
}
diff --git a/src/emu/sound/discrete.c b/src/emu/sound/discrete.c
index 1657043e922..c7e35012339 100644
--- a/src/emu/sound/discrete.c
+++ b/src/emu/sound/discrete.c
@@ -169,6 +169,39 @@ static DISCRETE_RESET( dso_output )
/* nothing to do - just avoid being stepped */
}
+
+/*************************************
+ *
+ * Add an entry to a list
+ *
+ *************************************/
+
+static void linked_list_add(discrete_info *info, linked_list_entry ***list_tail_ptr, void *ptr)
+{
+ **list_tail_ptr = auto_alloc(info->device->machine, linked_list_entry);
+ (**list_tail_ptr)->ptr = ptr;
+ (**list_tail_ptr)->next = NULL;
+ *list_tail_ptr = &((**list_tail_ptr)->next);
+}
+
+/*************************************
+ *
+ * Count entries in a list
+ *
+ *************************************/
+
+static int linked_list_count(linked_list_entry *list)
+{
+ int cnt = 0;
+ linked_list_entry *entry;
+
+ for (entry = list; entry != NULL; entry = entry->next)
+ cnt++;
+
+ return cnt;
+}
+
+
/*************************************
*
* Included simulation objects
@@ -191,7 +224,7 @@ static DISCRETE_RESET( dso_output )
static const discrete_module module_list[] =
{
- { DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,sizeof(0) ,dso_output_reset ,dso_output_step },
+ { DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,0 ,dso_output_reset ,dso_output_step },
{ DSO_CSVLOG ,"DSO_CSVLOG" , 0 ,0 ,NULL ,NULL },
{ DSO_WAVELOG ,"DSO_WAVELOG" , 0 ,0 ,NULL ,NULL },
{ DSO_IMPORT ,"DSO_IMPORT" , 0 ,0 ,NULL ,NULL },
@@ -207,11 +240,11 @@ static const discrete_module module_list[] =
/* from disc_inp.c */
{ DSS_ADJUSTMENT ,"DSS_ADJUSTMENT" , 1 ,sizeof(struct dss_adjustment_context) ,dss_adjustment_reset ,dss_adjustment_step },
{ DSS_CONSTANT ,"DSS_CONSTANT" , 1 ,0 ,dss_constant_reset ,NULL },
- { DSS_INPUT_DATA ,"DSS_INPUT_DATA" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL },
- { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL },
- { DSS_INPUT_NOT ,"DSS_INPUT_NOT" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL },
- { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(UINT8) ,dss_input_reset ,dss_input_pulse_step },
- { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,0 ,dss_input_stream_reset,dss_input_stream_step},
+ { DSS_INPUT_DATA ,"DSS_INPUT_DATA" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL },
+ { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL },
+ { DSS_INPUT_NOT ,"DSS_INPUT_NOT" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL },
+ { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,dss_input_pulse_step },
+ { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,sizeof(struct dss_input_context) ,dss_input_stream_reset,dss_input_stream_step},
/* from disc_wav.c */
/* Generic modules */
@@ -306,20 +339,6 @@ static const discrete_module module_list[] =
/*************************************
*
- * Add an entry to a list
- *
- *************************************/
-
-static void add_list(discrete_info *info, linked_list_entry ***list, void *ptr)
-{
- **list = auto_alloc(info->device->machine, linked_list_entry);
- (**list)->ptr = ptr;
- (**list)->next = NULL;
- *list = &((**list)->next);
-}
-
-/*************************************
- *
* Find a given node
*
*************************************/
@@ -396,7 +415,7 @@ static void discrete_build_list(discrete_info *info, discrete_sound_block *intf,
else
{
discrete_log(info, "discrete_build_list() - adding node %d (*current %p)\n", node_count, *current);
- add_list(info, current, &intf[node_count]);
+ linked_list_add(info, current, &intf[node_count]);
}
node_count++;
@@ -482,6 +501,8 @@ static DEVICE_START( discrete )
/* Start with empty lists */
info->node_list = NULL;
info->step_list = NULL;
+ info->output_list = NULL;
+ info->input_list = NULL;
/* allocate memory to hold pointers to nodes by index */
info->indexed_node = auto_alloc_array_clear(device->machine, node_description *, DISCRETE_MAX_NODES);
@@ -494,7 +515,7 @@ static DEVICE_START( discrete )
/* then set up the output nodes */
/* initialize the stream(s) */
- info->discrete_stream = stream_create(device, info->discrete_input_streams, info->discrete_outputs, info->sample_rate, info, discrete_stream_update);
+ info->discrete_stream = stream_create(device,linked_list_count(info->input_list), linked_list_count(info->output_list), info->sample_rate, info, discrete_stream_update);
/* allocate a queue */
@@ -749,22 +770,22 @@ static STREAM_UPDATE( discrete_stream_update )
{
discrete_info *info = (discrete_info *)param;
linked_list_entry *entry;
- int samplenum, nodenum, outputnum;
- //int j; int left; int run;
+ int samplenum, outputnum;
if (samples == 0)
return;
/* Setup any output streams */
- for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
+ for (entry = info->output_list, outputnum = 0; entry != NULL; entry = entry->next, outputnum++)
{
- info->output_node[outputnum]->context = (void *) outputs[outputnum];
+ ((node_description *) entry->ptr)->context = (void *) outputs[outputnum];
}
/* Setup any input streams */
- for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
+ for (entry = info->input_list; entry != NULL; entry = entry->next)
{
- info->input_stream_data[nodenum] = inputs[nodenum];
+ struct dss_input_context *context = (struct dss_input_context *) ((node_description *) entry->ptr)->context;
+ context->ptr = (void *) inputs[context->stream_in_number];
}
for (entry = info->task_list; entry != 0; entry = entry->next)
@@ -812,17 +833,15 @@ static STREAM_UPDATE( discrete_stream_update )
static void init_nodes(discrete_info *info, linked_list_entry *block_list, const device_config *device)
{
- linked_list_entry **step_list = &info->step_list;
- linked_list_entry **node_list = &info->node_list;
- linked_list_entry **task_list = &info->task_list;
linked_list_entry **cur_task_node = NULL;
linked_list_entry *entry;
discrete_task_context *task = NULL;
-
- /* start with no outputs or input streams */
-
- info->discrete_outputs = 0;
- info->discrete_input_streams = 0;
+ /* list tail pointers */
+ linked_list_entry **step_list = &info->step_list;
+ linked_list_entry **node_list = &info->node_list;
+ linked_list_entry **task_list = &info->task_list;
+ linked_list_entry **output_list = &info->output_list;
+ linked_list_entry **input_list = &info->input_list;
/* loop over all nodes */
for (entry = block_list; entry != NULL; entry = entry->next)
@@ -854,9 +873,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
{
/* Output Node */
case DSO_OUTPUT:
- if (info->discrete_outputs == DISCRETE_MAX_OUTPUTS)
- fatalerror("init_nodes() - There can not be more then %d output nodes", DISCRETE_MAX_OUTPUTS);
- info->output_node[info->discrete_outputs++] = node;
+ linked_list_add(info, &output_list, node);
break;
/* CSVlog Node for debugging */
@@ -878,7 +895,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
if (cur_task_node != NULL)
fatalerror("init_nodes() - Nested DISCRETE_START_TASK.");
task = auto_alloc_clear(info->device->machine, discrete_task_context);
- add_list(info, &task_list, task);
+ linked_list_add(info, &task_list, task);
cur_task_node = &task->list;
break;
@@ -924,15 +941,11 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
/* if we are an stream input node, track that */
if (block->type == DSS_INPUT_STREAM)
{
- if (info->discrete_input_streams == DISCRETE_MAX_OUTPUTS)
- fatalerror("init_nodes() - There can not be more then %d input stream nodes", DISCRETE_MAX_OUTPUTS);
-
- node->context = NULL;
- info->discrete_input_streams++;
+ linked_list_add(info, &input_list, node);
}
/* add to node list */
- add_list(info, &node_list, node);
+ linked_list_add(info, &node_list, node);
/* our running order just follows the order specified */
/* does the node step ? */
@@ -940,9 +953,9 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
{
/* do we belong to a task? */
if (cur_task_node == NULL)
- add_list(info, &step_list, node);
+ linked_list_add(info, &step_list, node);
else
- add_list(info, &cur_task_node, node);
+ linked_list_add(info, &cur_task_node, node);
}
if (block->type == DSO_TASK_END)
@@ -956,7 +969,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
}
/* if no outputs, give an error */
- if (info->discrete_outputs == 0)
+ if (linked_list_count(info->output_list) == 0)
fatalerror("init_nodes() - Couldn't find an output node");
}
diff --git a/src/emu/sound/discrete.h b/src/emu/sound/discrete.h
index 4f629ee5dff..4c208bd3842 100644
--- a/src/emu/sound/discrete.h
+++ b/src/emu/sound/discrete.h
@@ -438,8 +438,12 @@
* Note: The discrete system is floating point based. So when routing a stream
* set it's gain to 100% and then use DISCRETE_INPUTX_STREAM to adjust
* it if needed.
+ * If you need to access a stream from a discrete task, the stream node
+ * must be part of that task. If a given stream is used in two tasks or
+ * a task and the main task, you must declare two stream nodes acccessing the
+ * same stream input NUM.
*
- * EXAMPLES: see
+ * EXAMPLES: see scramble, frogger
*
***********************************************************************
=======================================================================
@@ -3371,10 +3375,9 @@
#define DISCRETE_MAX_NODES 300
#define DISCRETE_MAX_INPUTS 10
-#define DISCRETE_MAX_OUTPUTS 16
#define DISCRETE_MAX_WAVELOGS 10
#define DISCRETE_MAX_CSVLOGS 10
-#define DISCRETE_MAX_NODE_OUTPUTS 8
+#define DISCRETE_MAX_OUTPUTS 8
/*************************************
@@ -3625,7 +3628,7 @@ struct _discrete_module
struct _node_description
{
int node; /* The node's index number in the node list */
- double output[DISCRETE_MAX_NODE_OUTPUTS]; /* The node's last output value */
+ double output[DISCRETE_MAX_OUTPUTS]; /* The node's last output value */
int active_inputs; /* Number of active inputs on this node type */
int input_is_node; /* Bit Flags. 1 in bit location means input_is_node */
@@ -3667,7 +3670,6 @@ struct _discrete_task_context
double *ptr;
double node_buf[2048];
double **dest;
- volatile INT32 active;
};
struct _discrete_info
@@ -3695,12 +3697,10 @@ struct _discrete_info
linked_list_entry *task_list; /* discrete_task_context * */
/* the input streams */
- int discrete_input_streams;
- stream_sample_t *input_stream_data[DISCRETE_MAX_OUTPUTS];
+ linked_list_entry *input_list;
/* output node tracking */
- int discrete_outputs;
- node_description *output_node[DISCRETE_MAX_OUTPUTS];
+ linked_list_entry *output_list;
/* the output stream */
sound_stream *discrete_stream;
@@ -4024,10 +4024,10 @@ struct _discrete_inverter_osc_desc
*
*************************************/
-#define NODE0_DEF(_x) NODE_ ## 0 ## _x = (0x40000000 + (_x) * DISCRETE_MAX_NODE_OUTPUTS), \
+#define NODE0_DEF(_x) NODE_ ## 0 ## _x = (0x40000000 + (_x) * DISCRETE_MAX_OUTPUTS), \
NODE_ ## 0 ## _x ## _01, NODE_ ## 0 ## _x ## _02, NODE_ ## 0 ## _x ## _03, NODE_ ## 0 ## _x ## _04, \
NODE_ ## 0 ## _x ## _05, NODE_ ## 0 ## _x ## _06, NODE_ ## 0 ## _x ## _07
-#define NODE_DEF(_x) NODE_ ## _x = (0x40000000 + (_x) * DISCRETE_MAX_NODE_OUTPUTS), \
+#define NODE_DEF(_x) NODE_ ## _x = (0x40000000 + (_x) * DISCRETE_MAX_OUTPUTS), \
NODE_ ## _x ## _01, NODE_ ## _x ## _02, NODE_ ## _x ## _03, NODE_ ## _x ## _04, \
NODE_ ## _x ## _05, NODE_ ## _x ## _06, NODE_ ## _x ## _07
@@ -4066,15 +4066,15 @@ enum {
/* Some Pre-defined nodes for convenience */
-#define NODE(_x) (NODE_00 + (_x) * DISCRETE_MAX_NODE_OUTPUTS)
+#define NODE(_x) (NODE_00 + (_x) * DISCRETE_MAX_OUTPUTS)
#define NODE_SUB(_x, _y) (NODE(_x) + (_y))
-#if DISCRETE_MAX_NODE_OUTPUTS == 8
+#if DISCRETE_MAX_OUTPUTS == 8
#define NODE_CHILD_NODE_NUM(_x) ((int)(_x) & 7)
#define NODE_DEFAULT_NODE(_x) ((int)(_x) & ~7)
#define NODE_INDEX(_x) (((int)(_x) - NODE_START)>>3)
#else
-#error "DISCRETE_MAX_NODE_OUTPUTS != 8"
+#error "DISCRETE_MAX_OUTPUTS != 8"
#endif
#define NODE_RELATIVE(_x, _y) (NODE(NODE_INDEX(_x) + (_y)))