furnace/src/engine/platform/sound/es550x/es550x_alu.cpp
cam900 29ea6dc360 Partially ES5506 support (not working yet!)
Add sample related enums
Add support for backward/pingpong loop, loop end position
Structize Notemap in sample instrument
2022-04-21 01:52:37 +09:00

117 lines
2.3 KiB
C++

/*
License: BSD-3-Clause
see https://github.com/cam900/vgsound_emu/LICENSE for more details
Copyright holder(s): cam900
Ensoniq ES5504/ES5505/ES5506 Shared Accumulator emulation core
see es550x.cpp for more info
*/
#include "es550x.hpp"
// Accumulator functions
void es550x_shared_core::es550x_alu_t::reset()
{
m_cr.reset();
m_fc = 0;
m_start = 0;
m_end = 0;
m_accum = 0;
m_sample[0] = m_sample[1] = 0;
}
bool es550x_shared_core::es550x_alu_t::busy()
{
return ((!m_cr.stop0) && (!m_cr.stop1));
}
bool es550x_shared_core::es550x_alu_t::tick()
{
if (m_cr.dir)
{
m_accum = bitfield(m_accum - m_fc, 0, m_total_bits);
return ((!m_cr.lei) && (m_accum < m_start)) ? true : false;
}
else
{
m_accum = bitfield(m_accum + m_fc, 0, m_total_bits);
return ((!m_cr.lei) && (m_accum > m_end)) ? true : false;
}
}
void es550x_shared_core::es550x_alu_t::loop_exec()
{
if (m_cr.irqe) // Set IRQ
m_cr.irq = 1;
if (m_cr.dir) // Reverse playback
{
if (m_cr.lpe) // Loop enable
{
if (m_cr.ble) // Bidirectional
{
m_cr.dir = 0;
m_accum = m_start + (m_start - m_accum);
}
else// Normal
m_accum = (m_accum + m_start) - m_end;
}
else if (m_cr.ble && m_transwave) // m_transwave
{
m_cr.lpe = m_cr.ble = 0;
m_cr.lei = 1; // Loop end ignore
m_accum = (m_accum + m_start) - m_end;
}
else // Stop
m_cr.stop0 = 1;
}
else
{
if (m_cr.lpe) // Loop enable
{
if (m_cr.ble) // Bidirectional
{
m_cr.dir = 1;
m_accum = m_end - (m_end - m_accum);
}
else // Normal
m_accum = (m_accum - m_end) + m_start;
}
else if (m_cr.ble && m_transwave) // m_transwave
{
m_cr.lpe = m_cr.ble = 0;
m_cr.lei = 1; // Loop end ignore
m_accum = (m_accum - m_end) + m_start;
}
else // Stop
m_cr.stop0 = 1;
}
}
s32 es550x_shared_core::es550x_alu_t::interpolation()
{
// SF = S1 + ACCfr * (S2 - S1)
return m_sample[0] + ((bitfield(m_accum, std::min<u8>(0, m_fraction - 9), 9) * (m_sample[1] - m_sample[0])) >> 9);
}
u32 es550x_shared_core::es550x_alu_t::get_accum_integer()
{
return bitfield(m_accum, m_fraction, m_integer);
}
void es550x_shared_core::es550x_alu_t::irq_exec(es550x_intf &intf, es550x_irq_t &irqv, u8 index)
{
const u8 prev = irqv.irqb;
if (m_cr.irq)
{
if (irqv.irqb)
{
irqv.set(index);
m_cr.irq = 0;
}
}
if (prev != irqv.irqb)
irq_update(intf, irqv);
}