Discrete sound parallel tasks

Introduced DISCRETE_TASK_START, DISCRETE_TASK_END

DISCRETE_TASK_START
- Start a new task. A task is a set of nodes which only depend on input nodes and nodes in the set

DISCRETE_TASK_END(task_output_node)
- Marks the end of the task. task_output_node is the node whose output over time should be preserved. This node can be accessed by nodes in the main thread.

Order of execution:
a) All tasks in parallel
b) All nodes not part of a task. These may only refer to nodes listed in DISCRETE_TASK_END

Illustrated the concept in the dkong discrete emulation. This also has been enhanced to buffer DAC output. 

Further changes:
- DISCRETE_OUTPUT now is a stepping node.
- DISCRETE_STREAM_INPUT now advances input pointer in step.
- More linked_list usage.

I estimate that the rework without tasks leads to a 5% performance gain. For dkong, the usage of tasks adds another 15%.
There are some features missing:
- Multiple nodes in DISCRETE_TASK_END
- More task consistency checks
- Task identifiers for tasks
This commit is contained in:
Couriersud 2009-08-25 23:29:31 +00:00
parent 05730aa0a1
commit dd836ed4d5
6 changed files with 290 additions and 134 deletions

View File

@ -1070,6 +1070,8 @@ static DISCRETE_STEP(dst_rcfilter_sw)
int i,j ;
int bits = (int)DST_RCFILTER_SW__SWITCH;
double us = 0, rs = 0;
double vd;
double rt;
if (DST_RCFILTER_SW__ENABLE)
{
@ -1086,18 +1088,43 @@ static DISCRETE_STEP(dst_rcfilter_sw)
context->vCap[1] += (DST_RCFILTER_SW__VIN - context->vCap[1]) * context->exp1;
node->output[0] = context->vCap[1] + (DST_RCFILTER_SW__VIN - context->vCap[1]) * context->factor;
break;
default:
case 3:
rs = 2 * DST_RCFILTER_SW__R;
vd = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES) * DST_RCFILTER_SW__VIN;
rt = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs);
for (j = 0; j < DST_RCFILTER_SW_ITERATIONS; j++)
{
node->output[0] = vd + rt * (context->vCap[0] + context->vCap[1]);
context->vCap[0] += (node->output[0] - context->vCap[0]) * context->exp[0];
context->vCap[1] += (node->output[0] - context->vCap[1]) * context->exp[1];
}
break;
default:
rs = 0;
for (i = 0; i < 4; i++)
{
if (( bits & (1 << i)) != 0)
{
rs += DST_RCFILTER_SW__R;
}
}
vd = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES) * DST_RCFILTER_SW__VIN;
rt = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs);
for (j = 0; j < DST_RCFILTER_SW_ITERATIONS; j++)
{
us = 0;
for (i = 0; i < 4; i++)
{
if (( bits & (1 << i)) != 0)
{
us += context->vCap[i];
rs += DST_RCFILTER_SW__R;
}
}
node->output[0] = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES) * DST_RCFILTER_SW__VIN + DST_RCFILTER_SW__R / (CD4066_ON_RES + rs) * us;
node->output[0] = vd + rt * us;
for (i = 0; i < 4; i++)
{
if (( bits & (1 << i)) != 0)

View File

@ -15,7 +15,6 @@
*
************************************************************************/
#define EXPERIMENTAL_STREAM_PARALLEL (0)
#define DSS_INPUT__GAIN (*(node->input[0]))
#define DSS_INPUT__OFFSET (*(node->input[1]))
@ -67,14 +66,6 @@ READ8_DEVICE_HANDLER(discrete_sound_r)
return data;
}
#if EXPERIMENTAL_STREAM_PARALLEL
static STREAM_BACKGROUND_CALLBACK( disc_cb )
{
node_description *node = (node_description *) ptr;
node->output[0] = param * DSS_INPUT__GAIN + DSS_INPUT__OFFSET;
}
#endif
WRITE8_DEVICE_HANDLER(discrete_sound_w)
{
@ -104,7 +95,6 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
if (last_data != new_data)
{
#if !EXPERIMENTAL_STREAM_PARALLEL
/* Bring the system up to now */
stream_update(info->discrete_stream);
@ -112,12 +102,6 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
/* 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;
#else
*node_data = new_data;
/* Bring the system up to now */
stream_update_background(info->discrete_stream, disc_cb, (void *) node, *node_data);
#endif
}
}
else

View File

