Skip to content

Commit 24faec6

Browse files
CD-i: Fix XA Audio Peaking (#14470)
-cdicdic: Fixed audio peaking by decoding in 32-bit and clipping to 16 later. [Vincent Halver] -cdislavehle: Simplified mouse position-update logic. [Vincent Halver]
1 parent a24f85a commit 24faec6

File tree

4 files changed

+53
-166
lines changed

4 files changed

+53
-166
lines changed

src/mame/philips/cdicdic.cpp

Lines changed: 18 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@
4141
#define VERBOSE (0)
4242
#include "logmacro.h"
4343

44-
45-
namespace {
46-
47-
[[maybe_unused]] constexpr int16_t clip_int16(int32_t sample)
48-
{
49-
return int16_t(std::clamp<int32_t>(sample, -32768, 32767));
50-
}
51-
52-
} // anonymous namespace
53-
54-
5544
// device type definition
5645
DEFINE_DEVICE_TYPE(CDI_CDIC, cdicdic_device, "cdicdic", "CD-i CDIC")
5746

@@ -267,119 +256,33 @@ const uint8_t cdicdic_device::s_sector_scramble[2448] =
267256
// MEMBER FUNCTIONS
268257
//**************************************************************************
269258

270-
void cdicdic_device::decode_xa_unit(const uint8_t param, int16_t sample, int16_t &sample0, int16_t &sample1, int16_t &out_buffer)
271-
{
272-
int16_t const *const filter = s_xa_filter_coef[(param >> 4) & 3];
273-
uint8_t const range = (param & 0xf);
274-
sample = (sample >> range) + ((filter[0] * sample0 + filter[1] * sample1 + 128) >> 8);
275-
276-
//int16_t const sample16 = clip_int16(sample);
277-
sample1 = std::exchange(sample0, sample);
278-
out_buffer = sample0;
259+
static inline int16_t clip_int16(int32_t sample) {
260+
if (sample < -32768)
261+
return -32768;
262+
if (sample > 32767)
263+
return 32767;
264+
return static_cast<int16_t>(sample);
279265
}
280266

281-
void cdicdic_device::decode_xa_mono(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
282-
{
283-
for (int32_t b = 0; b < 18; b++)
284-
{
285-
for (int32_t s = 0; s < 4; s++)
286-
{
287-
uint8_t flags = xa[4 + (s << 1)];
288-
289-
for (int32_t i = 0; i < 28; i++)
290-
{
291-
//int16_t sample = ((*data) & 0xf) << 12;
292-
int16_t d = (xa[16 + (i << 2) + s] & 0xf) << 12;
293-
decode_xa_unit(flags, d, cdic_xa_last[0], cdic_xa_last[1], dp[0]);
294-
dp++;
295-
}
296-
297-
flags = xa[5 + (s << 1)];
298-
299-
for (int32_t i = 0; i < 28; i++)
300-
{
301-
//int16_t sample = (*data >> 4) << 12;
302-
int16_t d = (xa[16 + (i << 2) + s] >> 4) << 12;
303-
decode_xa_unit(flags, d, cdic_xa_last[0], cdic_xa_last[1], dp[0]);
304-
dp++;
305-
}
306-
}
307-
308-
xa += 128;
309-
}
267+
inline void rotate_samples(int16_t val, int16_t& a, int16_t& b, int16_t& output) {
268+
b = a;
269+
a = val;
270+
output = a;
310271
}
311272

312-
void cdicdic_device::decode_xa_mono8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
273+
void cdicdic_device::decode_xa_unit(const uint8_t param, int16_t sample, int16_t& sample0, int16_t& sample1, int16_t& out_buffer)
313274
{
314-
for (int32_t b = 0; b < 18; b++)
315-
{
316-
for (int32_t s = 0; s < 4; s++)
317-
{
318-
uint8_t flags = xa[4 + s];
319-
for (int32_t i = 0; i < 28; i++)
320-
{
321-
int16_t d = (xa[16 + (i << 2) + s] << 8);
322-
decode_xa_unit(flags, d, cdic_xa_last[0], cdic_xa_last[1], dp[0]);
323-
dp++;
324-
}
325-
}
326-
327-
xa += 128;
328-
}
329-
}
275+
const int16_t* filter = s_xa_filter_coef[(param >> 4) & 3]; // High bits are reserved.
276+
uint8_t range = (param & 0xf);
277+
if (range > 12) range = 12; // Should be at most 8. Some decoders set 13..15 to 9.
330278

331-
void cdicdic_device::decode_xa_stereo(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
332-
{
333-
for (int32_t b = 0; b < 18; b++)
334-
{
335-
for (int32_t s = 0; s < 4; s++)
336-
{
337-
uint8_t flags0 = xa[4 + (s << 1)];
338-
uint8_t flags1 = xa[5 + (s << 1)];
279+
int32_t sample32 = (int32_t)sample; // Work in 32-bit, clamp to avoid peaking audio.
280+
sample32 = (sample32 >> range) + (((int32_t)filter[0] * sample0 + (int32_t)filter[1] * sample1 + 128) >> 8);
339281

340-
for (int32_t i = 0; i < 28; i++)
341-
{
342-
int16_t d = xa[16 + (i << 2) + s];
343-
int16_t d0 = (d & 0xf) << 12;
344-
decode_xa_unit(flags0, d0, cdic_xa_last[0], cdic_xa_last[1], dp[0]);
345-
dp++;
346-
347-
int16_t d1 = (d >> 4) << 12;
348-
decode_xa_unit(flags1, d1, cdic_xa_last[2], cdic_xa_last[3], dp[0]);
349-
dp++;
350-
}
351-
}
352-
353-
xa += 128;
354-
}
282+
sample = clip_int16(sample32);
283+
rotate_samples(sample, sample0, sample1, out_buffer);
355284
}
356285

357-
void cdicdic_device::decode_xa_stereo8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
358-
{
359-
for (int32_t b = 0; b < 18; b++)
360-
{
361-
for (int32_t s = 0; s < 4; s += 2)
362-
{
363-
uint8_t flags0 = xa[4 + s];
364-
uint8_t flags1 = xa[5 + s];
365-
366-
for (int32_t i = 0; i < 28; i++)
367-
{
368-
int16_t d0 = (xa[16 + (i << 2) + s + 0] << 8);
369-
370-
decode_xa_unit(flags0, d0, cdic_xa_last[0], cdic_xa_last[1], dp[0]);
371-
dp++;
372-
373-
int16_t d1 = (xa[16 + (i << 2) + s + 1] << 8);
374-
decode_xa_unit(flags1, d1, cdic_xa_last[2], cdic_xa_last[3], dp[0]);
375-
dp++;
376-
}
377-
}
378-
xa += 128;
379-
}
380-
}
381-
382-
383286
void cdicdic_device::decode_8bit_xa_unit(int channel, uint8_t param, const uint8_t *data, int16_t *out_buffer)
384287
{
385288
int16_t *const old_samples = &m_xa_last[channel << 1];

src/mame/philips/cdicdic.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ class cdicdic_device : public device_t
215215
uint32_t lba_from_time();
216216

217217
static uint8_t get_sector_count_for_coding(uint8_t coding);
218-
void decode_xa_mono(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
219-
void decode_xa_mono8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
220-
void decode_xa_stereo(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
221-
void decode_xa_stereo8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
222218

223219
static const int16_t s_xa_filter_coef[4][2];
224220
static const int32_t s_samples_per_sector;

src/mame/philips/cdislavehle.cpp

Lines changed: 34 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -141,59 +141,46 @@ void cdislave_hle_device::set_mouse_position()
141141
m_device_mouse_y = ((m_in_buf[1] & 0x0f) << 6) | (m_in_buf[0] & 0x3f);
142142
}
143143

144+
void cdislave_hle_device::slave_w_mouse(offs_t offset, uint16_t data)
145+
{
146+
m_in_buf[m_in_index] = data & 0x00ff;
147+
bool set_mouse = m_in_buf[0] >= 0xc0;
148+
if (set_mouse)
149+
{
150+
if (m_in_index == 0)
151+
{
152+
LOGMASKED(LOG_COMMANDS, "slave_w: Channel %d: Update Mouse Position (0x%02x)\n", offset, data & 0x00ff);
153+
m_in_count = 3;
154+
}
155+
else
156+
{
157+
if (m_in_index == m_in_count - 1)
158+
{
159+
// Update Mouse Position
160+
set_mouse_position();
161+
memset(m_in_buf, 0, 17);
162+
m_in_index = 0;
163+
m_in_count = 0;
164+
return;
165+
}
166+
}
167+
}
168+
else
169+
{
170+
LOGMASKED(LOG_COMMANDS | LOG_UNKNOWNS, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff);
171+
if (m_in_index == 0){
172+
return;
173+
}
174+
}
175+
m_in_index++;
176+
}
144177
void cdislave_hle_device::slave_w(offs_t offset, uint16_t data)
145178
{
146179
LOGMASKED(LOG_WRITES, "slave_w: Channel %d: %d = %02x\n", offset, m_in_index, data & 0x00ff);
147180
switch (offset)
148181
{
149182
case 0:
150-
if (m_in_index)
151-
{
152-
m_in_buf[m_in_index] = data & 0x00ff;
153-
m_in_index++;
154-
if (m_in_index == m_in_count)
155-
{
156-
switch (m_in_buf[0])
157-
{
158-
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
159-
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
160-
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
161-
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
162-
case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
163-
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
164-
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
165-
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: // Update Mouse Position
166-
set_mouse_position();
167-
memset(m_in_buf, 0, 17);
168-
m_in_index = 0;
169-
m_in_count = 0;
170-
break;
171-
}
172-
}
173-
}
174-
else
175-
{
176-
m_in_buf[m_in_index] = data & 0x00ff;
177-
m_in_index++;
178-
switch (data & 0x00ff)
179-
{
180-
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
181-
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
182-
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
183-
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
184-
case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
185-
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
186-
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
187-
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
188-
LOGMASKED(LOG_COMMANDS, "slave_w: Channel %d: Update Mouse Position (0x%02x)\n", offset, data & 0x00ff);
189-
m_in_count = 3;
190-
break;
191-
default:
192-
LOGMASKED(LOG_COMMANDS | LOG_UNKNOWNS, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff);
193-
m_in_index = 0;
194-
break;
195-
}
196-
}
183+
slave_w_mouse(offset, data);
197184
break;
198185
case 1:
199186
if (m_in_index)

src/mame/philips/cdislavehle.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class cdislave_hle_device : public device_t
4343

4444
uint16_t slave_r(offs_t offset);
4545
void slave_w(offs_t offset, uint16_t data);
46+
void slave_w_mouse(offs_t offset, uint16_t data);
4647

4748
protected:
4849
// device_t implementation

0 commit comments

Comments
 (0)