|
41 | 41 | #define VERBOSE (0) |
42 | 42 | #include "logmacro.h" |
43 | 43 |
|
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 | | - |
55 | 44 | // device type definition |
56 | 45 | DEFINE_DEVICE_TYPE(CDI_CDIC, cdicdic_device, "cdicdic", "CD-i CDIC") |
57 | 46 |
|
@@ -267,119 +256,33 @@ const uint8_t cdicdic_device::s_sector_scramble[2448] = |
267 | 256 | // MEMBER FUNCTIONS |
268 | 257 | //************************************************************************** |
269 | 258 |
|
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); |
279 | 265 | } |
280 | 266 |
|
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; |
310 | 271 | } |
311 | 272 |
|
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) |
313 | 274 | { |
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. |
330 | 278 |
|
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); |
339 | 281 |
|
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); |
355 | 284 | } |
356 | 285 |
|
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 | | - |
383 | 286 | void cdicdic_device::decode_8bit_xa_unit(int channel, uint8_t param, const uint8_t *data, int16_t *out_buffer) |
384 | 287 | { |
385 | 288 | int16_t *const old_samples = &m_xa_last[channel << 1]; |
|
0 commit comments