@ -38,6 +38,7 @@
#include "inptport.h"
#include "wavwrite.h"
#include "discrete.h"
#include "eminline.h"
/*************************************
@ -65,11 +66,10 @@
static void init_nodes(discrete_info *info, linked_list_entry *block_list, const device_config *device);
static void find_input_nodes(discrete_info *info);
static void setup_output_nodes(const device_config *device, discrete_info *info);
static void setup_disc_logs(discrete_info *info);
static node_description *discrete_find_node(const discrete_info *info, int node);
static DEVICE_RESET( discrete );
static STREAM_UPDATE( discrete_stream_update );
/*************************************
@ -95,7 +95,79 @@ static void CLIB_DECL ATTR_PRINTF(2,3) discrete_log(const discrete_info *disc_in
}
}
typedef struct _task_info task_info;
struct _task_info
{
discrete_task_context *context;
int samples;
};
INLINE void step_nodes_in_list(linked_list_entry **list)
{
linked_list_entry *entry;
for (entry = *list; entry != NULL; entry = entry->next)
{
node_description *node = (node_description *) entry->ptr;
/* Now step the node */
if (DISCRETE_PROFILING)
node->run_time -= osd_profiling_ticks();
(*node->module->step)(node);
//bigselect(info->device, node);
if (DISCRETE_PROFILING)
node->run_time += osd_profiling_ticks();
}
}
static void *task_callback(void *param, int threadid)
{
task_info *ti = (task_info *) param;
int samples;
/* set up task buffer */
ti->context->ptr = &ti->context->node_buf[0];
samples = ti->samples;
while (samples-- > 0)
{
step_nodes_in_list(&ti->context->list);
}
/* reset ptr */
ti->context->ptr = &ti->context->node_buf[0];
free(param);
return NULL;
}
static DISCRETE_STEP( dso_task )
{
discrete_task_context *ctx = (discrete_task_context *) node->context;
*(ctx->ptr++) = (double) *(node->input[0]);
}
static DISCRETE_RESET( dso_task )
{
/* nothing to do - just avoid being stepped */
}
static DISCRETE_STEP( dso_output )
{
stream_sample_t **output = (stream_sample_t **) &node->context;
double val;
/* Add gain to the output and put into the buffers */
/* Clipping will be handled by the main sound system */
val = (*node->input[0]) * (*node->input[1]);
**output = val;
(*output)++;
}
static DISCRETE_RESET( dso_output )
{
/* nothing to do - just avoid being stepped */
}
/*************************************
*
@ -119,13 +191,18 @@ static void CLIB_DECL ATTR_PRINTF(2,3) discrete_log(const discrete_info *disc_in
static const discrete_module module_list[] =
{
{ DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,0 ,NULL ,NULL },
{ DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,sizeof(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 },
/* parallel modules */
{ DSO_TASK_START ,"DSO_TASK_START" , 0 ,0 ,NULL ,NULL },
{ DSO_TASK_END ,"DSO_TASK_END" , 0 ,0 ,dso_task_reset ,dso_task_step },
{ DSO_TASK_SYNC ,"DSO_TASK_SYNC" , 0 ,0 ,NULL ,NULL },
/* nop */
{ DSS_NOP ,"DSS_NOP" , 0 ,0 ,NULL ,NULL },
{ DSS_NOP ,"DSS_NOP" , 0 ,0 ,NULL ,NULL },
/* from disc_inp.c */
{ DSS_ADJUSTMENT ,"DSS_ADJUSTMENT" , 1 ,sizeof(struct dss_adjustment_context) ,dss_adjustment_reset ,dss_adjustment_step },
@ -298,11 +375,8 @@ static void discrete_build_list(discrete_info *info, discrete_sound_block *intf,
}
else if (intf[node_count].type == DSO_DELETE)
{
int p,deleted;
linked_list_entry *entry, *last;
p = 0;
deleted = 0;
last = NULL;
for (entry = info->block_list; entry != NULL; last = entry, entry = entry->next)
{
@ -419,7 +493,12 @@ static DEVICE_START( discrete )
find_input_nodes(info);
/* then set up the output nodes */
setup_output_nodes(device, info);
/* initialize the stream(s) */
info->discrete_stream = stream_create(device, info->discrete_input_streams, info->discrete_outputs, info->sample_rate, info, discrete_stream_update);
/* allocate a queue */
info->queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_MULTI | WORK_QUEUE_FLAG_HIGH_FREQ);
setup_disc_logs(info);
}
@ -437,6 +516,8 @@ static DEVICE_STOP( discrete )
discrete_info *info = get_safe_token(device);
int log_num;
osd_work_queue_free(info->queue);
if (DISCRETE_PROFILING)
{
int count = 0;
@ -646,50 +727,39 @@ INLINE void discrete_stream_update_wave(discrete_info *info)
}
}
INLINE void discrete_stream_update_nodes(discrete_info *info, stream_sample_t **outputs)
INLINE void discrete_stream_update_nodes(discrete_info *info)
{
int outputnum;
double val;
linked_list_entry *entry;
linked_list_entry *entry;
if (DISCRETE_PROFILING)
info->total_samples++;
/* update task nodes */
for (entry = info->task_list; entry != 0; entry = entry->next)
{
discrete_task_context *task = (discrete_task_context *) entry->ptr;
**task->dest = *task->ptr++;
}
/* loop over all nodes */
for (entry = info->step_list; entry != NULL; entry = entry->next)
{
node_description *node = (node_description *) entry->ptr;
/* Now step the node */
if (DISCRETE_PROFILING)
node->run_time -= osd_profiling_ticks();
(*node->module->step)(node);
//bigselect(info->device, node);
if (DISCRETE_PROFILING)
node->run_time += osd_profiling_ticks();
}
/* Add gain to the output and put into the buffers */
/* Clipping will be handled by the main sound system */
for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
{
val = (*info->output_node[outputnum]->input[0]) * (*info->output_node[outputnum]->input[1]);
*(outputs[outputnum]++) = val;
}
step_nodes_in_list(&info->step_list);
}
static STREAM_UPDATE( discrete_stream_update )
{
discrete_info *info = (discrete_info *)param;
stream_sample_t *outptr[DISCRETE_MAX_OUTPUTS];
linked_list_entry *entry;
int samplenum, nodenum, outputnum;
//int j; int left; int run;
if (samples == 0)
return;
/* Setup any output streams */
for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
outptr[outputnum] = outputs[outputnum];
{
info->output_node[outputnum]->context = (void *) outputs[outputnum];
}
/* Setup any input streams */
for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
@ -697,20 +767,32 @@ static STREAM_UPDATE( discrete_stream_update )
info->input_stream_data[nodenum] = inputs[nodenum];
}
if ((info->num_csvlogs > 0) || (info->num_wavelogs > 0))
for (entry = info->task_list; entry != 0; entry = entry->next)
{
task_info *ti = malloc(sizeof(task_info));
discrete_task_context *task = (discrete_task_context *) entry->ptr;
/* Fire task */
ti->context = task;
ti->samples = samples;
osd_work_item_queue(info->queue, task_callback, (void *) ti, WORK_ITEM_FLAG_AUTO_RELEASE);
}
/* and wait for them */
osd_work_queue_wait(info->queue, osd_ticks_per_second()*10);
if ((info->num_csvlogs == 0) && (info->num_wavelogs == 0))
{
/* Now we must do samples iterations of the node list, one output for each step */
for (samplenum = 0; samplenum < samples; samplenum++)
{
discrete_stream_update_nodes(info, outptr);
}
discrete_stream_update_nodes(info);
}
else
{
/* Now we must do samples iterations of the node list, one output for each step */
for (samplenum = 0; samplenum < samples; samplenum++)
{
discrete_stream_update_nodes(info, outptr);
discrete_stream_update_nodes(info);
discrete_stream_update_csv(info);
discrete_stream_update_wave(info);
@ -732,9 +814,13 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
{
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;
/* start with no outputs or input streams */
info->discrete_outputs = 0;
info->discrete_input_streams = 0;
@ -745,6 +831,22 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
node_description *node = auto_alloc_clear(info->device->machine, node_description);
int inputnum, modulenum;
/* find the requested module */
for (modulenum = 0; module_list[modulenum].type != DSS_NULL; modulenum++)
if (module_list[modulenum].type == block->type)
break;
if (module_list[modulenum].type != block->type)
fatalerror("init_nodes() - Unable to find discrete module type %d for NODE_%02d", block->type, NODE_INDEX(block->node));
/* static inits */
node->context = NULL;
node->info = info;
node->node = block->node;
node->module = &module_list[modulenum];
node->output[0] = 0.0;
node->block = block;
node->custom = block->custom;
/* keep track of special nodes */
if (block->node == NODE_SPECIAL)
{
@ -771,6 +873,23 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
info->wavelog_node[info->num_wavelogs++] = node;
break;
/* Task processing */
case DSO_TASK_START:
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);
cur_task_node = &task->list;
break;
case DSO_TASK_END:
if (cur_task_node == NULL)
fatalerror("init_nodes() - NO DISCRETE_START_TASK.");
node->context = task;
task->dest = (double **) &node->input[0];
task = NULL;
break;
default:
fatalerror("init_nodes() - Failed, trying to create unknown special discrete node.");
}
@ -784,29 +903,12 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
info->indexed_node[NODE_INDEX(block->node)] = node;
}
/* find the requested module */
for (modulenum = 0; module_list[modulenum].type != DSS_NULL; modulenum++)
if (module_list[modulenum].type == block->type)
break;
if (module_list[modulenum].type != block->type)
fatalerror("init_nodes() - Unable to find discrete module type %d for NODE_%02d", block->type, NODE_INDEX(block->node));
/* static inits */
node->info = info;
node->node = block->node;
node->module = &module_list[modulenum];
node->output[0] = 0.0;
node->block = block;
node->active_inputs = block->active_inputs;
for (inputnum = 0; inputnum < DISCRETE_MAX_INPUTS; inputnum++)
{
node->input[inputnum] = &(block->initial[inputnum]);
}
node->context = NULL;
node->custom = block->custom;
/* setup module if custom */
if (block->type == DST_CUSTOM)
{
@ -835,7 +937,18 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const
/* our running order just follows the order specified */
/* does the node step ? */
if (node->module->step != NULL)
add_list(info, &step_list, node);
{
/* do we belong to a task? */
if (cur_task_node == NULL)
add_list(info, &step_list, node);
else
add_list(info, &cur_task_node, node);
}
if (block->type == DSO_TASK_END)
{
cur_task_node = NULL;
}
/* and register save state */
if (node->node != NODE_SPECIAL)
@ -899,21 +1012,6 @@ static void find_input_nodes(discrete_info *info)
}
/*************************************
*
* Set up the output nodes
*
*************************************/
static void setup_output_nodes(const device_config *device, discrete_info *info)
{
/* initialize the stream(s) */
info->discrete_stream = stream_create(device, info->discrete_input_streams, info->discrete_outputs, info->sample_rate, info, discrete_stream_update);
}
/*************************************
*
* Set up the logs

View File

@ -3659,6 +3659,17 @@ struct _linked_list_entry
linked_list_entry *next;
};
typedef struct _discrete_task_context discrete_task_context;
struct _discrete_task_context
{
linked_list_entry *list;
double *ptr;
double node_buf[2048];
double **dest;
volatile INT32 active;
};
struct _discrete_info
{
const device_config *device;
@ -3680,6 +3691,9 @@ struct _discrete_info
/* list of discrete blocks after prescan (IMPORT, DELETE, REPLACE) */
linked_list_entry *block_list; /* discrete_sound_block * */
/* tasks */
linked_list_entry *task_list; /* discrete_task_context * */
/* the input streams */
int discrete_input_streams;
stream_sample_t *input_stream_data[DISCRETE_MAX_OUTPUTS];
@ -3705,6 +3719,10 @@ struct _discrete_info
wav_file *disc_wav_file[DISCRETE_MAX_WAVELOGS];
node_description *wavelog_node[DISCRETE_MAX_WAVELOGS];
/* parallel tasks */
osd_work_queue *queue;
/* profiling */
int total_samples;
};
@ -4190,6 +4208,11 @@ enum
DSO_CSVLOG, /* Dump nodes as csv file */
DSO_WAVELOG, /* Dump nodes as wav file */
/* Parallel execution */
DSO_TASK_START, /* start of parallel task */
DSO_TASK_END, /* end of parallel task */
DSO_TASK_SYNC, /* wait for all parallel tasks to finish */
/* Output Node -- this must be the last entry in this enum! */
DSO_OUTPUT, /* The final output node */
@ -4198,12 +4221,6 @@ enum
DSO_REPLACE, /* replace next node */
DSO_DELETE, /* delete nodes */
/* Parallel execution */
DSO_TASK_START, /* start of parallel task */
DSO_TASK_END, /* end of parallel task */
DSO_TASK_SYNC, /* wait for all parallel tasks to finish */
/* Marks end of this enum -- must be last entry ! */
DSO_LAST
};
@ -4375,19 +4392,24 @@ enum
#define DISCRETE_NOP(NODE) { NODE, DSS_NOP , 0, { 0 }, { 0 }, NULL, "DISCRETE_NOP" },
/* logging */
#define DISCRETE_CSVLOG1(NODE1) { NODE_SPECIAL, DSO_CSVLOG , 1, { NODE1 }, { NODE1 }, NULL, "DISCRETE_CSVLOG1" },
#define DISCRETE_CSVLOG2(NODE1,NODE2) { NODE_SPECIAL, DSO_CSVLOG , 2, { NODE1,NODE2 }, { NODE1,NODE2 }, NULL, "DISCRETE_CSVLOG2" },
#define DISCRETE_CSVLOG3(NODE1,NODE2,NODE3) { NODE_SPECIAL, DSO_CSVLOG , 3, { NODE1,NODE2,NODE3 }, { NODE1,NODE2,NODE3 }, NULL, "DISCRETE_CSVLOG3" },
#define DISCRETE_CSVLOG4(NODE1,NODE2,NODE3,NODE4) { NODE_SPECIAL, DSO_CSVLOG , 4, { NODE1,NODE2,NODE3,NODE4 }, { NODE1,NODE2,NODE3,NODE4 }, NULL, "DISCRETE_CSVLOG4" },
#define DISCRETE_CSVLOG5(NODE1,NODE2,NODE3,NODE4,NODE5) { NODE_SPECIAL, DSO_CSVLOG , 5, { NODE1,NODE2,NODE3,NODE4,NODE5 }, { NODE1,NODE2,NODE3,NODE4,NODE5 }, NULL, "DISCRETE_CSVLOG5" },
#define DISCRETE_WAVELOG1(NODE1,GAIN1) { NODE_SPECIAL, DSO_WAVELOG , 2, { NODE1,NODE_NC }, { NODE1,GAIN1 }, NULL, "DISCRETE_WAVELOG1" },
#define DISCRETE_WAVELOG2(NODE1,GAIN1,NODE2,GAIN2) { NODE_SPECIAL, DSO_WAVELOG , 4, { NODE1,NODE_NC,NODE2,NODE_NC }, { NODE1,GAIN1,NODE2,GAIN2 }, NULL, "DISCRETE_WAVELOG2" },
#define DISCRETE_CSVLOG1(NODE1) { NODE_SPECIAL, DSO_CSVLOG , 1, { NODE1 }, { NODE1 }, NULL, "DISCRETE_CSVLOG1" },
#define DISCRETE_CSVLOG2(NODE1,NODE2) { NODE_SPECIAL, DSO_CSVLOG , 2, { NODE1,NODE2 }, { NODE1,NODE2 }, NULL, "DISCRETE_CSVLOG2" },
#define DISCRETE_CSVLOG3(NODE1,NODE2,NODE3) { NODE_SPECIAL, DSO_CSVLOG , 3, { NODE1,NODE2,NODE3 }, { NODE1,NODE2,NODE3 }, NULL, "DISCRETE_CSVLOG3" },
#define DISCRETE_CSVLOG4(NODE1,NODE2,NODE3,NODE4) { NODE_SPECIAL, DSO_CSVLOG , 4, { NODE1,NODE2,NODE3,NODE4 }, { NODE1,NODE2,NODE3,NODE4 }, NULL, "DISCRETE_CSVLOG4" },
#define DISCRETE_CSVLOG5(NODE1,NODE2,NODE3,NODE4,NODE5) { NODE_SPECIAL, DSO_CSVLOG , 5, { NODE1,NODE2,NODE3,NODE4,NODE5 }, { NODE1,NODE2,NODE3,NODE4,NODE5 }, NULL, "DISCRETE_CSVLOG5" },
#define DISCRETE_WAVELOG1(NODE1,GAIN1) { NODE_SPECIAL, DSO_WAVELOG , 2, { NODE1,NODE_NC }, { NODE1,GAIN1 }, NULL, "DISCRETE_WAVELOG1" },
#define DISCRETE_WAVELOG2(NODE1,GAIN1,NODE2,GAIN2) { NODE_SPECIAL, DSO_WAVELOG , 4, { NODE1,NODE_NC,NODE2,NODE_NC }, { NODE1,GAIN1,NODE2,GAIN2 }, NULL, "DISCRETE_WAVELOG2" },
/* import */
#define DISCRETE_IMPORT(INFO) { NODE_SPECIAL, DSO_IMPORT , 0, { 0 }, { 0 }, &(INFO##_discrete_interface), "DISCRETE_IMPORT" },
#define DISCRETE_DELETE(NODE_FROM, NODE_TO) { NODE_SPECIAL, DSO_DELETE , 2, { NODE_FROM, NODE_TO }, { NODE_FROM, NODE_TO }, NULL, "DISCRETE_DELETE" },
#define DISCRETE_REPLACE { NODE_SPECIAL, DSO_REPLACE , 0, { 0 }, { 0 }, NULL, "DISCRETE_REPLACE" },
#define DISCRETE_IMPORT(INFO) { NODE_SPECIAL, DSO_IMPORT , 0, { 0 }, { 0 }, &(INFO##_discrete_interface), "DISCRETE_IMPORT" },
#define DISCRETE_DELETE(NODE_FROM, NODE_TO) { NODE_SPECIAL, DSO_DELETE , 2, { NODE_FROM, NODE_TO }, { NODE_FROM, NODE_TO }, NULL, "DISCRETE_DELETE" },
#define DISCRETE_REPLACE { NODE_SPECIAL, DSO_REPLACE , 0, { 0 }, { 0 }, NULL, "DISCRETE_REPLACE" },
/* parallel tasks */
#define DISCRETE_TASK_START() { NODE_SPECIAL, DSO_TASK_START, 0, { 0 }, { 0 }, NULL, "DISCRETE_TASK_START" },
#define DISCRETE_TASK_END(BUF_NODE) { NODE_SPECIAL, DSO_TASK_END , 1, { BUF_NODE }, { BUF_NODE }, NULL, "DISCRETE_TASK_END" },
//#define DISCRETE_TASK_SYNC() { NODE_SPECIAL, DSO_TASK_SYNC, 0, { 0 }, { 0 }, NULL, "DISCRETE_TASK_SYNC" },
/* output */
#define DISCRETE_OUTPUT(OPNODE,GAIN) { NODE_SPECIAL, DSO_OUTPUT , 2, { OPNODE,NODE_NC }, { 0,GAIN }, NULL, "DISCRETE_OUTPUT" },

