Mercurial > repos > blastem
comparison ym2612.c @ 2554:76259d246695
Fix YM2612 channel accumulator precision
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 11 Jan 2025 17:58:58 -0800 |
parents | 9fb04d29049e |
children | 78e1769efcdb |
comparison
equal
deleted
inserted
replaced
2553:35f765c2bc87 | 2554:76259d246695 |
---|---|
583 } | 583 } |
584 operator->output = output; | 584 operator->output = output; |
585 //Update the channel output if we've updated all operators | 585 //Update the channel output if we've updated all operators |
586 if (op % 4 == 3) { | 586 if (op % 4 == 3) { |
587 if (chan->algorithm < 4) { | 587 if (chan->algorithm < 4) { |
588 chan->output = operator->output; | 588 chan->output = operator->output & ~0x1F; |
589 chan->phase_overflow = operator->phase_overflow; | 589 chan->phase_overflow = operator->phase_overflow; |
590 } else if(chan->algorithm == 4) { | 590 } else if(chan->algorithm == 4) { |
591 ym_operator *other_op = context->operators + channel * 4 + 2; | 591 ym_operator *other_op = context->operators + channel * 4 + 2; |
592 chan->output = operator->output + other_op->output; | 592 chan->output = (operator->output & ~0x1F) + (other_op->output & ~0x1F); |
593 if (chan->output > 0x1FE0) { | |
594 chan->output = 0x1FE0; | |
595 } else if (chan->output < -0x1FF0) { | |
596 chan->output = - 0x1FF0; | |
597 } | |
593 if (operator->phase_inc < other_op->phase_inc) { | 598 if (operator->phase_inc < other_op->phase_inc) { |
594 chan->phase_overflow = operator->phase_overflow; | 599 chan->phase_overflow = operator->phase_overflow; |
595 } else { | 600 } else { |
596 chan->phase_overflow = other_op->phase_overflow; | 601 chan->phase_overflow = other_op->phase_overflow; |
597 } | 602 } |
598 } else { | 603 } else { |
599 output = 0; | 604 output = 0; |
600 uint32_t lowest_phase_inc = 0xFFFFFFFF; | 605 uint32_t lowest_phase_inc = 0xFFFFFFFF; |
601 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | 606 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { |
602 output += context->operators[op].output; | 607 output += context->operators[op].output & ~0x1F; |
608 if (output > 0x1FE0) { | |
609 output = 0x1FE0; | |
610 } else if (output < -0x1FF0) { | |
611 output = - 0x1FF0; | |
612 } | |
603 if (context->operators[op].phase_inc < lowest_phase_inc) { | 613 if (context->operators[op].phase_inc < lowest_phase_inc) { |
604 lowest_phase_inc = context->operators[op].phase_inc; | 614 lowest_phase_inc = context->operators[op].phase_inc; |
605 chan->phase_overflow = context->operators[op].phase_overflow; | 615 chan->phase_overflow = context->operators[op].phase_overflow; |
606 } | 616 } |
607 } | 617 } |
615 void ym_output_sample(ym2612_context *context) | 625 void ym_output_sample(ym2612_context *context) |
616 { | 626 { |
617 int16_t left = 0, right = 0; | 627 int16_t left = 0, right = 0; |
618 for (int i = 0; i < NUM_CHANNELS; i++) { | 628 for (int i = 0; i < NUM_CHANNELS; i++) { |
619 int16_t value = context->channels[i].output; | 629 int16_t value = context->channels[i].output; |
620 if (value > 0x1FE0) { | |
621 value = 0x1FE0; | |
622 } else if (value < -0x1FF0) { | |
623 value = -0x1FF0; | |
624 } else { | |
625 value &= 0x3FE0; | |
626 if (value & 0x2000) { | |
627 value |= 0xC000; | |
628 } | |
629 } | |
630 if (value >= 0) { | 630 if (value >= 0) { |
631 value += context->zero_offset; | 631 value += context->zero_offset; |
632 } else { | 632 } else { |
633 value -= context->zero_offset; | 633 value -= context->zero_offset; |
634 } | 634 } |