#include "sndintrf.h" #include "streams.h" #include "dac.h" #include /* default to 4x oversampling */ #define DEFAULT_SAMPLE_RATE (48000 * 4) struct dac_info { sound_stream *channel; INT16 output; INT16 UnsignedVolTable[256]; INT16 SignedVolTable[256]; }; static void DAC_update(void *param,stream_sample_t **inputs, stream_sample_t **_buffer,int length) { struct dac_info *info = param; stream_sample_t *buffer = _buffer[0]; INT16 out = info->output; while (length--) *(buffer++) = out; } void dac_data_w(int num,UINT8 data) { struct dac_info *info = sndti_token(SOUND_DAC, num); INT16 out = info->UnsignedVolTable[data]; if (info->output != out) { /* update the output buffer before changing the registers */ stream_update(info->channel); info->output = out; } } void dac_signed_data_w(int num,UINT8 data) { struct dac_info *info = sndti_token(SOUND_DAC, num); INT16 out = info->SignedVolTable[data]; if (info->output != out) { /* update the output buffer before changing the registers */ stream_update(info->channel); info->output = out; } } void dac_data_16_w(int num,UINT16 data) { struct dac_info *info = sndti_token(SOUND_DAC, num); INT16 out = data >> 1; /* range 0..32767 */ if (info->output != out) { /* update the output buffer before changing the registers */ stream_update(info->channel); info->output = out; } } void dac_signed_data_16_w(int num,UINT16 data) { struct dac_info *info = sndti_token(SOUND_DAC, num); INT16 out = (INT32)data - (INT32)0x08000; /* range -32768..32767 */ /* casts avoid potential overflow on some ABIs */ if (info->output != out) { /* update the output buffer before changing the registers */ stream_update(info->channel); info->output = out; } } static void DAC_build_voltable(struct dac_info *info) { int i; /* build volume table (linear) */ for (i = 0;i < 256;i++) { info->UnsignedVolTable[i] = i * 0x101 / 2; /* range 0..32767 */ info->SignedVolTable[i] = i * 0x101 - 0x8000; /* range -32768..32767 */ } } static SND_START( dac ) { struct dac_info *info; info = auto_malloc(sizeof(*info)); memset(info, 0, sizeof(*info)); DAC_build_voltable(info); info->channel = stream_create(0,1,clock ? clock : DEFAULT_SAMPLE_RATE,info,DAC_update); info->output = 0; state_save_register_item("dac", tag, 0, info->output); return info; } WRITE8_HANDLER( dac_0_data_w ) { dac_data_w(0,data); } WRITE8_HANDLER( dac_1_data_w ) { dac_data_w(1,data); } WRITE8_HANDLER( dac_2_data_w ) { dac_data_w(2,data); } WRITE8_HANDLER( dac_0_signed_data_w ) { dac_signed_data_w(0,data); } WRITE8_HANDLER( dac_1_signed_data_w ) { dac_signed_data_w(1,data); } WRITE8_HANDLER( dac_2_signed_data_w ) { dac_signed_data_w(2,data); } /************************************************************************** * Generic get_info **************************************************************************/ static SND_SET_INFO( dac ) { switch (state) { /* no parameters to set */ } } SND_GET_INFO( dac ) { switch (state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ /* --- the following bits of info are returned as pointers to data or functions --- */ case SNDINFO_PTR_SET_INFO: info->set_info = SND_SET_INFO_NAME( dac ); break; case SNDINFO_PTR_START: info->start = SND_START_NAME( dac ); break; case SNDINFO_PTR_STOP: /* nothing */ break; case SNDINFO_PTR_RESET: /* nothing */ break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case SNDINFO_STR_NAME: info->s = "DAC"; break; case SNDINFO_STR_CORE_FAMILY: info->s = "TI Speech"; break; case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break; case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break; case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Nicola Salmoria and the MAME Team"; break; } }