summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound')
-rw-r--r--src/devices/sound/ay8910.cpp4
-rw-r--r--src/devices/sound/c140.cpp3
-rw-r--r--src/devices/sound/cdp1863.cpp4
-rw-r--r--src/devices/sound/cdp1864.cpp9
-rw-r--r--src/devices/sound/cdp1864.h2
-rw-r--r--src/devices/sound/disc_cls.h8
-rw-r--r--src/devices/sound/disc_dev.hxx4
-rw-r--r--src/devices/sound/disc_flt.hxx1
-rw-r--r--src/devices/sound/disc_mth.hxx2
-rw-r--r--src/devices/sound/disc_sys.hxx9
-rw-r--r--src/devices/sound/esqpump.cpp3
-rw-r--r--src/devices/sound/flt_biquad.cpp83
-rw-r--r--src/devices/sound/flt_biquad.h16
-rw-r--r--src/devices/sound/gaelco.cpp21
-rw-r--r--src/devices/sound/gaelco.h1
-rw-r--r--src/devices/sound/i5000.cpp1
-rw-r--r--src/devices/sound/k007232.cpp14
-rw-r--r--src/devices/sound/k007232.h2
-rw-r--r--src/devices/sound/ks0164.cpp76
-rw-r--r--src/devices/sound/ks0164.h20
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.cpp41
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.h2
-rw-r--r--src/devices/sound/mas3507d.cpp301
-rw-r--r--src/devices/sound/mas3507d.h78
-rw-r--r--src/devices/sound/multipcm.cpp60
-rw-r--r--src/devices/sound/multipcm.h2
-rw-r--r--src/devices/sound/namco.cpp4
-rw-r--r--src/devices/sound/s14001a.cpp14
-rw-r--r--src/devices/sound/samples.h2
-rw-r--r--src/devices/sound/sn76477.cpp8
-rw-r--r--src/devices/sound/sn76477.h34
-rw-r--r--src/devices/sound/spkrdev.cpp1
-rw-r--r--src/devices/sound/spu.cpp1
-rw-r--r--src/devices/sound/swp20.cpp25
-rw-r--r--src/devices/sound/swp20.h3
-rw-r--r--src/devices/sound/tc8830f.cpp13
-rw-r--r--src/devices/sound/tms5110.cpp2
-rw-r--r--src/devices/sound/tms5220.cpp1
-rw-r--r--src/devices/sound/uda1344.cpp290
-rw-r--r--src/devices/sound/uda1344.h104
-rw-r--r--src/devices/sound/ymf278b.cpp4
-rw-r--r--src/devices/sound/ymz280b.cpp8
42 files changed, 993 insertions, 288 deletions
diff --git a/src/devices/sound/ay8910.cpp b/src/devices/sound/ay8910.cpp
index 8ba53fb8b3f..46a6ff8bf00 100644
--- a/src/devices/sound/ay8910.cpp
+++ b/src/devices/sound/ay8910.cpp
@@ -968,8 +968,6 @@ void ay8910_device::ay8910_write_reg(int r, int v)
m_tone[2].set_volume(m_regs[AY_CVOL]);
break;
case AY_EACOARSE:
- if ((v & 0x0f) > 0)
- osd_printf_verbose("ECoarse\n");
case AY_EAFINE:
m_envelope[0].set_period(m_regs[AY_EAFINE], m_regs[AY_EACOARSE]);
break;
@@ -1010,8 +1008,6 @@ void ay8910_device::ay8910_write_reg(int r, int v)
logerror("warning: activated unknown mode %02x at %s\n", m_mode & 0xf, name());
}
}
- if ((v & 0x0f) > 0)
- osd_printf_verbose("EShape\n");
m_envelope[0].set_shape(m_regs[AY_EASHAPE], m_env_step_mask);
break;
case AY_PORTA:
diff --git a/src/devices/sound/c140.cpp b/src/devices/sound/c140.cpp
index 5d0b0811854..62e32707f6c 100644
--- a/src/devices/sound/c140.cpp
+++ b/src/devices/sound/c140.cpp
@@ -292,8 +292,9 @@ void c140_device::sound_stream_update(sound_stream &stream, std::vector<read_str
if (cnt)
{
+ const u16 sample = read_word((sampleData + pos) << 1) & 0xfff0; // 12bit
prevdt = lastdt;
- lastdt = ((ch_mulaw(v)) ? m_pcmtbl[read_byte((sampleData + pos) << 1)] : s16(read_word((sampleData + pos) << 1) & 0xfff0)) >> 4; // 12bit
+ lastdt = ((ch_mulaw(v)) ? m_pcmtbl[(sample >> 8) & 0xff] : s16(sample)) >> 4;
dltdt = (lastdt - prevdt);
}
diff --git a/src/devices/sound/cdp1863.cpp b/src/devices/sound/cdp1863.cpp
index 984a306b28a..da9194b9a7e 100644
--- a/src/devices/sound/cdp1863.cpp
+++ b/src/devices/sound/cdp1863.cpp
@@ -53,6 +53,10 @@ cdp1863_device::cdp1863_device(const machine_config &mconfig, const char *tag, d
, m_stream(nullptr)
, m_clock1(clock)
, m_clock2(0)
+ , m_oe(0)
+ , m_latch(0)
+ , m_signal(0)
+ , m_incr(0)
{
}
diff --git a/src/devices/sound/cdp1864.cpp b/src/devices/sound/cdp1864.cpp
index f4a46748593..7f3811bf09b 100644
--- a/src/devices/sound/cdp1864.cpp
+++ b/src/devices/sound/cdp1864.cpp
@@ -359,7 +359,7 @@ void cdp1864_device::dma_w(uint8_t data)
int sx = screen().hpos() + 4;
int y = screen().vpos();
- if (!m_con)
+ if (m_con)
{
rdata = m_read_rdata();
bdata = m_read_bdata();
@@ -384,11 +384,16 @@ void cdp1864_device::dma_w(uint8_t data)
//-------------------------------------------------
// con_w - color on write
+// At start, color is disabled. If the CON
+// pin is taken low (or pulsed low), color is
+// enabled. It can only be disabled again by
+// resetting the chip.
//-------------------------------------------------
void cdp1864_device::con_w(int state)
{
- m_con = state;
+ if (!state)
+ m_con = true;
}
diff --git a/src/devices/sound/cdp1864.h b/src/devices/sound/cdp1864.h
index 6c589128ef7..589867997dd 100644
--- a/src/devices/sound/cdp1864.h
+++ b/src/devices/sound/cdp1864.h
@@ -152,7 +152,7 @@ private:
int m_disp; // display on
int m_dmaout; // DMA request active
int m_bgcolor; // background color
- int m_con; // color on
+ bool m_con; // color on
// sound state
int m_aoe; // audio on
diff --git a/src/devices/sound/disc_cls.h b/src/devices/sound/disc_cls.h
index cb043557734..5761b31ae9e 100644
--- a/src/devices/sound/disc_cls.h
+++ b/src/devices/sound/disc_cls.h
@@ -5,6 +5,8 @@
#pragma once
+#include "wavwrite.h"
+
/***********************************************************************
*
* MAME - Discrete sound system emulation library
@@ -130,12 +132,12 @@ private:
DISCRETE_CLASS(dso_csvlog, 0,
FILE *m_csv_file;
int64_t m_sample_num;
- char m_name[32];
+ char m_name[32];
);
DISCRETE_CLASS(dso_wavlog, 0,
- wav_file *m_wavfile;
- char m_name[32];
+ util::wav_file_ptr m_wavfile;
+ char m_name[32];
);
/*************************************
diff --git a/src/devices/sound/disc_dev.hxx b/src/devices/sound/disc_dev.hxx
index e340f4004a7..e18d4d36711 100644
--- a/src/devices/sound/disc_dev.hxx
+++ b/src/devices/sound/disc_dev.hxx
@@ -633,10 +633,12 @@ DISCRETE_STEP(dsd_555_cc)
{
case 1:
r_discharge = DSD_555_CC__RDIS;
+ [[fallthrough]];
case 0:
break;
case 3:
r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
+ [[fallthrough]];
case 2:
r_charge = DSD_555_CC__RGND;
vi = i * r_charge;
@@ -944,10 +946,12 @@ DISCRETE_RESET(dsd_555_cc)
{
case 1:
r_discharge = DSD_555_CC__RDIS;
+ [[fallthrough]];
case 0:
break;
case 3:
r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
+ [[fallthrough]];
case 2:
r_charge = DSD_555_CC__RGND;
break;
diff --git a/src/devices/sound/disc_flt.hxx b/src/devices/sound/disc_flt.hxx
index 66b28bdeac4..32669a6cdc4 100644
--- a/src/devices/sound/disc_flt.hxx
+++ b/src/devices/sound/disc_flt.hxx
@@ -469,6 +469,7 @@ DISCRETE_RESET(dst_op_amp_filt)
m_rTotal = info->r1;
else
m_rTotal = RES_2_PARALLEL(info->r1, info->r2);
+ [[fallthrough]];
case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
{
double fc = 1.0 / (2 * M_PI * sqrt(m_rTotal * info->rF * info->c1 * info->c2));
diff --git a/src/devices/sound/disc_mth.hxx b/src/devices/sound/disc_mth.hxx
index cb423b175d1..d37de22784f 100644
--- a/src/devices/sound/disc_mth.hxx
+++ b/src/devices/sound/disc_mth.hxx
@@ -1057,6 +1057,7 @@ DISCRETE_STEP(dst_mixer)
break;
}
/* else, fall through and just use the resistor value */
+ [[fallthrough]];
case DISC_MIXER_IS_OP_AMP:
rTemp2 = rTemp;
break;
@@ -1219,6 +1220,7 @@ DISCRETE_RESET(dst_mixer)
break;
}
/* else, fall through and just use the resistor value */
+ [[fallthrough]];
case DISC_MIXER_IS_OP_AMP:
rTemp = info->r[bit];
break;
diff --git a/src/devices/sound/disc_sys.hxx b/src/devices/sound/disc_sys.hxx
index 539942a707b..86cb356ec38 100644
--- a/src/devices/sound/disc_sys.hxx
+++ b/src/devices/sound/disc_sys.hxx
@@ -81,14 +81,13 @@ DISCRETE_START( dso_wavlog )
log_num = m_device->same_module_index(*this);
sprintf(m_name, "%s_%d.csv", m_device->basetag(), log_num);
- m_wavfile = wav_open(m_name, sample_rate(), active_inputs()/2);
+ m_wavfile = util::wav_open(m_name, sample_rate(), active_inputs()/2);
}
DISCRETE_STOP( dso_wavlog )
{
/* close any wave files */
- if (m_wavfile)
- wav_close(m_wavfile);
+ m_wavfile.reset();
}
DISCRETE_STEP( dso_wavlog )
@@ -104,7 +103,7 @@ DISCRETE_STEP( dso_wavlog )
if (this->active_inputs() == 2)
{
/* DISCRETE_WAVLOG1 */
- wav_add_data_16(m_wavfile, &wave_data_l, 1);
+ util::wav_add_data_16(*m_wavfile, &wave_data_l, 1);
}
else
{
@@ -113,7 +112,7 @@ DISCRETE_STEP( dso_wavlog )
val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
wave_data_r = (int16_t)val;
- wav_add_data_16lr(m_wavfile, &wave_data_l, &wave_data_r, 1);
+ util::wav_add_data_16lr(*m_wavfile, &wave_data_l, &wave_data_r, 1);
}
}
diff --git a/src/devices/sound/esqpump.cpp b/src/devices/sound/esqpump.cpp
index bf34520869f..38b95a15bed 100644
--- a/src/devices/sound/esqpump.cpp
+++ b/src/devices/sound/esqpump.cpp
@@ -26,8 +26,6 @@ esq_5505_5510_pump_device::esq_5505_5510_pump_device(const machine_config &mconf
void esq_5505_5510_pump_device::device_start()
{
- logerror("Clock = %d\n", clock());
-
m_stream = stream_alloc(8, 2, clock(), STREAM_SYNCHRONOUS);
#if PUMP_DETECT_SILENCE
@@ -81,7 +79,6 @@ void esq_5505_5510_pump_device::sound_stream_update(sound_stream &stream, std::v
m_esp->ser_w(7, m_esp->ser_r(1) + m_esp->ser_r(3) + m_esp->ser_r(5));
#else
if (!m_esp_halted) {
- logerror("passing one sample through ESP\n");
osd_ticks_t a = osd_ticks();
m_esp->run_once();
osd_ticks_t b = osd_ticks();
diff --git a/src/devices/sound/flt_biquad.cpp b/src/devices/sound/flt_biquad.cpp
index c625b28c6df..8daa78e07ae 100644
--- a/src/devices/sound/flt_biquad.cpp
+++ b/src/devices/sound/flt_biquad.cpp
@@ -76,9 +76,17 @@ filter_biquad_device& filter_biquad_device::setup(biquad_type type, double fc, d
m_gain = gain;
return *this;
}
+filter_biquad_device& filter_biquad_device::setup(filter_biquad_device::biquad_params p)
+{
+ m_type = p.type;
+ m_fc = p.fc;
+ m_q = p.q;
+ m_gain = p.gain;
+ return *this;
+}
-// update an existing instance with new filter parameters
-void filter_biquad_device::update_params(biquad_type type, double fc, double q, double gain)
+// modify an existing instance with new filter parameters
+void filter_biquad_device::modify(biquad_type type, double fc, double q, double gain)
{
m_stream->update();
m_type = type;
@@ -87,7 +95,15 @@ void filter_biquad_device::update_params(biquad_type type, double fc, double q,
m_gain = gain;
recalc();
}
-
+void filter_biquad_device::modify(filter_biquad_device::biquad_params p)
+{
+ m_stream->update();
+ m_type = p.type;
+ m_fc = p.fc;
+ m_q = p.q;
+ m_gain = p.gain;
+ recalc();
+}
//-------------------------------------------------
// Filter setup helpers for various filter models
@@ -141,13 +157,12 @@ filter_biquad_device& filter_biquad_device::opamp_sk_lowpass_setup(double r1, do
/* Setup a biquad filter structure based on a single op-amp Multiple-Feedback low-pass filter circuit.
* NOTE: vRef is not definable when setting up the filter.
- * If the analog effects caused by vRef are important to the operation of the specific filter
- * in question, a netlist implementation may work better under those circumstances.
- * NOTE2: a variant of this circuit has the c1 capacitor left off. if so, set c1 to 0
- * which will form a controllable gain 1st order version of the circuit.
- * NOTE3: There is a well known 'proper' 1st order version of this circuit where r2 is
- * a dead short, and c1 is also ommitted as in NOTE2. Set both r2 to 0 and c1 to 0 to
- * emulate a circuit of this type.
+ * If the analog effects caused by vRef are important to the operation of the specific
+ * filter in question, a netlist implementation may work better under those circumstances.
+ * NOTE2: There is a well known 'proper' 1st order version of this circuit where r2 is
+ * a dead short, and c1 omitted. set both c1 and r2 to 0 in this case.
+ * NOTE3: a variant of NOTE2 has only the c1 capacitor left off, and r2 present. if so,
+ * set c1 to 0 and r2 to its expected value.
*
* .--------+---------.
* | | |
@@ -165,37 +180,40 @@ filter_biquad_device& filter_biquad_device::opamp_sk_lowpass_setup(double r1, do
*/
filter_biquad_device& filter_biquad_device::opamp_mfb_lowpass_setup(double r1, double r2, double r3, double c1, double c2)
{
+ filter_biquad_device::biquad_params p = opamp_mfb_lowpass_calc(r1, r2, r3, c1, c2);
+ return setup(p);
+}
+
+void filter_biquad_device::opamp_mfb_lowpass_modify(double r1, double r2, double r3, double c1, double c2)
+{
+ filter_biquad_device::biquad_params p = opamp_mfb_lowpass_calc(r1, r2, r3, c1, c2);
+ modify(p);
+}
+
+filter_biquad_device::biquad_params filter_biquad_device::opamp_mfb_lowpass_calc(double r1, double r2, double r3, double c1, double c2)
+{
+ filter_biquad_device::biquad_params r;
if ((r1 == 0) || ((r2 == 0) && (c1 != 0)) || (r3 == 0) || (c2 == 0))
{
- fatalerror("filter_biquad_device::opamp_mfb_lowpass_setup() - only c1 can be 0 (and if c1 is 0, r2 can also be 0); parameters were: r1: %f, r2: %f, r3: %f, c1: %f, c2: %f", r1, r2, r3, c1, c2); /* Filter can not be setup. Undefined results. */
- }
- double const gain = -r3 / r1;
- double fc, q = (M_SQRT2 / 2.0);
- if ((r2 != 0) && (c1 == 0)) // set C1 to 0 to run this filter in single pole mode where C1 was left off the filter entirely. Certain Williams boards seem to have omitted C1, presumably by accident.
- {
- fc = (r1 * r3) / (2 * M_PI * ((r1 * r2) + (r1 * r3) + (r2 * r3)) * r3 * c2);
-#ifdef FLT_BIQUAD_DEBUG_SETUP
- logerror("filter_biquad_device::opamp_mfb_lowpass_setup() in degraded mode yields: fc = %f, Q = %f(ignored), gain = %f\n", fc, q, gain);
-#endif
- return setup(biquad_type::LOWPASS1P, fc, q, gain);
+ fatalerror("filter_biquad_device::opamp_mfb_lowpass_calc() - only c1 can be 0 (and if c1 is 0, r2 can also be 0); parameters were: r1: %f, r2: %f, r3: %f, c1: %f, c2: %f", r1, r2, r3, c1, c2); /* Filter can not be setup. Undefined results. */
}
- else if ((r2 == 0) && (c1 == 0)) // proper first order case, set both C1 to 0 and R2 to 0 for the first order
+ r.gain = -r3 / r1;
+ r.q = (M_SQRT2 / 2.0);
+ if (c1 == 0) // if both R2 and C1 are 0, it is the 'proper' first order case. There do exist some unusual filters where R2 is not 0, though. In both cases this yields a single-pole filter with limited configurable gain, and a Q of ~0.707. R2 being zero makes the (r1 * r3) numerator term cancel out to 1.0.
{
- fc = 1.0 / (2 * M_PI * r3 * c2);
-#ifdef FLT_BIQUAD_DEBUG_SETUP
- logerror("filter_biquad_device::opamp_mfb_lowpass_setup() in 1st order mode yields: fc = %f, Q = %f(ignored), gain = %f\n", fc, q, gain);
-#endif
- return setup(biquad_type::LOWPASS1P, fc, q, gain);
+ r.fc = (r1 * r3) / (2 * M_PI * ((r1 * r2) + (r1 * r3) + (r2 * r3)) * r3 * c2);
+ r.type = biquad_type::LOWPASS1P;
}
else // common case, (r2 != 0) && (c1 != 0)
{
- fc = 1.0 / (2 * M_PI * sqrt(r2 * r3 * c1 * c2));
- q = sqrt(r2 * r3 * c1 * c2) / ((r3 * c2) + (r2 * c2) + ((r2 * c2) * -gain));
+ r.fc = 1.0 / (2 * M_PI * sqrt(r2 * r3 * c1 * c2));
+ r.q = sqrt(r2 * r3 * c1 * c2) / ((r3 * c2) + (r2 * c2) + ((r2 * c2) * -r.gain));
+ r.type = biquad_type::LOWPASS;
+ }
#ifdef FLT_BIQUAD_DEBUG_SETUP
- logerror("filter_biquad_device::opamp_mfb_lowpass_setup() in 2nd order mode yields: fc = %f, Q = %f, gain = %f\n", fc, q, gain);
+ logerror("filter_biquad_device::opamp_mfb_lowpass_setup(%f, %f, %f, %f, %f) yields:\n\ttype = %d, fc = %f, Q = %f, gain = %f\n", r1, r2, r3, c1*1000000, c2*1000000, static_cast<int>(r.type), r.fc, r.q, r.gain);
#endif
- return setup(biquad_type::LOWPASS, fc, q, gain);
- }
+ return r;
}
/* Setup a biquad filter structure based on a single op-amp Multiple-Feedback band-pass filter circuit.
@@ -272,7 +290,6 @@ filter_biquad_device& filter_biquad_device::opamp_mfb_highpass_setup(double r1,
{
fatalerror("filter_biquad_device::opamp_mfb_highpass_setup() - no parameters can be 0; parameters were: r1: %f, r2: %f, c1: %f, c2: %f, c3: %f", r1, r2, c1, c2, c3); /* Filter can not be setup. Undefined results. */
}
- // TODO: if c1 is 0/shorted, should the circuit should work with a gain of 1 in a first order mode?
double const gain = -c1 / c3;
double const fc = 1.0 / (2 * M_PI * sqrt(c2 * c3 * r1 * r2));
diff --git a/src/devices/sound/flt_biquad.h b/src/devices/sound/flt_biquad.h
index 17050c75017..97c434d9f79 100644
--- a/src/devices/sound/flt_biquad.h
+++ b/src/devices/sound/flt_biquad.h
@@ -27,12 +27,22 @@ public:
HIGHSHELF
};
+ struct biquad_params
+ {
+ biquad_type type;
+ double fc;
+ double q;
+ double gain;
+ };
+
filter_biquad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// set up the filter with the specified filter parameters and return a pointer to the new device
filter_biquad_device& setup(biquad_type type, double fc, double q, double gain);
- // update an existing instance with new filter parameters
- void update_params(biquad_type type, double fc, double q, double gain);
+ filter_biquad_device& setup(biquad_params p);
+ // modify an existing instance with new filter parameters
+ void modify(biquad_type type, double fc, double q, double gain);
+ void modify(biquad_params p);
// helper setup functions to create common filters representable by biquad filters
// Sallen-Key low-pass
@@ -42,6 +52,8 @@ public:
// Multiple-Feedback low-pass
filter_biquad_device& opamp_mfb_lowpass_setup(double r1, double r2, double r3, double c1, double c2);
+ void opamp_mfb_lowpass_modify(double r1, double r2, double r3, double c1, double c2);
+ biquad_params opamp_mfb_lowpass_calc(double r1, double r2, double r3, double c1, double c2);
// Multiple-Feedback band-pass
filter_biquad_device& opamp_mfb_bandpass_setup(double r1, double r2, double r3, double c1, double c2);
diff --git a/src/devices/sound/gaelco.cpp b/src/devices/sound/gaelco.cpp
index 2a213408095..31d294ee948 100644
--- a/src/devices/sound/gaelco.cpp
+++ b/src/devices/sound/gaelco.cpp
@@ -37,6 +37,7 @@ Registers per channel:
#include "emu.h"
#include "gaelco.h"
+
#include "wavwrite.h"
#define VERBOSE_SOUND 0
@@ -47,7 +48,7 @@ Registers per channel:
//#define ALT_MIX
#define LOG_WAVE 0
-static wav_file* wavraw; // Raw waveform
+static util::wav_file_ptr wavraw; // Raw waveform
/*============================================================================
@@ -182,7 +183,7 @@ void gaelco_gae1_device::sound_stream_update(sound_stream &stream, std::vector<r
}
// if (wavraw)
-// wav_add_data_buffer(wavraw, outputs[0], outputs[1]);
+// util::wav_add_data_buffer(*wavraw, outputs[0], outputs[1]);
}
/*============================================================================
@@ -261,15 +262,18 @@ void gaelco_gae1_device::device_start()
m_volume_table[vol][(j ^ 0x80) & 0xff] = (vol*j*256)/(VOLUME_LEVELS - 1);
if (LOG_WAVE)
- wavraw = wav_open("gae1_snd.wav", rate, 2);
+ wavraw = util::wav_open("gae1_snd.wav", rate, 2);
}
+void gaelco_gae1_device::device_reset()
+{
+ for (int ch = 0; ch < NUM_CHANNELS; ch++)
+ m_channel[ch].active = 0;
+}
void gaelco_gae1_device::device_stop()
{
- if (wavraw)
- wav_close(wavraw);
- wavraw = nullptr;
+ wavraw.reset();
}
@@ -283,11 +287,10 @@ void gaelco_gae1_device::device_clock_changed()
{
u32 rate = clock() / 128;
m_stream->set_sample_rate(rate);
- if (wavraw)
- wav_close(wavraw);
+ wavraw.reset();
if (LOG_WAVE)
- wavraw = wav_open("gae1_snd.wav", rate, 2);
+ wavraw = util::wav_open("gae1_snd.wav", rate, 2);
}
diff --git a/src/devices/sound/gaelco.h b/src/devices/sound/gaelco.h
index a598c64345d..76a77c0bb40 100644
--- a/src/devices/sound/gaelco.h
+++ b/src/devices/sound/gaelco.h
@@ -38,6 +38,7 @@ protected:
// device-level overrides
virtual void device_start() override;
+ virtual void device_reset() override;
virtual void device_stop() override;
virtual void device_post_load() override;
virtual void device_clock_changed() override;
diff --git a/src/devices/sound/i5000.cpp b/src/devices/sound/i5000.cpp
index 6978b9336f3..3f194ef74c5 100644
--- a/src/devices/sound/i5000.cpp
+++ b/src/devices/sound/i5000.cpp
@@ -224,6 +224,7 @@ void i5000snd_device::write_reg16(uint8_t reg, uint16_t data)
default:
logerror("i5000snd: channel %d unknown sample param %04X!\n", ch, param);
// fall through (take settings from 0x0184)
+ [[fallthrough]];
// 4-bit ADPCM
case 0x0184:
m_channels[ch].freq_min = 0x100;
diff --git a/src/devices/sound/k007232.cpp b/src/devices/sound/k007232.cpp
index a8b6c135a51..32623f187df 100644
--- a/src/devices/sound/k007232.cpp
+++ b/src/devices/sound/k007232.cpp
@@ -52,15 +52,18 @@ k007232_device::k007232_device(const machine_config &mconfig, const char *tag, d
void k007232_device::device_start()
{
+ // assumes it can make an address mask with m_rom.length() - 1
+ assert (!m_rom.found() || !(m_rom.length() & (m_rom.length() - 1)));
+
m_pcmlimit = 1 << 17;
// default mapping (bankswitched ROM)
- if ((m_rom.target() != nullptr) && (!has_configured_map(0)))
+ if (m_rom.found() && !has_configured_map(0))
{
if (m_rom.bytes() > 0x20000)
space(0).install_read_handler(0x00000, std::min<offs_t>(0x1ffff, m_rom.bytes() - 1), read8sm_delegate(*this, FUNC(k007232_device::read_rom_default)));
else
{
- space(0).install_rom(0x00000, m_rom.mask(), m_rom.target());
+ space(0).install_rom(0x00000, m_rom.length() - 1, m_rom.target());
m_pcmlimit = m_rom.bytes();
}
}
@@ -220,17 +223,16 @@ void k007232_device::sound_stream_update(sound_stream &stream, std::vector<read_
{
char filebuf[256];
snprintf(filebuf, 256, "pcm%08x.wav", channel->start);
- wav_file *file = wav_open(filebuf, stream.sample_rate(), 1);
- if (file != nullptr)
+ util::wav_file_ptr file = util::wav_open(filebuf, stream.sample_rate(), 1);
+ if (file)
{
u32 addr = channel->start;
while (!BIT(read_sample(i, addr), 7) && addr < m_pcmlimit)
{
int16_t out = ((read_sample(i, addr) & 0x7f) - 0x40) << 7;
- wav_add_data_16(file, &out, 1);
+ util::wav_add_data_16(*file, &out, 1);
addr++;
}
- wav_close(file);
}
}
}
diff --git a/src/devices/sound/k007232.h b/src/devices/sound/k007232.h
index 57cb72fcf7b..f467670fc9b 100644
--- a/src/devices/sound/k007232.h
+++ b/src/devices/sound/k007232.h
@@ -62,7 +62,7 @@ private:
bool play;
};
- u8 read_rom_default(offs_t offset) { return m_rom[(m_bank + (offset & 0x1ffff)) & m_rom.mask()]; }
+ u8 read_rom_default(offs_t offset) { return m_rom[(m_bank + (offset & 0x1ffff)) & (m_rom.length() - 1)]; }
inline u8 read_sample(int channel, u32 addr) { m_bank = m_channel[channel].bank; return m_cache.read_byte(addr & 0x1ffff); }
channel_t m_channel[KDAC_A_PCM_MAX]; // 2 channels
diff --git a/src/devices/sound/ks0164.cpp b/src/devices/sound/ks0164.cpp
index 2086b014478..8fdcbf026ba 100644
--- a/src/devices/sound/ks0164.cpp
+++ b/src/devices/sound/ks0164.cpp
@@ -13,6 +13,8 @@ ks0164_device::ks0164_device(const machine_config &mconfig, const char *tag, dev
: device_t(mconfig, KS0164, tag, owner, clock),
device_sound_interface(mconfig, *this),
device_memory_interface(mconfig, *this),
+ device_serial_interface(mconfig, *this),
+ m_midi_tx(*this),
m_mem_region(*this, DEVICE_SELF),
m_cpu(*this, "cpu"),
m_mem_config("mem", ENDIANNESS_BIG, 16, 23)
@@ -54,6 +56,11 @@ void ks0164_device::device_start()
space().cache(m_mem_cache);
m_timer = timer_alloc(0);
+ m_midi_tx.resolve_safe();
+
+ set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
+ set_rate(clock(), 542);
+
save_item(NAME(m_bank1_base));
save_item(NAME(m_bank1_select));
save_item(NAME(m_bank2_base));
@@ -85,6 +92,8 @@ void ks0164_device::device_reset()
m_mpu_in = 0x00;
m_mpu_out = 0x00;
m_mpu_status = 0x00;
+ m_midi_in = 0x00;
+ m_midi_in_active = false;
m_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
}
@@ -96,6 +105,50 @@ void ks0164_device::device_timer(emu_timer &timer, device_timer_id id, int param
m_cpu->set_input_line(14, ASSERT_LINE);
}
+void ks0164_device::tra_complete()
+{
+ logerror("transmit done\n");
+}
+
+void ks0164_device::rcv_complete()
+{
+ receive_register_extract();
+ m_midi_in = get_received_char();
+ m_midi_in_active = true;
+ m_cpu->set_input_line(6, ASSERT_LINE);
+
+ logerror("recieved %02x\n", m_midi_in);
+}
+
+void ks0164_device::tra_callback()
+{
+ m_midi_tx(transmit_register_get_data_bit());
+}
+
+u8 ks0164_device::midi_r()
+{
+ m_midi_in_active = false;
+ m_cpu->set_input_line(6, CLEAR_LINE);
+ return m_midi_in;
+}
+
+void ks0164_device::midi_w(u8 data)
+{
+ logerror("want to transmit %02x\n", data);
+}
+
+u8 ks0164_device::midi_status_r()
+{
+ // transmit done/tx empty on bit 1
+ return m_midi_in_active ? 1 : 0;
+}
+
+void ks0164_device::midi_status_w(u8 data)
+{
+ logerror("midi status_w %02x\n", data);
+}
+
+
void ks0164_device::mpuin_set(bool control, u8 data)
{
// logerror("mpu push %s %02x\n", control ? "ctrl" : "data", data);
@@ -233,7 +286,7 @@ void ks0164_device::voice_w(offs_t offset, u16 data, u16 mem_mask)
if(m_cpu->pc() < 0x5f94 || m_cpu->pc() > 0x5fc0)
logerror("voice %02x.%02x = %04x @ %04x (%04x)\n", m_voice_select & 0x1f, offset, m_sregs[m_voice_select & 0x1f][offset], mem_mask, m_cpu->pc());
if(offset == 0 && (data & 1) && !(old & 1))
- logerror("keyon %02x mode=%04x (%s %c %c %c) cur=%02x%04x.%04x loop=%02x%04x.%04x end=%02x%04x.%04x pitch=%04x 10=%02x/%02x:%02x/%02x 14=%03x/%03x:%03x/%03x 18=%04x/%04x c=%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ logerror("keyon %02x mode=%04x (%s %c %c %c) cur=%02x%04x.%04x loop=%02x%04x.%04x end=%02x%04x.%04x pitch=%02x.%03x 10=%02x/%02x:%02x/%02x 14=%03x/%03x:%03x/%03x 18=%04x/%04x c=%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
m_voice_select,
m_sregs[m_voice_select & 0x1f][0x00],
@@ -255,7 +308,8 @@ void ks0164_device::voice_w(offs_t offset, u16 data, u16 mem_mask)
m_sregs[m_voice_select & 0x1f][0x0e],
m_sregs[m_voice_select & 0x1f][0x0f],
- m_sregs[m_voice_select & 0x1f][0x08], // pitch
+ m_sregs[m_voice_select & 0x1f][0x08] & 0x1f, // pitch
+ m_sregs[m_voice_select & 0x1f][0x08] >> 5,
m_sregs[m_voice_select & 0x1f][0x10] >> 9,
m_sregs[m_voice_select & 0x1f][0x12] >> 9,
@@ -289,6 +343,7 @@ u8 ks0164_device::irqen_76_r()
return m_irqen_76;
}
+// alternates 1e/5e
void ks0164_device::irqen_76_w(u8 data)
{
m_irqen_76 = data;
@@ -348,6 +403,8 @@ void ks0164_device::cpu_map(address_map &map)
map(0x0068, 0x0068).rw(FUNC(ks0164_device::mpu401_r), FUNC(ks0164_device::mpu401_w));
map(0x0069, 0x0069).rw(FUNC(ks0164_device::mpu401_istatus_r), FUNC(ks0164_device::mpu401_istatus_w));
+ map(0x006c, 0x006c).rw(FUNC(ks0164_device::midi_r), FUNC(ks0164_device::midi_w));
+ map(0x006d, 0x006d).rw(FUNC(ks0164_device::midi_status_r), FUNC(ks0164_device::midi_status_w));
map(0x0076, 0x0076).rw(FUNC(ks0164_device::irqen_76_r), FUNC(ks0164_device::irqen_76_w));
map(0x0077, 0x0077).rw(FUNC(ks0164_device::irqen_77_r), FUNC(ks0164_device::irqen_77_w));
@@ -375,9 +432,10 @@ void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_s
for(int voice = 0; voice < 0x20; voice++) {
u16 *regs = m_sregs[voice];
if(regs[0] & 0x0001) {
- u64 current = (u64(regs[1]) << 32) | (regs[2] << 16) | regs[3];
- if(current & 0xc00000000000)
+ u64 current = (u64(regs[1]) << 32) | (u64(regs[2]) << 16) | regs[3];
+
+ if(current & 0xc000000000)
continue;
u32 adr = current >> 16;
@@ -400,8 +458,14 @@ void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_s
}
s16 samp = samp0 + (((samp1 - samp0) * (current & 0xffff)) >> 16);
- current += regs[8];
- u64 end = (u64(regs[0xd]) << 32) | (regs[0xe] << 16) | regs[0xf];
+ u32 step = 0x10000 | (regs[8] & ~0x1f);
+ u32 shift = regs[8] & 0x1f;
+ if(shift > 0x10)
+ step >>= 0x20 - shift;
+ else if(shift)
+ step <<= shift;
+ current += step;
+ u64 end = (u64(regs[0xd]) << 32) | (u64(regs[0xe]) << 16) | regs[0xf];
if(current >= end) {
// Is there a loop enabled flag?
u64 loop = (u64(regs[9]) << 32) | (regs[0xa] << 16) | regs[0xb];
diff --git a/src/devices/sound/ks0164.h b/src/devices/sound/ks0164.h
index cc707699f2e..c82689f4ff1 100644
--- a/src/devices/sound/ks0164.h
+++ b/src/devices/sound/ks0164.h
@@ -9,8 +9,9 @@
#pragma once
#include "cpu/ks0164/ks0164.h"
+#include "diserial.h"
-class ks0164_device : public device_t, public device_sound_interface, public device_memory_interface
+class ks0164_device : public device_t, public device_sound_interface, public device_memory_interface, public device_serial_interface
{
public:
ks0164_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 16934400);
@@ -20,6 +21,9 @@ public:
u8 mpu401_data_r();
u8 mpu401_status_r();
+ void midi_rx(int state) { rx_w(state); }
+ auto midi_tx() { return m_midi_tx.bind(); }
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
@@ -28,6 +32,10 @@ protected:
virtual space_config_vector memory_space_config() const override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void tra_callback() override;
+ virtual void tra_complete() override;
+ virtual void rcv_complete() override;
+
private:
enum {
MPUS_RX_FULL = 0x01,
@@ -37,6 +45,8 @@ private:
MPUS_RX_INT = 0x80
};
+ devcb_write_line m_midi_tx;
+
optional_memory_region m_mem_region;
required_device<ks0164_cpu_device> m_cpu;
address_space_config m_mem_config;
@@ -53,6 +63,9 @@ private:
u8 m_mpu_out;
u8 m_mpu_status;
+ u8 m_midi_in;
+ bool m_midi_in_active;
+
u8 m_unk60;
u8 m_voice_select;
u8 m_irqen_76, m_irqen_77;
@@ -88,6 +101,11 @@ private:
u8 mpu401_istatus_r();
void mpu401_istatus_w(u8 data);
+ u8 midi_r();
+ void midi_w(u8 data);
+ u8 midi_status_r();
+ void midi_status_w(u8 data);
+
static inline u16 uncomp_8_16(u8 value);
};
diff --git a/src/devices/sound/l7a1045_l6028_dsp_a.cpp b/src/devices/sound/l7a1045_l6028_dsp_a.cpp
index 7f567f86cbb..a9db61b5deb 100644
--- a/src/devices/sound/l7a1045_l6028_dsp_a.cpp
+++ b/src/devices/sound/l7a1045_l6028_dsp_a.cpp
@@ -116,29 +116,23 @@ l7a1045_sound_device::l7a1045_sound_device(const machine_config &mconfig, const
void l7a1045_sound_device::device_start()
{
- /* Allocate the stream */
+ // assumes it can make an address mask with m_rom.length() - 1
+ assert(!(m_rom.length() & (m_rom.length() - 1)));
+
+ // Allocate the stream
m_stream = stream_alloc(0, 2, 66150); //clock() / 384);
- for (int voice = 0; voice < 32; voice++)
- {
- save_item(NAME(m_voice[voice].start), voice);
- save_item(NAME(m_voice[voice].end), voice);
- save_item(NAME(m_voice[voice].mode), voice);
- save_item(NAME(m_voice[voice].pos), voice);
- save_item(NAME(m_voice[voice].frac), voice);
- save_item(NAME(m_voice[voice].l_volume), voice);
- save_item(NAME(m_voice[voice].r_volume), voice);
- }
+ save_item(STRUCT_MEMBER(m_voice, start));
+ save_item(STRUCT_MEMBER(m_voice, end));
+ save_item(STRUCT_MEMBER(m_voice, mode));
+ save_item(STRUCT_MEMBER(m_voice, pos));
+ save_item(STRUCT_MEMBER(m_voice, frac));
+ save_item(STRUCT_MEMBER(m_voice, l_volume));
+ save_item(STRUCT_MEMBER(m_voice, r_volume));
save_item(NAME(m_key));
save_item(NAME(m_audiochannel));
save_item(NAME(m_audioregister));
- for (int reg = 0; reg < 0x10; reg++)
- {
- for (int voice = 0; voice < 0x20; voice++)
- {
- save_item(NAME(m_audiodat[reg][voice].dat), (reg << 8) | voice);
- }
- }
+ save_item(STRUCT_MEMBER(m_audiodat, dat));
}
@@ -188,8 +182,8 @@ void l7a1045_sound_device::sound_stream_update(sound_stream &stream, std::vector
}
- data = m_rom[(start + pos) & m_rom.mask()];
- sample = ((int8_t)(data & 0xfc)) << (3 - (data & 3));
+ data = m_rom[(start + pos) & (m_rom.length() - 1)];
+ sample = int8_t(data & 0xfc) << (3 - (data & 3));
frac += step;
outputs[0].add_int(j, sample * vptr->l_volume, 32768 * 512);
@@ -277,7 +271,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
//logerror("%s: channel %d start = %08x\n", tag(), m_audiochannel, vptr->start);
- vptr->start &= m_rom.mask();
+ vptr->start &= m_rom.length() - 1;
// if voice isn't active, clear the pos on start writes (required for DMA tests on MPC3000)
if (!(m_key & (1 << m_audiochannel)))
@@ -297,8 +291,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
vptr->end += vptr->start;
vptr->mode = false;
// hopefully it'll never happen? Maybe assert here?
- vptr->end &= m_rom.mask();
-
+ vptr->end &= m_rom.length() - 1;
}
else // absolute
{
@@ -307,7 +300,7 @@ void l7a1045_sound_device::sound_data_w(offs_t offset, uint16_t data)
vptr->end |= (m_audiodat[m_audioregister][m_audiochannel].dat[0] & 0xf000) >> (12);
vptr->mode = true;
- vptr->end &= m_rom.mask();
+ vptr->end &= m_rom.length() - 1;
}
//logerror("%s: channel %d end = %08x\n", tag(), m_audiochannel, vptr->start);
break;
diff --git a/src/devices/sound/l7a1045_l6028_dsp_a.h b/src/devices/sound/l7a1045_l6028_dsp_a.h
index 542b6aad386..4fff2caa465 100644
--- a/src/devices/sound/l7a1045_l6028_dsp_a.h
+++ b/src/devices/sound/l7a1045_l6028_dsp_a.h
@@ -38,7 +38,7 @@ protected:
private:
struct l7a1045_voice
{
- l7a1045_voice() { }
+ constexpr l7a1045_voice() { }
uint32_t start = 0;
uint32_t end = 0;
diff --git a/src/devices/sound/mas3507d.cpp b/src/devices/sound/mas3507d.cpp
index a5b7a7917d2..c2b50088d11 100644
--- a/src/devices/sound/mas3507d.cpp
+++ b/src/devices/sound/mas3507d.cpp
@@ -14,6 +14,28 @@
#include "minimp3/minimp3.h"
#include "minimp3/minimp3_ex.h"
+#define LOG_GENERAL (1 << 0)
+#define LOG_READ (1 << 1)
+#define LOG_WRITE (1 << 2)
+#define LOG_REGISTER (1 << 3)
+#define LOG_CONFIG (1 << 4)
+#define LOG_OTHER (1 << 5)
+// #define VERBOSE (LOG_GENERAL | LOG_READ | LOG_WRITE | LOG_REGISTER | LOG_CONFIG | LOG_OTHER)
+// #define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGREAD(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGWRITE(...) LOGMASKED(LOG_WRITE, __VA_ARGS__)
+#define LOGREGISTER(...) LOGMASKED(LOG_REGISTER, __VA_ARGS__)
+#define LOGCONFIG(...) LOGMASKED(LOG_CONFIG, __VA_ARGS__)
+#define LOGOTHER(...) LOGMASKED(LOG_OTHER, __VA_ARGS__)
+
+ALLOW_SAVE_TYPE(mas3507d_device::i2c_bus_state_t)
+ALLOW_SAVE_TYPE(mas3507d_device::i2c_bus_address_t)
+ALLOW_SAVE_TYPE(mas3507d_device::i2c_subdest_t)
+ALLOW_SAVE_TYPE(mas3507d_device::i2c_command_t)
+
// device type definition
DEFINE_DEVICE_TYPE(MAS3507D, mas3507d_device, "mas3507d", "MAS 3507D MPEG decoder")
@@ -21,8 +43,9 @@ mas3507d_device::mas3507d_device(const machine_config &mconfig, const char *tag,
: device_t(mconfig, MAS3507D, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, cb_sample(*this)
- , i2c_bus_state(), i2c_bus_address(), i2c_scli(false), i2c_sclo(false), i2c_sdai(false), i2c_sdao(false)
- , i2c_bus_curbit(0), i2c_bus_curval(0), i2c_subdest(), i2c_command(), i2c_bytecount(0), i2c_io_bank(0), i2c_io_adr(0), i2c_io_count(0), i2c_io_val(0)
+ , i2c_bus_state(IDLE), i2c_bus_address(UNKNOWN), i2c_subdest(UNDEFINED), i2c_command(CMD_BAD)
+ , i2c_scli(false), i2c_sclo(false), i2c_sdai(false), i2c_sdao(false)
+ , i2c_bus_curbit(0), i2c_bus_curval(0), i2c_bytecount(0), i2c_io_bank(0), i2c_io_adr(0), i2c_io_count(0), i2c_io_val(0)
{
}
@@ -31,6 +54,50 @@ void mas3507d_device::device_start()
current_rate = 44100;
stream = stream_alloc(0, 2, current_rate);
cb_sample.resolve();
+
+ save_item(NAME(mp3data));
+ save_item(NAME(samples));
+ save_item(NAME(i2c_bus_state));
+ save_item(NAME(i2c_bus_address));
+ save_item(NAME(i2c_subdest));
+ save_item(NAME(i2c_command));
+ save_item(NAME(i2c_scli));
+ save_item(NAME(i2c_sclo));
+ save_item(NAME(i2c_sdai));
+ save_item(NAME(i2c_sdao));
+ save_item(NAME(i2c_bus_curbit));
+ save_item(NAME(i2c_bus_curval));
+ save_item(NAME(mp3data_count));
+ save_item(NAME(current_rate));
+ save_item(NAME(decoded_frame_count));
+ save_item(NAME(decoded_samples));
+ save_item(NAME(sample_count));
+ save_item(NAME(samples_idx));
+ save_item(NAME(is_muted));
+ save_item(NAME(gain_ll));
+ save_item(NAME(gain_rr));
+ save_item(NAME(i2c_bytecount));
+ save_item(NAME(i2c_io_bank));
+ save_item(NAME(i2c_io_adr));
+ save_item(NAME(i2c_io_count));
+ save_item(NAME(i2c_io_val));
+ save_item(NAME(i2c_sdao_data));
+ save_item(NAME(playback_status));
+
+ // This should be removed in the future if/when native MP3 decoding is implemented in MAME
+ save_item(NAME(mp3_dec.mdct_overlap));
+ save_item(NAME(mp3_dec.qmf_state));
+ save_item(NAME(mp3_dec.reserv));
+ save_item(NAME(mp3_dec.free_format_bytes));
+ save_item(NAME(mp3_dec.header));
+ save_item(NAME(mp3_dec.reserv_buf));
+
+ save_item(NAME(mp3_info.frame_bytes));
+ save_item(NAME(mp3_info.frame_offset));
+ save_item(NAME(mp3_info.channels));
+ save_item(NAME(mp3_info.hz));
+ save_item(NAME(mp3_info.layer));
+ save_item(NAME(mp3_info.bitrate_kbps));
}
void mas3507d_device::device_reset()
@@ -42,13 +109,10 @@ void mas3507d_device::device_reset()
i2c_bus_curbit = -1;
i2c_bus_curval = 0;
- mp3dec_init(&mp3_dec);
- memset(mp3data.data(), 0, mp3data.size());
- memset(samples.data(), 0, samples.size());
- mp3_count = 0;
- sample_count = 0;
- total_frame_count = 0;
- buffered_frame_count = 0;
+ is_muted = false;
+ gain_ll = gain_rr = 0;
+
+ reset_playback();
}
void mas3507d_device::i2c_scl_w(bool line)
@@ -61,6 +125,14 @@ void mas3507d_device::i2c_scl_w(bool line)
if(i2c_bus_state == STARTED) {
if(i2c_sdai)
i2c_bus_curval |= 1 << i2c_bus_curbit;
+
+ if(i2c_subdest == DATA_READ)
+ i2c_sdao = BIT(i2c_sdao_data, i2c_bus_curbit + (i2c_bytecount * 8));
+ else {
+ i2c_sdao_data = 0;
+ i2c_sdao = false;
+ }
+
i2c_bus_curbit --;
if(i2c_bus_curbit == -1) {
if(i2c_bus_address == UNKNOWN) {
@@ -86,7 +158,7 @@ void mas3507d_device::i2c_scl_w(bool line)
i2c_bus_state = STARTED;
i2c_bus_curbit = 7;
i2c_bus_curval = 0;
- i2c_sdao = true;
+ i2c_sdao = false;
}
}
}
@@ -131,24 +203,30 @@ int mas3507d_device::i2c_sda_r()
bool mas3507d_device::i2c_device_got_address(uint8_t address)
{
- if (address == 0x3b) {
+ if(address == CMD_DEV_READ)
i2c_subdest = DATA_READ;
- } else {
+ else
i2c_subdest = UNDEFINED;
- }
- return (address & 0xfe) == 0x3a;
+ return (address & 0xfe) == CMD_DEV_WRITE;
}
void mas3507d_device::i2c_device_got_byte(uint8_t byte)
{
switch(i2c_subdest) {
case UNDEFINED:
- if(byte == 0x68)
+ if(byte == CMD_DATA_WRITE)
i2c_subdest = DATA_WRITE;
- else if(byte == 0x69)
+ else if(byte == CMD_DATA_READ) {
i2c_subdest = DATA_READ;
- else if(byte == 0x6a)
+
+ // Default read, returns the current frame count
+ i2c_sdao_data = ((decoded_frame_count >> 8) & 0xff)
+ | ((decoded_frame_count & 0xff) << 8)
+ | (((decoded_frame_count >> 24) & 0xff) << 16)
+ | (((decoded_frame_count >> 16) & 0xff) << 24);
+ }
+ else if(byte == CMD_CONTROL_WRITE)
i2c_subdest = CONTROL;
else
i2c_subdest = BAD;
@@ -159,19 +237,19 @@ void mas3507d_device::i2c_device_got_byte(uint8_t byte)
break;
case BAD:
- logerror("MAS I2C: Dropping byte %02x\n", byte);
+ LOGOTHER("MAS I2C: Dropping byte %02x\n", byte);
break;
case DATA_READ:
- // Default Read
- // This should return the current MPEGFrameCount value when called
+ switch(i2c_bytecount) {
+ case 0: i2c_io_val = byte; break;
+ case 1: i2c_io_val |= byte << 8; break;
+ case 2: i2c_nak(); return;
+ }
- // TODO: Figure out how to use this data exactly (chip docs are a little unclear to me)
- i2c_io_val <<= 8;
- i2c_io_val |= byte;
- i2c_bytecount++;
+ LOGREAD("MAS I2C: DATA_READ %d %02x %08x\n", i2c_bytecount, byte, i2c_io_val);
- logerror("MAS I2C: DATA_READ %d %08x\n", i2c_bytecount, i2c_io_val);
+ i2c_bytecount++;
break;
@@ -184,7 +262,7 @@ void mas3507d_device::i2c_device_got_byte(uint8_t byte)
break;
case 3:
i2c_command = CMD_READ_CTRL;
- logerror("MAS I2C: READ_CTRL\n");
+ LOGWRITE("MAS I2C: READ_CTRL\n");
break;
case 9:
i2c_io_adr = (byte & 15) << 4;
@@ -196,22 +274,22 @@ void mas3507d_device::i2c_device_got_byte(uint8_t byte)
break;
case 0xd:
i2c_command = CMD_READ_REG;
- logerror("MAS I2C: READ_REG\n");
+ LOGWRITE("MAS I2C: READ_REG\n");
break;
case 0xe: case 0xf:
i2c_io_bank = (byte >> 4) & 1;
i2c_command = CMD_READ_MEM;
- logerror("MAS I2C: READ_MEM\n");
+ LOGWRITE("MAS I2C: READ_MEM\n");
break;
default:
i2c_command = CMD_BAD;
- logerror("MAS I2C: BAD\n");
+ LOGWRITE("MAS I2C: BAD\n");
break;
}
} else {
switch(i2c_command) {
default:
- logerror("MAS I2C: Ignoring byte %02x\n", byte);
+ LOGWRITE("MAS I2C: Ignoring byte %02x\n", byte);
break;
case CMD_WRITE_REG:
@@ -260,14 +338,14 @@ void mas3507d_device::i2c_device_got_byte(uint8_t byte)
break;
case CONTROL:
- logerror("MAS I2C: Control byte %02x\n", byte);
+ LOGOTHER("MAS I2C: Control byte %02x\n", byte);
break;
}
}
void mas3507d_device::i2c_device_got_stop()
{
- logerror("MAS I2C: got stop\n");
+ LOGOTHER("MAS I2C: got stop\n");
}
int gain_to_db(double val) {
@@ -275,9 +353,8 @@ int gain_to_db(double val) {
}
float gain_to_percentage(int val) {
- if (val == 0) {
+ if(val == 0)
return 0; // Special case for muting it seems
- }
double db = gain_to_db(val);
@@ -287,113 +364,129 @@ float gain_to_percentage(int val) {
void mas3507d_device::mem_write(int bank, uint32_t adr, uint32_t val)
{
switch(adr | (bank ? 0x10000 : 0)) {
- case 0x0032f: logerror("MAS3507D: OutputConfig = %05x\n", val); break;
+ case 0x0032d: LOGCONFIG("MAS3507D: PLLOffset48 = %05x\n", val); break;
+ case 0x0032e: LOGCONFIG("MAS3507D: PLLOffset44 = %05x\n", val); break;
+ case 0x0032f: LOGCONFIG("MAS3507D: OutputConfig = %05x\n", val); break;
case 0x107f8:
- logerror("MAS3507D: left->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
- set_output_gain(0, gain_to_percentage(val));
+ gain_ll = gain_to_percentage(val);
+ LOGCONFIG("MAS3507D: left->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_ll);
+
+ if(!is_muted) {
+ set_output_gain(0, gain_ll);
+ }
break;
case 0x107f9:
- logerror("MAS3507D: left->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
+ LOGCONFIG("MAS3507D: left->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
break;
case 0x107fa:
- logerror("MAS3507D: right->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
+ LOGCONFIG("MAS3507D: right->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
break;
case 0x107fb:
- logerror("MAS3507D: right->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
- set_output_gain(1, gain_to_percentage(val));
+ gain_rr = gain_to_percentage(val);
+ LOGCONFIG("MAS3507D: right->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_rr);
+
+ if(!is_muted) {
+ set_output_gain(1, gain_rr);
+ }
break;
- default: logerror("MAS3507D: %d:%04x = %05x\n", bank, adr, val); break;
+ default: LOGCONFIG("MAS3507D: %d:%04x = %05x\n", bank, adr, val); break;
}
}
void mas3507d_device::reg_write(uint32_t adr, uint32_t val)
{
switch(adr) {
- case 0x8e: logerror("MAS3507D: DCCF = %05x\n", val); break;
- case 0xaa: logerror("MAS3507D: Mute/bypass = %05x\n", val); break;
- case 0xe6: logerror("MAS3507D: StartupConfig = %05x\n", val); break;
- case 0xe7: logerror("MAS3507D: Kprescale = %05x\n", val); break;
- case 0x6b: logerror("MAS3507D: Kbass = %05x\n", val); break;
- case 0x6f: logerror("MAS3507D: Ktreble = %05x\n", val); break;
- default: logerror("MAS3507D: reg %02x = %05x\n", adr, val); break;
+ case 0x8e: LOGCONFIG("MAS3507D: DCCF = %05x\n", val); break;
+ case 0xaa:
+ LOGCONFIG("MAS3507D: Mute/bypass = %05x\n", val);
+ set_output_gain(0, val == 1 ? 0 : gain_ll);
+ set_output_gain(1, val == 1 ? 0 : gain_rr);
+ break;
+ case 0xe6: LOGCONFIG("MAS3507D: StartupConfig = %05x\n", val); break;
+ case 0xe7: LOGCONFIG("MAS3507D: Kprescale = %05x\n", val); break;
+ case 0x6b: LOGCONFIG("MAS3507D: Kbass = %05x\n", val); break;
+ case 0x6f: LOGCONFIG("MAS3507D: Ktreble = %05x\n", val); break;
+ default: LOGCONFIG("MAS3507D: reg %02x = %05x\n", adr, val); break;
}
}
void mas3507d_device::run_program(uint32_t adr)
{
switch(adr) {
- case 0xfcb: logerror("MAS3507D: validate OutputConfig\n"); break;
- default: logerror("MAS3507D: run %04x\n", adr); break;
+ case 0xfcb: LOGCONFIG("MAS3507D: validate OutputConfig\n"); break;
+ default: LOGCONFIG("MAS3507D: run %04x\n", adr); break;
}
}
void mas3507d_device::fill_buffer()
{
- while(mp3_count + 2 < mp3data.size()) {
- u16 v = cb_sample();
- mp3data[mp3_count++] = v >> 8;
- mp3data[mp3_count++] = v;
+ while(mp3data_count + 2 < mp3data.size()) {
+ uint16_t v = cb_sample();
+ mp3data[mp3data_count++] = v >> 8;
+ mp3data[mp3data_count++] = v;
}
- int scount = mp3dec_decode_frame(&mp3_dec, static_cast<const uint8_t *>(&mp3data[0]), mp3_count, static_cast<mp3d_sample_t *>(&samples[0]), &mp3_info);
+ sample_count = mp3dec_decode_frame(&mp3_dec, static_cast<const uint8_t *>(&mp3data[0]), mp3data_count, static_cast<mp3d_sample_t *>(&samples[0]), &mp3_info);
+ samples_idx = 0;
+ playback_status = PLAYBACK_STATE_BUFFER_FULL;
- if(!scount) {
- int to_drop = mp3_info.frame_bytes;
- // At 1MHz, we can transfer around 2082 bytes/video frame. So
- // that puts a boundary on how much we're ready to drop
- if(to_drop > 2082 || !to_drop)
- to_drop = 2082;
- std::copy(mp3data.begin() + to_drop, mp3data.end(), mp3data.begin());
- mp3_count -= to_drop;
+ if(sample_count == 0)
return;
- }
std::copy(mp3data.begin() + mp3_info.frame_bytes, mp3data.end(), mp3data.begin());
- mp3_count -= mp3_info.frame_bytes;
-
- sample_count = scount;
+ mp3data_count -= mp3_info.frame_bytes;
if(mp3_info.hz != current_rate) {
current_rate = mp3_info.hz;
stream->set_sample_rate(current_rate);
}
+
+ decoded_frame_count++;
}
void mas3507d_device::append_buffer(std::vector<write_stream_view> &outputs, int &pos, int scount)
{
- buffered_frame_count = scount;
-
int s1 = scount - pos;
+ int bytes_per_sample = mp3_info.channels > 2 ? 2 : mp3_info.channels; // More than 2 channels is unsupported here
+
if(s1 > sample_count)
s1 = sample_count;
- if(mp3_info.channels == 1) {
- for(int i=0; i<s1; i++) {
- outputs[0].put_int(i+pos, samples[i], 32768);
- outputs[1].put_int(i+pos, samples[i], 32768);
- }
- } else {
- for(int i=0; i<s1; i++) {
- outputs[0].put_int(i+pos, samples[i*2], 32768);
- outputs[1].put_int(i+pos, samples[i*2+1], 32768);
- }
- }
+ playback_status = PLAYBACK_STATE_DEMAND_BUFFER;
- if(s1 == sample_count) {
- pos += s1;
- sample_count = 0;
- total_frame_count += s1;
- return;
+ for(int i = 0; i < s1; i++) {
+ outputs[0].put_int(pos, samples[samples_idx * bytes_per_sample], 32768);
+ outputs[1].put_int(pos, samples[samples_idx * bytes_per_sample + (bytes_per_sample >> 1)], 32768);
+
+ samples_idx++;
+ decoded_samples++;
+ pos++;
+
+ if(samples_idx >= sample_count) {
+ sample_count = 0;
+ return;
+ }
}
+}
- if(mp3_info.channels == 1)
- std::copy(samples.begin() + s1, samples.begin() + sample_count, samples.begin());
- else
- std::copy(samples.begin() + s1*2, samples.begin() + sample_count*2, samples.begin());
+void mas3507d_device::reset_playback()
+{
+ mp3dec_init(&mp3_dec);
+ mp3data_count = 0;
+ sample_count = 0;
+ decoded_frame_count = 0;
+ decoded_samples = 0;
+ playback_status = PLAYBACK_STATE_IDLE;
+ is_started = false;
+ samples_idx = 0;
+ std::fill(mp3data.begin(), mp3data.end(), 0);
+ std::fill(samples.begin(), samples.end(), 0);
+}
- pos += s1;
- sample_count -= s1;
- total_frame_count += s1;
+void mas3507d_device::start_playback()
+{
+ reset_playback();
+ is_started = true;
}
void mas3507d_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
@@ -401,25 +494,19 @@ void mas3507d_device::sound_stream_update(sound_stream &stream, std::vector<read
int csamples = outputs[0].samples();
int pos = 0;
- append_buffer(outputs, pos, csamples);
- for(;;) {
- if(pos == csamples)
- return;
- fill_buffer();
- if(!sample_count) {
- // In the case of a bad frame or no frames being around, reset the state of the decoder
- mp3dec_init(&mp3_dec);
- memset(mp3data.data(), 0, mp3data.size());
- memset(samples.data(), 0, samples.size());
- mp3_count = 0;
- sample_count = 0;
- total_frame_count = 0;
- buffered_frame_count = 0;
+ while(pos < csamples) {
+ if(is_started && sample_count == 0)
+ fill_buffer();
+ if(!is_started || sample_count <= 0) {
+ playback_status = PLAYBACK_STATE_IDLE;
+ decoded_frame_count = 0;
+ decoded_samples = 0;
outputs[0].fill(0, pos);
outputs[1].fill(0, pos);
return;
}
+
append_buffer(outputs, pos, csamples);
}
}
diff --git a/src/devices/sound/mas3507d.h b/src/devices/sound/mas3507d.h
index b04e157e2f2..36f95de72db 100644
--- a/src/devices/sound/mas3507d.h
+++ b/src/devices/sound/mas3507d.h
@@ -12,6 +12,12 @@
class mas3507d_device : public device_t, public device_sound_interface
{
public:
+ enum {
+ PLAYBACK_STATE_IDLE,
+ PLAYBACK_STATE_BUFFER_FULL,
+ PLAYBACK_STATE_DEMAND_BUFFER
+ };
+
// construction/destruction
mas3507d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
@@ -22,7 +28,15 @@ public:
void i2c_scl_w(bool line);
void i2c_sda_w(bool line);
- u32 get_frame_count() const { return total_frame_count - buffered_frame_count; }
+ uint32_t get_samples() const { return decoded_samples; }
+ uint32_t get_status() const { return playback_status; }
+
+ void update_stream() { stream->update(); }
+
+ void reset_playback();
+ void start_playback();
+
+ bool is_started;
protected:
virtual void device_start() override;
@@ -30,40 +44,62 @@ protected:
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
private:
+ void i2c_nak();
+ bool i2c_device_got_address(uint8_t address);
+ void i2c_device_got_byte(uint8_t byte);
+ void i2c_device_got_stop();
+
+ void mem_write(int bank, uint32_t adr, uint32_t val);
+ void run_program(uint32_t adr);
+ void reg_write(uint32_t adr, uint32_t val);
+
+ void fill_buffer();
+ void append_buffer(std::vector<write_stream_view> &outputs, int &pos, int scount);
+
devcb_read16 cb_sample;
- enum { IDLE, STARTED, NAK, ACK, ACK2 } i2c_bus_state;
- enum { UNKNOWN, VALIDATED, WRONG } i2c_bus_address;
+ enum {
+ CMD_DEV_WRITE = 0x3a,
+ CMD_DEV_READ = 0x3b,
- std::array<u8, 0xe00> mp3data;
- std::array<mp3d_sample_t, MINIMP3_MAX_SAMPLES_PER_FRAME> samples;
- bool i2c_scli, i2c_sclo, i2c_sdai, i2c_sdao;
- int i2c_bus_curbit;
- uint8_t i2c_bus_curval;
- int mp3_count, sample_count, current_rate;
- u32 total_frame_count, buffered_frame_count;
+ CMD_DATA_WRITE = 0x68,
+ CMD_DATA_READ = 0x69,
+ CMD_CONTROL_WRITE = 0x6a
+ };
+
+ enum i2c_bus_state_t : uint8_t { IDLE = 0, STARTED, NAK, ACK, ACK2 };
+ enum i2c_bus_address_t : uint8_t { UNKNOWN = 0, VALIDATED, WRONG };
+ enum i2c_subdest_t : uint8_t { UNDEFINED = 0, CONTROL, DATA_READ, DATA_WRITE, BAD };
+ enum i2c_command_t : uint8_t { CMD_BAD = 0, CMD_RUN, CMD_READ_CTRL, CMD_WRITE_REG, CMD_WRITE_MEM, CMD_READ_REG, CMD_READ_MEM };
+
+ i2c_bus_state_t i2c_bus_state;
+ i2c_bus_address_t i2c_bus_address;
+ i2c_subdest_t i2c_subdest;
+ i2c_command_t i2c_command;
mp3dec_t mp3_dec;
mp3dec_frame_info_t mp3_info;
sound_stream *stream;
- void i2c_nak();
- bool i2c_device_got_address(uint8_t address);
- void i2c_device_got_byte(uint8_t byte);
- void i2c_device_got_stop();
+ std::array<uint8_t, 0xe00> mp3data;
+ std::array<mp3d_sample_t, MINIMP3_MAX_SAMPLES_PER_FRAME> samples;
- enum { UNDEFINED, CONTROL, DATA_READ, DATA_WRITE, BAD } i2c_subdest;
- enum { CMD_BAD, CMD_RUN, CMD_READ_CTRL, CMD_WRITE_REG, CMD_WRITE_MEM, CMD_READ_REG, CMD_READ_MEM } i2c_command;
+ bool i2c_scli, i2c_sclo, i2c_sdai, i2c_sdao;
+ int i2c_bus_curbit;
+ uint8_t i2c_bus_curval;
int i2c_bytecount;
uint32_t i2c_io_bank, i2c_io_adr, i2c_io_count, i2c_io_val;
+ uint32_t i2c_sdao_data;
- void mem_write(int bank, uint32_t adr, uint32_t val);
- void run_program(uint32_t adr);
- void reg_write(uint32_t adr, uint32_t val);
+ uint32_t mp3data_count, current_rate;
+ uint32_t decoded_frame_count, decoded_samples;
+ int32_t sample_count, samples_idx;
- void fill_buffer();
- void append_buffer(std::vector<write_stream_view> &outputs, int &pos, int samples);
+ bool is_muted;
+ float gain_ll, gain_rr;
+
+ uint32_t playback_status;
};
diff --git a/src/devices/sound/multipcm.cpp b/src/devices/sound/multipcm.cpp
index 4ea099b947a..1f3b86d83b5 100644
--- a/src/devices/sound/multipcm.cpp
+++ b/src/devices/sound/multipcm.cpp
@@ -13,7 +13,7 @@
* 3: MSB of pitch (ooooppppppppppxx) (o=octave (4 bit signed), p=pitch (10 bits), x=unused?
* 4: voice control: top bit = 1 for key on, 0 for key off
* 5: bit 0: 0: interpolate volume changes, 1: direct set volume,
- bits 1-7 = volume attenuate (0=max, 7f=min)
+ * bits 1-7 = volume attenuate (0=max, 7f=min)
* 6: LFO frequency + Phase LFO depth
* 7: Amplitude LFO size
*
@@ -21,7 +21,9 @@
* bytes per instrument sample. This is very similar to the YMF278B 'OPL4'.
* This sample format might be derived from the one used by the older YM7138 'GEW6' chip.
*
- * The first 3 bytes are the offset into the file (big endian). (0, 1, 2)
+ * The first 3 bytes are the offset into the file (big endian). (0, 1, 2).
+ * Bit 23 is the sample format flag: 0 for 8-bit linear, 1 for 12-bit linear.
+ * Bits 21 and 22 are used by the MU5 on some samples for as-yet unknown purposes.
* The next 2 are the loop start point, in samples (big endian) (3, 4)
* The next 2 are the 2's complement negation of of the total number of samples (big endian) (5, 6)
* The next byte is LFO freq + depth (copied to reg 6 ?) (7, 8)
@@ -29,8 +31,7 @@
* The next byte is Amplitude LFO size (copied to reg 7 ?)
*
* TODO
- * - http://dtech.lv/techarticles_yamaha_chips.html indicates FM and 12-bit sample support,
- * which we don't have yet.
+ * - http://dtech.lv/techarticles_yamaha_chips.html indicates FM support, which we don't have yet.
*/
#include "emu.h"
@@ -80,6 +81,7 @@ void multipcm_device::init_sample(sample_t *sample, uint32_t index)
uint32_t address = index * 12;
sample->m_start = (read_byte(address) << 16) | (read_byte(address + 1) << 8) | read_byte(address + 2);
+ sample->m_format = (sample->m_start>>20) & 0xfe;
sample->m_start &= 0x3fffff;
sample->m_loop = (read_byte(address + 3) << 8) | read_byte(address + 4);
sample->m_end = 0xffff - ((read_byte(address + 5) << 8) | read_byte(address + 6));
@@ -329,6 +331,7 @@ void multipcm_device::write_slot(slot_t &slot, int32_t reg, uint8_t data)
case 0: // PANPOT
slot.m_pan = (data >> 4) & 0xf;
break;
+
case 1: // Sample
{
//according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
@@ -365,6 +368,7 @@ void multipcm_device::write_slot(slot_t &slot, int32_t reg, uint8_t data)
slot.m_offset = 0;
slot.m_prev_sample = 0;
slot.m_total_level = slot.m_dest_total_level << TL_SHIFT;
+ slot.m_format = slot.m_sample.m_format;
envelope_generator_calc(slot);
slot.m_envelope_gen.m_state = state_t::ATTACK;
@@ -476,7 +480,7 @@ multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag,
void multipcm_device::device_start()
{
- const float clock_divider = 180.0f;
+ const float clock_divider = 224.0f;
m_rate = (float)clock() / clock_divider;
m_stream = stream_alloc(0, 2, m_rate);
@@ -587,6 +591,7 @@ void multipcm_device::device_start()
save_pointer(STRUCT_MEMBER(m_slots, m_dest_total_level), 28);
save_pointer(STRUCT_MEMBER(m_slots, m_total_level_step), 28);
save_pointer(STRUCT_MEMBER(m_slots, m_prev_sample), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_format), 28);
for (int32_t slot = 0; slot < 28; ++slot)
{
@@ -616,7 +621,7 @@ void multipcm_device::device_start()
void multipcm_device::device_clock_changed()
{
- const float clock_divider = 180.0f;
+ const float clock_divider = 224.0f;
m_rate = (float)clock() / clock_divider;
m_stream->set_sample_rate(m_rate);
@@ -680,10 +685,47 @@ void multipcm_device::sound_stream_update(sound_stream &stream, std::vector<read
if (slot.m_playing)
{
uint32_t vol = (slot.m_total_level >> TL_SHIFT) | (slot.m_pan << 7);
- uint32_t adr = slot.m_offset >> TL_SHIFT;
+ uint32_t spos = slot.m_offset >> TL_SHIFT;
uint32_t step = slot.m_step;
- int32_t csample = (int16_t) (read_byte(slot.m_base + adr) << 8);
+ int32_t csample = 0;
int32_t fpart = slot.m_offset & ((1 << TL_SHIFT) - 1);
+
+ if (slot.m_format & 8) // 12-bit linear
+ {
+ offs_t adr = slot.m_base + (spos >> 2) * 6;
+ switch (spos & 3)
+ {
+ case 0:
+ { // ab.c .... ....
+ s16 w0 = read_byte(adr) << 8 | ((read_byte(adr + 1) & 0xf) << 4);
+ csample = w0;
+ break;
+ }
+ case 1:
+ { // ..C. AB.. ....
+ s16 w0 = (read_byte(adr + 2) << 8) | (read_byte(adr + 1) & 0xf0);
+ csample = w0;
+ break;
+ }
+ case 2:
+ { // .... ..ab .c..
+ s16 w0 = read_byte(adr + 3) << 8 | ((read_byte(adr + 4) & 0xf) << 4);
+ csample = w0;
+ break;
+ }
+ case 3:
+ { // .... .... C.AB
+ s16 w0 = (read_byte(adr + 5) << 8) | (read_byte(adr + 4) & 0xf0);
+ csample = w0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ csample = (int16_t)(read_byte(slot.m_base + spos) << 8);
+ }
+
int32_t sample = (csample * fpart + slot.m_prev_sample * ((1 << TL_SHIFT) - fpart)) >> TL_SHIFT;
if (slot.m_regs[6] & 7) // Vibrato enabled
@@ -698,7 +740,7 @@ void multipcm_device::sound_stream_update(sound_stream &stream, std::vector<read
slot.m_offset = slot.m_sample.m_loop << TL_SHIFT;
}
- if (adr ^ (slot.m_offset >> TL_SHIFT))
+ if (spos ^ (slot.m_offset >> TL_SHIFT))
{
slot.m_prev_sample = csample;
}
diff --git a/src/devices/sound/multipcm.h b/src/devices/sound/multipcm.h
index e8de5a06851..1349c8cf980 100644
--- a/src/devices/sound/multipcm.h
+++ b/src/devices/sound/multipcm.h
@@ -48,6 +48,7 @@ private:
uint8_t m_key_rate_scale = 0;
uint8_t m_lfo_vibrato_reg = 0;
uint8_t m_lfo_amplitude_reg = 0;
+ uint8_t m_format = 0;
};
enum class state_t : u8
@@ -95,6 +96,7 @@ private:
envelope_gen_t m_envelope_gen;
lfo_t m_pitch_lfo; // Pitch lfo
lfo_t m_amplitude_lfo; // AM lfo
+ uint8_t m_format;
};
// internal state
diff --git a/src/devices/sound/namco.cpp b/src/devices/sound/namco.cpp
index 694dad0cd29..27a540872c2 100644
--- a/src/devices/sound/namco.cpp
+++ b/src/devices/sound/namco.cpp
@@ -452,7 +452,7 @@ void namco_device::polepos_sound_w(offs_t offset, uint8_t data)
case 0x23:
voice->waveform_select = data & 7;
- /* fall through */
+ [[fallthrough]];
case 0x02:
case 0x03:
voice->volume[0] = voice->volume[1] = 0;
@@ -522,6 +522,7 @@ void namco_15xx_device::namco_15xx_w(offs_t offset, uint8_t data)
case 0x06:
voice->waveform_select = (data >> 4) & 7;
+ [[fallthrough]];
case 0x04:
case 0x05:
/* the frequency has 20 bits */
@@ -598,6 +599,7 @@ void namco_cus30_device::namcos1_sound_w(offs_t offset, uint8_t data)
case 0x01:
voice->waveform_select = (data >> 4) & 15;
+ [[fallthrough]];
case 0x02:
case 0x03:
/* the frequency has 20 bits */
diff --git a/src/devices/sound/s14001a.cpp b/src/devices/sound/s14001a.cpp
index aa4506ba1c8..50f2ca07eaa 100644
--- a/src/devices/sound/s14001a.cpp
+++ b/src/devices/sound/s14001a.cpp
@@ -116,19 +116,7 @@ uint8_t Mux8To2(bool bVoicedP2, uint8_t uPPQtrP2, uint8_t uDeltaAdrP2, uint8_t u
uDeltaAdrP2 ^= 0x03; // count backwards
// emulate 8 to 2 mux to obtain delta from byte (bigendian)
- switch (uDeltaAdrP2)
- {
- case 0x00:
- return (uRomDataP2 & 0xC0) >> 6;
- case 0x01:
- return (uRomDataP2 & 0x30) >> 4;
- case 0x02:
- return (uRomDataP2 & 0x0C) >> 2;
- case 0x03:
- return (uRomDataP2 & 0x03) >> 0;
- default:
- return 0xFF;
- }
+ return uRomDataP2 >> (~uDeltaAdrP2 << 1 & 0x06) & 0x03;
}
diff --git a/src/devices/sound/samples.h b/src/devices/sound/samples.h
index 394af9d0fdf..e7c2e5660fa 100644
--- a/src/devices/sound/samples.h
+++ b/src/devices/sound/samples.h
@@ -119,7 +119,7 @@ protected:
};
// iterator, since lots of people are interested in these devices
-typedef device_type_iterator<samples_device> samples_device_iterator;
+typedef device_type_enumerator<samples_device> samples_device_enumerator;
// ======================> samples_iterator
diff --git a/src/devices/sound/sn76477.cpp b/src/devices/sound/sn76477.cpp
index b8db037e26b..1ccbd2fc4b5 100644
--- a/src/devices/sound/sn76477.cpp
+++ b/src/devices/sound/sn76477.cpp
@@ -895,9 +895,9 @@ void sn76477_device::open_wav_file()
std::string s = tag();
std::replace(s.begin(), s.end(), ':', '_');
- const std::string wav_file_name = util::string_format(LOG_WAV_FILE_NAME, s).c_str();
+ const std::string wav_file_name = util::string_format(LOG_WAV_FILE_NAME, s);
- m_file = wav_open(wav_file_name.c_str(), m_our_sample_rate, 2);
+ m_file = util::wav_open(wav_file_name, m_our_sample_rate, 2);
LOG(1, "SN76477: Logging output: %s\n", wav_file_name);
}
@@ -905,13 +905,13 @@ void sn76477_device::open_wav_file()
void sn76477_device::close_wav_file()
{
- wav_close(m_file);
+ m_file.reset();
}
void sn76477_device::add_wav_data(int16_t data_l, int16_t data_r)
{
- wav_add_data_16lr(m_file, &data_l, &data_r, 1);
+ util::wav_add_data_16lr(*m_file, &data_l, &data_r, 1);
}
diff --git a/src/devices/sound/sn76477.h b/src/devices/sound/sn76477.h
index 094f8e78e1b..6aa4c10c9f0 100644
--- a/src/devices/sound/sn76477.h
+++ b/src/devices/sound/sn76477.h
@@ -42,6 +42,8 @@
#include "machine/rescap.h"
+#include "wavwrite.h"
+
/*****************************************************************************
*
@@ -186,24 +188,24 @@ private:
double m_pitch_voltage;
// internal state
- double m_one_shot_cap_voltage; /* voltage on the one-shot cap */
- uint32_t m_one_shot_running_ff; /* 1 = one-shot running, 0 = stopped */
+ double m_one_shot_cap_voltage; // voltage on the one-shot cap
+ uint32_t m_one_shot_running_ff; // 1 = one-shot running, 0 = stopped
- double m_slf_cap_voltage; /* voltage on the SLF cap */
- uint32_t m_slf_out_ff; /* output of the SLF */
+ double m_slf_cap_voltage; // voltage on the SLF cap
+ uint32_t m_slf_out_ff; // output of the SLF
- double m_vco_cap_voltage; /* voltage on the VCO cap */
- uint32_t m_vco_out_ff; /* output of the VCO */
- uint32_t m_vco_alt_pos_edge_ff; /* keeps track of the # of positive edges for VCO Alt envelope */
+ double m_vco_cap_voltage; // voltage on the VCO cap
+ uint32_t m_vco_out_ff; // output of the VCO
+ uint32_t m_vco_alt_pos_edge_ff; // keeps track of the # of positive edges for VCO Alt envelope
- double m_noise_filter_cap_voltage; /* voltage on the noise filter cap */
- uint32_t m_real_noise_bit_ff; /* the current noise bit before filtering */
- uint32_t m_filtered_noise_bit_ff; /* the noise bit after filtering */
- uint32_t m_noise_gen_count; /* noise freq emulation */
+ double m_noise_filter_cap_voltage; // voltage on the noise filter cap
+ uint32_t m_real_noise_bit_ff; // the current noise bit before filtering
+ uint32_t m_filtered_noise_bit_ff; // the noise bit after filtering
+ uint32_t m_noise_gen_count; // noise freq emulation
- double m_attack_decay_cap_voltage; /* voltage on the attack/decay cap */
+ double m_attack_decay_cap_voltage; // voltage on the attack/decay cap
- uint32_t m_rng; /* current value of the random number generator */
+ uint32_t m_rng; // current value of the random number generator
// configured by the drivers and used to setup m_mixer_mode & m_envelope_mode at start
uint32_t m_mixer_a;
@@ -213,10 +215,10 @@ private:
uint32_t m_envelope_2;
/* others */
- sound_stream *m_channel; /* returned by stream_create() */
- int m_our_sample_rate; /* from machine.sample_rate() */
+ sound_stream *m_channel; // returned by stream_create()
+ int m_our_sample_rate; // from machine.sample_rate()
- wav_file *m_file; /* handle of the wave file to produce */
+ util::wav_file_ptr m_file; // handle of the wave file to produce
double compute_one_shot_cap_charging_rate();
double compute_one_shot_cap_discharging_rate();
diff --git a/src/devices/sound/spkrdev.cpp b/src/devices/sound/spkrdev.cpp
index 184a628fe73..cf5e761ee46 100644
--- a/src/devices/sound/spkrdev.cpp
+++ b/src/devices/sound/spkrdev.cpp
@@ -296,7 +296,6 @@ void speaker_sound_device::level_w(int new_level)
/* Finally update speaker state before returning */
m_level = new_level;
-
}
diff --git a/src/devices/sound/spu.cpp b/src/devices/sound/spu.cpp
index 9a8f503cf04..6cfba4fc5bc 100644
--- a/src/devices/sound/spu.cpp
+++ b/src/devices/sound/spu.cpp
@@ -12,6 +12,7 @@
#include "spu.h"
#include "spureverb.h"
#include "cpu/psx/psx.h"
+#include "corestr.h"
//
//
diff --git a/src/devices/sound/swp20.cpp b/src/devices/sound/swp20.cpp
index a9de3851fef..eef91ef9678 100644
--- a/src/devices/sound/swp20.cpp
+++ b/src/devices/sound/swp20.cpp
@@ -23,6 +23,9 @@ void swp20_device::device_reset()
{
m_p3c_port = 0x00;
m_p3c_address = true;
+ m_voice = 0x00;
+ m_keyon = 0;
+ m_keyoff = 0;
}
void swp20_device::rom_bank_updated()
@@ -66,7 +69,27 @@ u8 swp20_device::snd_r(offs_t offset)
void swp20_device::snd_w(offs_t offset, u8 data)
{
- logerror("w %02x, %02x %s\n", offset, data, machine().describe_context());
+ switch(offset) {
+ case 0x01:
+ m_voice = data & 0x1f;
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07: {
+ int off = 8*(offset & 3);
+ u32 mask = 0xff << off;
+ m_keyon = (m_keyon & ~mask) | (data << off);
+ logerror("keyon %08x\n", m_keyon);
+ break;
+ }
+ case 0x08: case 0x09: case 0x0a: case 0x0b: {
+ int off = 8*(offset & 3);
+ u32 mask = 0xff << off;
+ m_keyoff = (m_keyoff & ~mask) | (data << off);
+ logerror("keyoff %08x\n", m_keyoff);
+ break;
+ }
+ default:
+ logerror("w %02x.%02x, %02x %s\n", m_voice, offset, data, machine().describe_context());
+ }
}
void swp20_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
diff --git a/src/devices/sound/swp20.h b/src/devices/sound/swp20.h
index 7323dd64f17..af6bac38bc5 100644
--- a/src/devices/sound/swp20.h
+++ b/src/devices/sound/swp20.h
@@ -26,6 +26,9 @@ protected:
private:
u8 m_p3c_port;
bool m_p3c_address;
+ u8 m_voice;
+ u32 m_keyon;
+ u32 m_keyoff;
// Generic upload port
void p3c_w(u8 data);
diff --git a/src/devices/sound/tc8830f.cpp b/src/devices/sound/tc8830f.cpp
index 85635f2f466..f9f65975347 100644
--- a/src/devices/sound/tc8830f.cpp
+++ b/src/devices/sound/tc8830f.cpp
@@ -45,6 +45,9 @@ tc8830f_device::tc8830f_device(const machine_config &mconfig, const char *tag, d
void tc8830f_device::device_start()
{
+ // assumes it can make an address mask with m_mem.length() - 1
+ assert(!(m_mem.length() & (m_mem.length() - 1)));
+
// create the stream
m_stream = stream_alloc(0, 1, clock() / 0x10);
@@ -92,7 +95,7 @@ void tc8830f_device::sound_stream_update(sound_stream &stream, std::vector<read_
m_bitcount = (m_bitcount + 1) & 7;
if (m_bitcount == 0)
{
- m_address = (m_address + 1) & m_mem.mask();
+ m_address = (m_address + 1) & (m_mem.length() - 1);
if (m_address == m_stop_address)
m_playing = false;
}
@@ -197,7 +200,7 @@ void tc8830f_device::write_p(uint8_t data)
m_address = (m_address & ~(0xf << (m_cmd_rw*4))) | (data << (m_cmd_rw*4));
if (m_cmd_rw == 5)
{
- m_address &= m_mem.mask();
+ m_address &= m_mem.length() - 1;
m_bitcount = 0;
m_cmd_rw = -1;
}
@@ -208,7 +211,7 @@ void tc8830f_device::write_p(uint8_t data)
m_stop_address = (m_stop_address & ~(0xf << (m_cmd_rw*4))) | (data << (m_cmd_rw*4));
if (m_cmd_rw == 5)
{
- m_stop_address &= m_mem.mask();
+ m_stop_address &= m_mem.length() - 1;
m_cmd_rw = -1;
}
break;
@@ -232,9 +235,9 @@ void tc8830f_device::write_p(uint8_t data)
// update addresses and start
uint8_t offs = m_phrase * 4;
- m_address = (m_mem[offs] | m_mem[offs|1]<<8 | m_mem[offs|2]<<16) & m_mem.mask();
+ m_address = (m_mem[offs] | m_mem[offs|1]<<8 | m_mem[offs|2]<<16) & (m_mem.length() - 1);
offs += 4;
- m_stop_address = (m_mem[offs] | m_mem[offs|1]<<8 | m_mem[offs|2]<<16) & m_mem.mask();
+ m_stop_address = (m_mem[offs] | m_mem[offs|1]<<8 | m_mem[offs|2]<<16) & (m_mem.length() - 1);
m_bitcount = 0;
m_prevbits = 0;
diff --git a/src/devices/sound/tms5110.cpp b/src/devices/sound/tms5110.cpp
index 5782aa905af..14bb5523322 100644
--- a/src/devices/sound/tms5110.cpp
+++ b/src/devices/sound/tms5110.cpp
@@ -1509,7 +1509,7 @@ DEFINE_DEVICE_TYPE(TMSPROM, tmsprom_device, "tmsprom", "TMSPROM")
tmsprom_device::tmsprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TMSPROM, tag, owner, clock),
m_rom(*this, DEVICE_SELF),
- m_prom(*this, finder_base::DUMMY_TAG, 0x20),
+ m_prom(*this, finder_base::DUMMY_TAG),
m_rom_size(0),
m_pdc_bit(0),
m_ctl1_bit(0),
diff --git a/src/devices/sound/tms5220.cpp b/src/devices/sound/tms5220.cpp
index d0afb710f46..05c5c3464df 100644
--- a/src/devices/sound/tms5220.cpp
+++ b/src/devices/sound/tms5220.cpp
@@ -1770,6 +1770,7 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
case 0x03:
/* High Impedance */
m_io_ready = param;
+ break;
case 0x00:
/* illegal */
m_io_ready = param;
diff --git a/src/devices/sound/uda1344.cpp b/src/devices/sound/uda1344.cpp
new file mode 100644
index 00000000000..8cc08d936b7
--- /dev/null
+++ b/src/devices/sound/uda1344.cpp
@@ -0,0 +1,290 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/***************************************************************************
+
+ Philips UDA1344 Stereo Audio Codec skeleton
+
+****************************************************************************/
+
+#include "emu.h"
+#include "sound/uda1344.h"
+
+#define LOG_ADDR (1 << 1)
+#define LOG_STATUS_REG (1 << 2)
+#define LOG_DATA_REG (1 << 3)
+#define LOG_INPUT (1 << 4)
+#define LOG_OVERRUNS (1 << 5)
+#define LOG_ALL (LOG_ADDR | LOG_STATUS_REG | LOG_DATA_REG | LOG_INPUT | LOG_OVERRUNS)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(UDA1344, uda1344_device, "ud1344", "Philips UDA1344 Codec")
+
+
+uda1344_device::uda1344_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, UDA1344, tag, owner, clock)
+ , device_sound_interface(mconfig, *this)
+ , m_stream(nullptr)
+ , m_volume(1.0)
+ , m_frequency(BASE_FREQUENCY)
+ , m_data_transfer_mode(0)
+ , m_status_reg(0)
+ , m_clock_divider(512)
+ , m_volume_reg(0)
+ , m_equalizer_reg(0)
+ , m_filter_reg(0)
+ , m_power_reg(0)
+ , m_dac_enable(false)
+ , m_adc_enable(false)
+ , m_l3_ack_out(*this)
+{
+}
+
+void uda1344_device::device_start()
+{
+ m_stream = stream_alloc(0, 2, BASE_FREQUENCY);
+
+ save_item(NAME(m_buffer[0]));
+ save_item(NAME(m_buffer[1]));
+ save_item(NAME(m_bufin));
+ save_item(NAME(m_bufout));
+ save_item(NAME(m_volume));
+ save_item(NAME(m_frequency));
+
+ save_item(NAME(m_data_transfer_mode));
+ save_item(NAME(m_status_reg));
+ save_item(NAME(m_clock_divider));
+ save_item(NAME(m_volume_reg));
+ save_item(NAME(m_equalizer_reg));
+ save_item(NAME(m_filter_reg));
+ save_item(NAME(m_power_reg));
+ save_item(NAME(m_dac_enable));
+ save_item(NAME(m_adc_enable));
+
+ m_l3_ack_out.resolve_safe();
+
+ m_buffer[0].resize(BUFFER_SIZE);
+ m_buffer[1].resize(BUFFER_SIZE);
+}
+
+void uda1344_device::device_reset()
+{
+ m_data_transfer_mode = 0;
+ m_status_reg = 0;
+ m_clock_divider = 512;
+ m_volume_reg = 0;
+ m_equalizer_reg = 0;
+ m_filter_reg = 0;
+ m_power_reg = 0;
+
+ m_dac_enable = false;
+ m_adc_enable = false;
+
+ m_volume = 1.0;
+ m_frequency = BASE_FREQUENCY;
+
+ memset(m_bufin, 0, sizeof(uint32_t) * 2);
+ memset(m_bufout, 0, sizeof(uint32_t) * 2);
+}
+
+void uda1344_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+{
+ for (int channel = 0; channel < 2 && channel < outputs.size(); channel++)
+ {
+ auto &output = outputs[channel];
+ uint32_t curout = m_bufout[channel];
+ uint32_t curin = m_bufin[channel];
+
+ // feed as much as we can
+ int sampindex;
+ for (sampindex = 0; curout != curin && sampindex < output.samples(); sampindex++)
+ {
+ output.put(sampindex, stream_buffer::sample_t(m_buffer[channel][curout]) * m_volume);
+ curout = (curout + 1) % BUFFER_SIZE;
+ }
+
+ // fill the rest with silence
+ output.fill(0, sampindex);
+
+ // save the new output pointer
+ m_bufout[channel] = curout;
+ }
+}
+
+void uda1344_device::ingest_samples(int16_t left, int16_t right)
+{
+ const int16_t samples[2] = { left, right };
+
+ const stream_buffer::sample_t sample_scale = 1.0 / 32768.0;
+ const stream_buffer::sample_t enable_scale = m_dac_enable ? 1.0 : 0.0;
+
+ m_stream->update();
+
+ for (int channel = 0; channel < 2; channel++)
+ {
+ int maxin = (m_bufout[channel] + BUFFER_SIZE - 1) % BUFFER_SIZE;
+ if (m_bufin[channel] != maxin)
+ {
+ m_buffer[channel][m_bufin[channel]] = stream_buffer::sample_t(samples[channel]) * sample_scale * enable_scale;
+ m_bufin[channel] = (m_bufin[channel] + 1) % BUFFER_SIZE;
+ }
+ else
+ {
+ LOGMASKED(LOG_OVERRUNS, "ingest_samples: buffer overrun (short 1 frame on channel %d)\n", channel);
+ }
+ }
+}
+
+void uda1344_device::device_clock_changed()
+{
+ if (clock() == 0)
+ return;
+
+ m_stream->update();
+ m_stream->set_sample_rate(clock() / m_clock_divider);
+}
+
+void uda1344_device::set_clock_divider(const uint32_t divider)
+{
+ m_clock_divider = divider;
+ device_clock_changed();
+}
+
+void uda1344_device::i2s_input_w(uint32_t data)
+{
+ const int16_t left = (int16_t)(data >> 16);
+ const int16_t right = (int16_t)data;
+ ingest_samples(left, right);
+}
+
+void uda1344_device::l3_addr_w(offs_t offset, uint8_t data)
+{
+ // Check for L3 address match, ignore if not addressed to us
+ if ((data & CHIP_ADDR_MASK) != CHIP_ADDR)
+ {
+ LOGMASKED(LOG_ADDR, "%s: L3 address %02x received, ignoring due to address mismatch\n", machine().describe_context(), data);
+ return;
+ }
+
+ m_data_transfer_mode = data & ~CHIP_ADDR_MASK;
+ LOGMASKED(LOG_ADDR, "%s: L3 address %02x received, preparing to receive data\n", machine().describe_context(), data);
+}
+
+void uda1344_device::l3_data_w(offs_t offset, uint8_t data)
+{
+ // Registers with bit 0 of the address set are unused
+ if (BIT(m_data_transfer_mode, 0))
+ {
+ LOGMASKED(LOG_DATA_REG, "%s: Data transfer mode has bit 0 set, ignoring L3 data write\n", machine().describe_context());
+ return;
+ }
+
+ if (BIT(m_data_transfer_mode, 1))
+ {
+ // Status transfer type
+ static const char *const s_clock_names[4] = { "512*freq", "384*freq", "256*freq", "unused" };
+ static const char *const s_format_names[8] =
+ {
+ "I2S-bus",
+ "LSB-justified 16-bits",
+ "LSB-justified 18-bits",
+ "LSB-justified 20-bits",
+ "MSB-justified",
+ "Input LSB-justified 16-bits / Output MSB-justified",
+ "Input LSB-justified 18-bits / Output MSB-justified",
+ "Input LSB-justified 20-bits / Output MSB-justified"
+ };
+ const uint8_t reg_bits = data & STATUS_REG_MASK;
+ LOGMASKED(LOG_STATUS_REG, "%s: Status register data: %02x (system clock: %s, format: %s, DC filtering: %s)\n", machine().describe_context(), reg_bits,
+ s_clock_names[(reg_bits & STATUS_SC_MASK) >> STATUS_SC_BIT],
+ s_format_names[(reg_bits & STATUS_IF_MASK) >> STATUS_IF_BIT],
+ BIT(reg_bits, STATUS_DC_BIT) ? "on" : "off");
+ m_status_reg = reg_bits;
+
+ switch ((reg_bits & STATUS_SC_MASK) >> STATUS_SC_BIT)
+ {
+ case 1:
+ set_clock_divider(384);
+ break;
+ case 2:
+ set_clock_divider(256);
+ break;
+ default:
+ set_clock_divider(512);
+ break;
+ }
+ }
+ else
+ {
+ // Data transfer type
+ switch ((data & REG_TYPE_MASK) >> REG_TYPE_BIT)
+ {
+ case VOLUME_REG:
+ {
+ m_stream->update();
+
+ const uint8_t reg_bits = data & VOLUME_REG_MASK;
+ if (reg_bits < 2)
+ {
+ LOGMASKED(LOG_DATA_REG, "%s: Volume register data: %02x, no attenuation\n", machine().describe_context(), reg_bits);
+ m_volume = 1.0;
+ }
+ else if (reg_bits >= 62)
+ {
+ LOGMASKED(LOG_DATA_REG, "%s: Volume register data: %02x, full attenuation\n", machine().describe_context(), reg_bits);
+ m_volume = 0.0;
+ }
+ else
+ {
+ LOGMASKED(LOG_DATA_REG, "%s: Volume register data: %02x, -%ddB attenuation\n", machine().describe_context(), reg_bits, reg_bits - 1);
+ m_volume = 1.0 - ((reg_bits - 1) / 62.0);
+ }
+
+ m_volume_reg = reg_bits;
+ break;
+ }
+
+ case EQUALIZER_REG:
+ {
+ const uint8_t reg_bits = data & EQUALIZER_REG_MASK;
+ LOGMASKED(LOG_DATA_REG, "%s: Equalizer register data: %02x (bass boost %02x, treble %d)\n", machine().describe_context(), reg_bits,
+ (reg_bits & EQUALIZER_BB_MASK) >> EQUALIZER_BB_BIT, (reg_bits & EQUALIZER_TR_MASK) >> EQUALIZER_TR_BIT);
+ m_equalizer_reg = reg_bits;
+ break;
+ }
+
+ case FILTER_REG:
+ {
+ static const char *const s_de_names[4] = { "none", "32kHz", "44.1kHz", "48kHz" };
+ static const char *const s_mode_names[4] = { "flat", "min(1)", "min(2)", "max" };
+ const uint8_t reg_bits = data & FILTER_REG_MASK;
+ LOGMASKED(LOG_DATA_REG, "%s: Filter register data: %02x (de-emphasis %s, mute %d, mode %s)\n", machine().describe_context(), reg_bits,
+ s_de_names[(reg_bits & FILTER_DE_MASK) >> FILTER_DE_BIT], BIT(reg_bits, FILTER_MT_BIT),
+ s_mode_names[(reg_bits & FILTER_MODE_MASK) >> FILTER_MODE_BIT]);
+ m_filter_reg = reg_bits;
+ break;
+ }
+
+ case POWER_REG:
+ {
+ const uint8_t reg_bits = data & POWER_REG_MASK;
+ LOGMASKED(LOG_DATA_REG, "%s: Power register data: %02x (ADC %s, DAC %s)\n", machine().describe_context(), reg_bits,
+ BIT(reg_bits, POWER_ADC_BIT) ? "on" : "off",
+ BIT(reg_bits, POWER_DAC_BIT) ? "on" : "off");
+ m_power_reg = reg_bits;
+
+ m_stream->update();
+ m_dac_enable = BIT(reg_bits, POWER_DAC_BIT);
+ m_adc_enable = BIT(reg_bits, POWER_ADC_BIT);
+ break;
+ }
+ }
+ }
+
+ // Pulse acknowledge line
+ m_l3_ack_out(1);
+ m_l3_ack_out(0);
+}
diff --git a/src/devices/sound/uda1344.h b/src/devices/sound/uda1344.h
new file mode 100644
index 00000000000..6d9041442c7
--- /dev/null
+++ b/src/devices/sound/uda1344.h
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/***************************************************************************
+
+ Philips UDA1344 Stereo Audio Codec skeleton
+
+****************************************************************************/
+
+#ifndef MAME_SOUND_UDA1344_H
+#define MAME_SOUND_UDA1344_H
+
+#pragma once
+
+class uda1344_device : public device_t, public device_sound_interface
+{
+public:
+ uda1344_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ void l3_addr_w(offs_t offset, uint8_t data);
+ void l3_data_w(offs_t offset, uint8_t data);
+
+ auto l3_ack_out() { return m_l3_ack_out.bind(); }
+
+ void i2s_input_w(uint32_t data);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_clock_changed() override;
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
+
+ void ingest_samples(int16_t left, int16_t right);
+
+ void set_clock_divider(const uint32_t divider);
+
+ static constexpr double BASE_FREQUENCY = 44100;
+ static constexpr size_t BUFFER_SIZE = 65536;
+
+ enum : uint8_t
+ {
+ CHIP_ADDR_MASK = 0xfc,
+ CHIP_ADDR = 0x14,
+
+ REG_TYPE_MASK = 0xc0,
+ REG_TYPE_BIT = 6,
+
+ VOLUME_REG = 0x00,
+ VOLUME_REG_MASK = 0x3f,
+
+ EQUALIZER_REG = 0x01,
+ EQUALIZER_REG_MASK = 0x3f,
+ EQUALIZER_BB_MASK = 0x3c,
+ EQUALIZER_BB_BIT = 2,
+ EQUALIZER_TR_MASK = 0x03,
+ EQUALIZER_TR_BIT = 0,
+
+ FILTER_REG = 0x02,
+ FILTER_REG_MASK = 0x1f,
+ FILTER_DE_MASK = 0x18,
+ FILTER_DE_BIT = 3,
+ FILTER_MT_BIT = 2,
+ FILTER_MODE_MASK = 0x03,
+ FILTER_MODE_BIT = 0,
+
+ POWER_REG = 0x03,
+ POWER_REG_MASK = 0x03,
+ POWER_ADC_BIT = 1,
+ POWER_DAC_BIT = 0,
+
+ STATUS_REG_MASK = 0x3f,
+ STATUS_SC_MASK = 0x30,
+ STATUS_SC_BIT = 4,
+ STATUS_IF_MASK = 0x0e,
+ STATUS_IF_BIT = 1,
+ STATUS_DC_BIT = 0
+ };
+
+ sound_stream *m_stream;
+ std::vector<stream_buffer::sample_t> m_buffer[2];
+ uint32_t m_bufin[2];
+ uint32_t m_bufout[2];
+ stream_buffer::sample_t m_volume;
+ double m_frequency;
+
+ uint8_t m_data_transfer_mode;
+ uint8_t m_status_reg;
+ uint32_t m_clock_divider;
+ uint8_t m_volume_reg;
+ uint8_t m_equalizer_reg;
+ uint8_t m_filter_reg;
+ uint8_t m_power_reg;
+
+ bool m_dac_enable;
+ bool m_adc_enable;
+
+ devcb_write_line m_l3_ack_out;
+};
+
+DECLARE_DEVICE_TYPE(UDA1344, uda1344_device)
+
+#endif // MAME_SOUND_UDA1344_H
diff --git a/src/devices/sound/ymf278b.cpp b/src/devices/sound/ymf278b.cpp
index f9f308a4892..50f655f1942 100644
--- a/src/devices/sound/ymf278b.cpp
+++ b/src/devices/sound/ymf278b.cpp
@@ -264,10 +264,10 @@ void ymf278b_device::sound_stream_update(sound_stream &stream, std::vector<read_
case 1:
if (slot->stepptr & 0x10000)
sample = read_byte(slot->startaddr + (slot->stepptr>>17)*3+2)<<8 |
- (read_byte(slot->startaddr + (slot->stepptr>>17)*3+1) << 4 & 0xf0);
+ (read_byte(slot->startaddr + (slot->stepptr>>17)*3+1) & 0xf0);
else
sample = read_byte(slot->startaddr + (slot->stepptr>>17)*3)<<8 |
- (read_byte(slot->startaddr + (slot->stepptr>>17)*3+1) & 0xf0);
+ ((read_byte(slot->startaddr + (slot->stepptr>>17)*3+1) << 4) & 0xf0);
break;
// 16 bit
diff --git a/src/devices/sound/ymz280b.cpp b/src/devices/sound/ymz280b.cpp
index b2836c74967..a9a87eb558f 100644
--- a/src/devices/sound/ymz280b.cpp
+++ b/src/devices/sound/ymz280b.cpp
@@ -452,8 +452,8 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, std::vector<read_
while (remaining > 0 && voice->output_pos < FRAC_ONE)
{
int interp_sample = ((s32(prev) * (FRAC_ONE - voice->output_pos)) + (s32(curr) * voice->output_pos)) >> FRAC_BITS;
- lacc.add_int(sampindex, interp_sample * lvol, 32768 * 256);
- racc.add_int(sampindex, interp_sample * rvol, 32768 * 256);
+ lacc.add_int(sampindex, interp_sample * lvol / 2, 32768 * 256);
+ racc.add_int(sampindex, interp_sample * rvol / 2, 32768 * 256);
sampindex++;
voice->output_pos += voice->output_step;
remaining--;
@@ -517,8 +517,8 @@ void ymz280b_device::sound_stream_update(sound_stream &stream, std::vector<read_
while (remaining > 0 && voice->output_pos < FRAC_ONE)
{
int interp_sample = ((s32(prev) * (FRAC_ONE - voice->output_pos)) + (s32(curr) * voice->output_pos)) >> FRAC_BITS;
- lacc.add_int(sampindex, interp_sample * lvol, 32768 * 256);
- racc.add_int(sampindex, interp_sample * rvol, 32768 * 256);
+ lacc.add_int(sampindex, interp_sample * lvol / 2, 32768 * 256);
+ racc.add_int(sampindex, interp_sample * rvol / 2, 32768 * 256);
sampindex++;
voice->output_pos += voice->output_step;
remaining--;