summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/alesis.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/alesis.c')
-rw-r--r--src/mame/audio/alesis.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/mame/audio/alesis.c b/src/mame/audio/alesis.c
new file mode 100644
index 00000000000..7a253db43a2
--- /dev/null
+++ b/src/mame/audio/alesis.c
@@ -0,0 +1,157 @@
+// license:BSD-3-Clause
+// copyright-holders:Sandro Ronco
+/***************************************************************************
+
+ Alesis HR-16 sound (DM3AG + PCM54) emulation
+
+ TODO:
+ - volume
+ - panning
+ - output 2
+
+****************************************************************************/
+
+#include "emu.h"
+#include "includes/alesis.h"
+
+#define LOG 1
+
+// device type definition
+const device_type ALESIS_DM3AG = &device_creator<alesis_dm3ag_device>;
+
+/***************************************************************************
+ 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, "alesis_dm3ag", __FILE__),
+ m_dac(*this, "dac"),
+ m_samples(*this, DEVICE_SELF)
+{
+}
+
+//-------------------------------------------------
+// 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_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;
+ m_shift = 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++];
+ int count = 0;
+
+ while (sample == -128)
+ {
+ count++;
+
+ if (count == 1 && m_shift)
+ {
+ /*
+ The HR-16 seems to use a simple scheme to generate 16-bit samples from its 8-bit sample ROMs.
+ When the sound starts the 8-bit sample is sent to the most significant bits of the DAC and every
+ time a -1 sample is found the data is shifted one position to right.
+ */
+ m_shift--;
+
+ if (LOG) logerror("DM3AG '%s' shift: %02x\n", tag(), m_shift);
+ }
+
+ // every block ends with three or more -1 samples
+ if (m_cur_sample == 0xfffff || count >= 3)
+ {
+ m_output_active = false;
+ sample = 0;
+
+ if (LOG) logerror("DM3AG '%s' stop: %d, len: %d\n", tag(), m_cur_sample, m_cur_sample-((m_cmd[0]<<12) | (m_cmd[1]<<4) | ((m_cmd[2]>>4) & 0x0f)));
+
+ break;
+ }
+
+ sample = m_samples[m_cur_sample++];
+ }
+
+ m_dac->write_signed16((sample << m_shift) + 0x8000);
+ }
+}
+
+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;
+ m_shift = 8;
+
+ 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;
+ }
+}