View File

@ -348,6 +348,12 @@ static const discrete_custom_info dkong_custom_mixer_info =
};
#endif
static DISCRETE_SOUND_START(dkong2b_dac)
DISCRETE_INPUT_DATA(DS_DAC)
DISCRETE_OUTPUT(DS_DAC, 1)
DISCRETE_SOUND_END
static DISCRETE_SOUND_START(dkong2b)
/************************************************/
@ -359,7 +365,8 @@ static DISCRETE_SOUND_START(dkong2b)
DISCRETE_INPUT_NOT(DS_SOUND1_INV) /* IC 6J, pin 12 */
DISCRETE_INPUT_NOT(DS_SOUND0_INV) /* IC 6J, pin 2 */
DISCRETE_INPUT_NOT(DS_DISCHARGE_INV)
DISCRETE_INPUT_DATA(DS_DAC)
//DISCRETE_INPUT_DATA(DS_DAC)
/* Mixing - DAC */
DISCRETE_ADJUSTMENT_TAG(DS_ADJ_DAC, 0, 1, DISC_LINADJ, "VR2")
@ -367,6 +374,7 @@ static DISCRETE_SOUND_START(dkong2b)
/* Stomp */
/************************************************/
/* Noise */
DISCRETE_TASK_START()
DISCRETE_LFSR_NOISE(NODE_11, 1, 1, CLOCK_2VF, 1.0, 0, 0.5, &dkong_lfsr)
DISCRETE_COUNTER(NODE_12, 1, 0, NODE_11, 7, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) /* LS161, IC 3J */
DISCRETE_TRANSFORM3(NODE_13,NODE_12,3,DK_SUP_V,"01>2*")
@ -382,12 +390,14 @@ static DISCRETE_SOUND_START(dkong2b)
DISCRETE_RCINTEGRATE(NODE_22,NODE_20,DK_R5, RES_2_PARALLEL(DK_R4+DK_R3,DK_R6),0,DK_C19,DK_SUP_V,DISC_RC_INTEGRATE_TYPE1)
DISCRETE_MULTIPLY(DS_OUT_SOUND0,1,NODE_22,DK_R3/R_SERIES(DK_R3,DK_R4))
DISCRETE_TASK_END(DS_OUT_SOUND0)
/************************************************/
/* Jump */
/************************************************/
/* tt */
/* tt */
/* 4049B Inverter Oscillator build from 3 inverters */
DISCRETE_TASK_START()
DISCRETE_INVERTER_OSC(NODE_25,1,0,DK_R38,DK_R39,DK_C26,0,&dkong_inverter_osc_desc_jump)
#if DK_USE_CUSTOM
@ -414,10 +424,12 @@ static DISCRETE_SOUND_START(dkong2b)
DISCRETE_RCINTEGRATE(NODE_39,NODE_38,DK_R27, RES_2_PARALLEL(DK_R28,DK_R26+DK_R25),0,DK_C16,DK_SUP_V,DISC_RC_INTEGRATE_TYPE1)
DISCRETE_MULTIPLY(DS_OUT_SOUND1,1,NODE_39,DK_R25/(DK_R26+DK_R25))
DISCRETE_TASK_END(DS_OUT_SOUND1)
/************************************************/
/* Walk */
/************************************************/
DISCRETE_TASK_START()
DISCRETE_INVERTER_OSC(NODE_51,1,0,DK_R47,DK_R48,DK_C30,0,&dkong_inverter_osc_desc_walk)
#if DK_USE_CUSTOM
@ -438,11 +450,14 @@ static DISCRETE_SOUND_START(dkong2b)
/* Filter and divide - omitted C22 */
DISCRETE_CRFILTER(NODE_61, 1, NODE_60, DK_R15+DK_R16, DK_C23)
DISCRETE_MULTIPLY(DS_OUT_SOUND2, 1, NODE_61, DK_R15/(DK_R15+DK_R16))
DISCRETE_TASK_END(DS_OUT_SOUND2)
/************************************************/
/* DAC */
/************************************************/
DISCRETE_TASK_START()
DISCRETE_INPUTX_STREAM(DS_DAC, 0, 1.0, 0)
/* Signal decay circuit Q7, R20, C32 */
DISCRETE_RCDISC(NODE_70, DS_DISCHARGE_INV, 1, DK_R20, DK_C32)
DISCRETE_TRANSFORM4(NODE_71, DS_DAC, DK_SUP_V/256.0, NODE_70, DS_DISCHARGE_INV, "01*3!2+*")
@ -463,6 +478,7 @@ static DISCRETE_SOUND_START(dkong2b)
#else
DISCRETE_MULTIPLY(DS_OUT_DAC, 1, NODE_73, DS_ADJ_DAC)
#endif
DISCRETE_TASK_END(DS_OUT_DAC)
/************************************************/
/* Amplifier */
@ -621,7 +637,10 @@ static DISCRETE_SOUND_START(radarscp)
DISCRETE_INPUT_NOT(DS_SOUND6_INV)
DISCRETE_INPUT_NOT(DS_SOUND7_INV)
DISCRETE_INPUT_NOT(DS_DISCHARGE_INV)
DISCRETE_INPUT_DATA(DS_DAC)
/* Must be in task if tasks added */
DISCRETE_INPUTX_STREAM(DS_DAC, 0, 1.0, 0)
//DISCRETE_INPUT_DATA(DS_DAC)
/* Mixing - DAC */
DISCRETE_ADJUSTMENT_TAG(DS_ADJ_DAC, 0, 1, DISC_LINADJ, "VR2")
@ -1152,7 +1171,7 @@ static ADDRESS_MAP_START( dkong_sound_io_map, ADDRESS_SPACE_IO, 8 )
AM_WRITE(dkong_voice_w)
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_DEVREAD("ls175.3d", dkong_tune_r)
AM_WRITE(dkong_voice_w)
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_DEVWRITE("discrete", dkong_p1_w) /* only write to dac */
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_DEVWRITE("discdac", dkong_p1_w) /* only write to dac */
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_LATCH8_READWRITE("virtual_p2")
AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_LATCH8_READBIT("ls259.6h", 5)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_LATCH8_READBIT("ls259.6h", 4)
@ -1168,7 +1187,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( radarsc1_sound_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0x00, 0x00) AM_MIRROR(0xff) AM_DEVREAD("ls175.3d", latch8_r)
AM_RANGE(0x00, 0xff) AM_DEVWRITE("discrete", dkong_p1_w) /* DAC here */
AM_RANGE(0x00, 0xff) AM_DEVWRITE("discdac", dkong_p1_w) /* DAC here */
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_LATCH8_READ("virtual_p1")
AM_DEVWRITE("tms", M58817_command_w)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_LATCH8_WRITE("virtual_p2")
@ -1243,6 +1262,11 @@ MACHINE_DRIVER_START( dkong2b_audio )
MDRV_CPU_IO_MAP(dkong_sound_io_map)
MDRV_SPEAKER_STANDARD_MONO("mono")
MDRV_SOUND_ADD("discdac", DISCRETE, 0)
MDRV_SOUND_CONFIG_DISCRETE(dkong2b_dac)
MDRV_SOUND_ROUTE_EX(0, "discrete", 1.0, 0)
MDRV_SOUND_ADD("discrete", DISCRETE, 0)
MDRV_SOUND_CONFIG_DISCRETE(dkong2b)
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)

