/*************************************************************************** Alesis HR-16 sound (DM3AG + PCM54) emulation TODO: - volume - panning - output 2 - fix 16-bit output to DAC (currently samples are only shifted by 8) - remove noise during patterns recording ****************************************************************************/ #include "emu.h" #include "includes/alesis.h" #define LOG 1 // device type definition const device_type ALESIS_DM3AG = &device_creator; /*************************************************************************** IMPLEMENTATION ***************************************************************************/ static MACHINE_CONFIG_FRAGMENT( alesis_dm3ag ) MCFG_SPEAKER_STANDARD_STEREO("out1_left", "out1_right") MCFG_SOUND_ADD("dac", DAC, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "out1_left", 1.0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "out1_right", 1.0) MACHINE_CONFIG_END //------------------------------------------------- // alesis_dm3ag_device - constructor //------------------------------------------------- alesis_dm3ag_device::alesis_dm3ag_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, ALESIS_DM3AG, "Alesis DM3AG", tag, owner, clock), m_dac(*this, "dac") { } //------------------------------------------------- // device_mconfig_additions //------------------------------------------------- machine_config_constructor alesis_dm3ag_device::device_mconfig_additions() const { return MACHINE_CONFIG_NAME( alesis_dm3ag ); } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void alesis_dm3ag_device::device_start() { m_samples = (INT8*)(*region()); m_dac_update_timer = timer_alloc(TIMER_DAC_UPDATE); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void alesis_dm3ag_device::device_reset() { m_dac_update_timer->adjust(attotime::from_hz(48000), 0, attotime::from_hz(48000)); m_output_active = false; m_count = 0; m_cur_sample = 0; memset(m_cmd, 0, sizeof(m_cmd)); } //------------------------------------------------- // device_timer - handler timer events //------------------------------------------------- void alesis_dm3ag_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { if (m_output_active) { INT16 sample = m_samples[m_cur_sample++]; // FIXME sample <<= 8; m_dac->write_signed16(sample + 0x8000); // every block ends with three or more -1 samples if (m_cur_sample == 0xfffff || (m_samples[m_cur_sample-1] == -128 && m_samples[m_cur_sample] == -128 && m_samples[m_cur_sample+1] == -128)) { m_output_active = false; m_dac->write_signed16(0x8000); if (LOG) logerror("DM3AG '%s' stop: %d\n", tag(), m_cur_sample-((m_cmd[0]<<12) | (m_cmd[1]<<4) | ((m_cmd[2]>>4) & 0x0f))); } } } WRITE8_MEMBER(alesis_dm3ag_device::write) { if (LOG) logerror("DM3AG '%s' write: %02x\n", tag(), data); m_cmd[m_count++] = data; if (m_count == 5) { /* commands are sent in block of 5 bytes (40 bits) bit 00-19 sample position in the roms bit 20-23 ??? bit 24-31 volume bit 32-34 panning bit 35 output selector: 0 = out2, 1 = out1 bit 36-39 ??? */ m_cur_sample = (m_cmd[0]<<12) | (m_cmd[1]<<4) | ((m_cmd[2]>>4) & 0x0f); if (m_cur_sample > 0) { m_output_active = true; if (LOG) { bool good_pos = (m_cur_sample<2 || m_samples[m_cur_sample-2] == -128); logerror("DM3AG '%s' start: %d (%s), vol: %02x out: %d pan: %d\n", tag(), m_cur_sample, good_pos ? "ok": "no", m_cmd[3], m_cmd[4] & 0x10 ? 1 : 2, (m_cmd[4]>>5)&7); } } m_count = 0; } }