View File

@ -314,7 +314,7 @@ static DISCRETE_SOUND_START(galaxian)
/* since only a sample of the LFSR is latched @V2 we let the lfsr
* run at a lower speed
*/
DISCRETE_LFSR_NOISE(NODE_150, 1, 1, RNG_RATE/100, 1.0, 0, 0.5, &galaxian_lfsr)
DISCRETE_LFSR_NOISE(NODE_150, 1, 1, RNG_RATE/100, 1.0, 0, 0.5, &galaxian_lfsr)
DISCRETE_SQUAREWFIX(NODE_151,1,60*264/2,1.0,50,0.5,0) /* 2V signal */
DISCRETE_LOGIC_DFLIPFLOP(NODE_152,1,1,1,NODE_151,NODE_150)
@ -327,30 +327,31 @@ static DISCRETE_SOUND_START(galaxian)
/************************************************/
/* FIRE */
/************************************************/
DISCRETE_LOGIC_INVERT(NODE_160, 1, GAL_INP_FIRE)
DISCRETE_MULTIPLY(NODE_161, 1, TTL_OUT, GAL_INP_FIRE)
DISCRETE_MULTIPLY(NODE_162, 1, TTL_OUT, NODE_160) // inverted
DISCRETE_RCFILTER(NODE_163, 1, NODE_162, GAL_R47, GAL_C28)
/* Mix noise and 163 */
DISCRETE_TRANSFORM5(NODE_167, NODE_152, TTL_OUT, 1.0/GAL_R46, NODE_163, 1.0/GAL_R48,
"01*2*34*+" )
//DISCRETE_MULTIPLY(NODE_164, 1, TTL_OUT, NODE_152)
//DISCRETE_MULTIPLY(NODE_165, 1, 1.0/GAL_R46, NODE_164)
//DISCRETE_MULTIPLY(NODE_166, 1, 1.0/GAL_R48, NODE_163)
//DISCRETE_ADDER2(NODE_167, 1, NODE_165, NODE_166)
DISCRETE_MULTIPLY(NODE_168, 1, RES_2_PARALLEL(GAL_R46, GAL_R48), NODE_167)
DISCRETE_555_ASTABLE_CV(NODE_171, 1, GAL_R44, GAL_R45, GAL_C27, NODE_168, &galaxian_555_fire_vco_desc)
DISCRETE_LOGIC_INVERT(NODE_170, 1, GAL_INP_FIRE)
DISCRETE_MULTIPLY(NODE_171, 1, TTL_OUT, GAL_INP_FIRE)
DISCRETE_MULTIPLY(NODE_172, 1, TTL_OUT, NODE_170) // inverted
DISCRETE_RCFILTER(NODE_173, 1, NODE_172, GAL_R47, GAL_C28)
/* Mix noise and 163 */
DISCRETE_TRANSFORM5(NODE_177, NODE_152, TTL_OUT, 1.0/GAL_R46, NODE_173, 1.0/GAL_R48,
"01*2*34*+" )
//DISCRETE_MULTIPLY(NODE_174, 1, TTL_OUT, NODE_152)
//DISCRETE_MULTIPLY(NODE_175, 1, 1.0/GAL_R46, NODE_174)
//DISCRETE_MULTIPLY(NODE_176, 1, 1.0/GAL_R48, NODE_173)
//DISCRETE_ADDER2(NODE_177, 1, NODE_175, NODE_176)
DISCRETE_MULTIPLY(NODE_178, 1, RES_2_PARALLEL(GAL_R46, GAL_R48), NODE_177)
DISCRETE_555_ASTABLE_CV(NODE_181, 1, GAL_R44, GAL_R45, GAL_C27, NODE_178, &galaxian_555_fire_vco_desc)
/* 555 toggles discharge on rc discharge module */
DISCRETE_RCDISC5(NODE_172, NODE_171, NODE_161, (GAL_R41), GAL_C25)
DISCRETE_RCDISC5(NODE_182, NODE_181, NODE_171, (GAL_R41), GAL_C25)
/************************************************/
/* FINAL MIX */
/************************************************/
DISCRETE_MIXER5(NODE_279, 1, NODE_SUB(133,0), NODE_SUB(133,2), NODE_SUB(133,2), NODE_SUB(133,3), NODE_120, &galaxian_mixerpre_desc)
DISCRETE_MIXER3(NODE_280, 1, NODE_279, NODE_157, NODE_172, &galaxian_mixer_desc)
DISCRETE_MIXER3(NODE_280, 1, NODE_279, NODE_157, NODE_182, &galaxian_mixer_desc)
DISCRETE_OUTPUT(NODE_280, 32767.0/5.0*5)
DISCRETE_SOUND_END
@ -364,7 +365,7 @@ static DISCRETE_SOUND_START(mooncrst)
/************************************************/
DISCRETE_DELETE(NODE_279, NODE_279)
DISCRETE_REPLACE
DISCRETE_MIXER7(NODE_280, 1, NODE_SUB(133,0), NODE_SUB(133,2), NODE_SUB(133,2), NODE_SUB(133,3), NODE_120, NODE_157, NODE_172, &mooncrst_mixer_desc)
DISCRETE_MIXER7(NODE_280, 1, NODE_SUB(133,0), NODE_SUB(133,2), NODE_SUB(133,2), NODE_SUB(133,3), NODE_120, NODE_157, NODE_182, &mooncrst_mixer_desc)
DISCRETE_SOUND_END
/*************************************