Mercurial > repos > blastem
comparison ym2612.c @ 935:01fb50390b27
Remove phase increment caching. Fix LFO phase modulation calculation
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 18 Feb 2016 21:28:33 -0800 |
parents | f33e8d88ab6f |
children | f1a8124ad881 |
comparison
equal
deleted
inserted
replaced
934:05b0a0d4fa40 | 935:01fb50390b27 |
---|---|
36 #define BIT_TIMERA_LOAD 0x40 | 36 #define BIT_TIMERA_LOAD 0x40 |
37 #define BIT_TIMERB_LOAD 0x80 | 37 #define BIT_TIMERB_LOAD 0x80 |
38 | 38 |
39 #define BIT_STATUS_TIMERA 0x1 | 39 #define BIT_STATUS_TIMERA 0x1 |
40 #define BIT_STATUS_TIMERB 0x2 | 40 #define BIT_STATUS_TIMERB 0x2 |
41 | |
42 uint32_t ym_calc_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op); | |
41 | 43 |
42 enum { | 44 enum { |
43 PHASE_ATTACK, | 45 PHASE_ATTACK, |
44 PHASE_DECAY, | 46 PHASE_DECAY, |
45 PHASE_SUSTAIN, | 47 PHASE_SUSTAIN, |
367 uint32_t op = context->current_op; | 369 uint32_t op = context->current_op; |
368 //printf("updating operator %d of channel %d\n", op, channel); | 370 //printf("updating operator %d of channel %d\n", op, channel); |
369 ym_operator * operator = context->operators + op; | 371 ym_operator * operator = context->operators + op; |
370 ym_channel * chan = context->channels + channel; | 372 ym_channel * chan = context->channels + channel; |
371 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | 373 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; |
372 operator->phase_counter += operator->phase_inc; | 374 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); |
373 if (chan->pms) { | |
374 //not entirely sure this will get the precision correct, but I'd like to avoid recalculating phase | |
375 //increment every update when LFO phase modulation is enabled | |
376 int16_t lfo_mod = lfo_pm_table[(chan->fnum & 0x7F0) * 16 + chan->pms + context->lfo_pm_step]; | |
377 if (operator->multiple) { | |
378 lfo_mod *= operator->multiple; | |
379 } else { | |
380 lfo_mod >>= 1; | |
381 } | |
382 operator->phase_counter += lfo_mod; | |
383 } | |
384 int16_t mod = 0; | 375 int16_t mod = 0; |
385 switch (op % 4) | 376 switch (op % 4) |
386 { | 377 { |
387 case 0://Operator 1 | 378 case 0://Operator 1 |
388 if (chan->feedback) { | 379 if (chan->feedback) { |
593 {0, 8,16,22}, //29 (0x1D) | 584 {0, 8,16,22}, //29 (0x1D) |
594 {0, 8,16,22}, //30 (0x1E) | 585 {0, 8,16,22}, //30 (0x1E) |
595 {0, 8,16,22} | 586 {0, 8,16,22} |
596 }; //31 (0x1F) | 587 }; //31 (0x1F) |
597 | 588 |
598 void ym_update_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op) | 589 uint32_t ym_calc_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op) |
599 { | 590 { |
600 uint32_t chan_num = op / 4; | 591 uint32_t chan_num = op / 4; |
601 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op); | 592 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op); |
602 //base frequency | 593 //base frequency |
603 ym_channel * channel = context->channels + chan_num; | 594 ym_channel * channel = context->channels + chan_num; |
604 uint32_t inc, detune; | 595 uint32_t inc, detune; |
605 if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) { | 596 if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) { |
606 //supplemental fnum registers are in a different order than normal slot paramters | 597 //supplemental fnum registers are in a different order than normal slot paramters |
607 int index = (op-2*4) ^ 2; | 598 int index = (op-2*4) ^ 2; |
608 inc = context->ch3_supp[index].fnum; | 599 inc = context->ch3_supp[index].fnum; |
600 if (channel->pms) { | |
601 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; | |
602 } | |
609 if (!context->ch3_supp[index].block) { | 603 if (!context->ch3_supp[index].block) { |
610 inc >>= 1; | 604 inc >>= 1; |
611 } else { | 605 } else { |
612 inc <<= (context->ch3_supp[index].block-1); | 606 inc <<= (context->ch3_supp[index].block-1); |
613 } | 607 } |
614 //detune | 608 //detune |
615 detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3]; | 609 detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3]; |
616 } else { | 610 } else { |
617 inc = channel->fnum; | 611 inc = channel->fnum; |
612 if (channel->pms) { | |
613 inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step]; | |
614 } | |
618 if (!channel->block) { | 615 if (!channel->block) { |
619 inc >>= 1; | 616 inc >>= 1; |
620 } else { | 617 } else { |
621 inc <<= (channel->block-1); | 618 inc <<= (channel->block-1); |
622 } | 619 } |
623 //detune | 620 //detune |
624 detune = detune_table[channel->keycode][operator->detune & 0x3]; | 621 detune = detune_table[channel->keycode][operator->detune & 0x3]; |
622 } | |
623 if (channel->pms) { | |
624 inc >>= 1; | |
625 } | 625 } |
626 if (operator->detune & 0x4) { | 626 if (operator->detune & 0x4) { |
627 inc -= detune; | 627 inc -= detune; |
628 //this can underflow, mask to 17-bit result | 628 //this can underflow, mask to 17-bit result |
629 inc &= 0x1FFFF; | 629 inc &= 0x1FFFF; |
637 } else { | 637 } else { |
638 //0.5 | 638 //0.5 |
639 inc >>= 1; | 639 inc >>= 1; |
640 } | 640 } |
641 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); | 641 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple); |
642 operator->phase_inc = inc; | 642 return inc; |
643 } | 643 } |
644 | 644 |
645 void ym_data_write(ym2612_context * context, uint8_t value) | 645 void ym_data_write(ym2612_context * context, uint8_t value) |
646 { | 646 { |
647 if (context->selected_reg >= YM_REG_END) { | 647 if (context->selected_reg >= YM_REG_END) { |
701 context->status &= ~BIT_STATUS_TIMERA; | 701 context->status &= ~BIT_STATUS_TIMERA; |
702 } | 702 } |
703 if (value & BIT_TIMERB_RESET) { | 703 if (value & BIT_TIMERB_RESET) { |
704 context->status &= ~BIT_STATUS_TIMERB; | 704 context->status &= ~BIT_STATUS_TIMERB; |
705 } | 705 } |
706 uint8_t old_mode = context->ch3_mode; | |
707 context->ch3_mode = value & 0xC0; | 706 context->ch3_mode = value & 0xC0; |
708 if (context->ch3_mode != old_mode) { | |
709 ym_update_phase_inc(context, context->operators + 2*4, 2*4); | |
710 ym_update_phase_inc(context, context->operators + 2*4+1, 2*4+1); | |
711 ym_update_phase_inc(context, context->operators + 2*4+2, 2*4+2); | |
712 } | |
713 break; | 707 break; |
714 } | 708 } |
715 case REG_KEY_ONOFF: { | 709 case REG_KEY_ONOFF: { |
716 uint8_t channel = value & 0x7; | 710 uint8_t channel = value & 0x7; |
717 if (channel != 3 && channel != 7) { | 711 if (channel != 3 && channel != 7) { |
758 switch (context->selected_reg & 0xF0) | 752 switch (context->selected_reg & 0xF0) |
759 { | 753 { |
760 case REG_DETUNE_MULT: | 754 case REG_DETUNE_MULT: |
761 operator->detune = value >> 4 & 0x7; | 755 operator->detune = value >> 4 & 0x7; |
762 operator->multiple = value & 0xF; | 756 operator->multiple = value & 0xF; |
763 ym_update_phase_inc(context, operator, op); | |
764 break; | 757 break; |
765 case REG_TOTAL_LEVEL: | 758 case REG_TOTAL_LEVEL: |
766 operator->total_level = (value & 0x7F) << 5; | 759 operator->total_level = (value & 0x7F) << 5; |
767 break; | 760 break; |
768 case REG_ATTACK_KS: | 761 case REG_ATTACK_KS: |
797 { | 790 { |
798 case REG_FNUM_LOW: | 791 case REG_FNUM_LOW: |
799 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; | 792 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7; |
800 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; | 793 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value; |
801 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; | 794 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7]; |
802 ym_update_phase_inc(context, context->operators + channel*4, channel*4); | |
803 ym_update_phase_inc(context, context->operators + channel*4+1, channel*4+1); | |
804 ym_update_phase_inc(context, context->operators + channel*4+2, channel*4+2); | |
805 ym_update_phase_inc(context, context->operators + channel*4+3, channel*4+3); | |
806 break; | 795 break; |
807 case REG_BLOCK_FNUM_H:{ | 796 case REG_BLOCK_FNUM_H:{ |
808 context->channels[channel].block_fnum_latch = value; | 797 context->channels[channel].block_fnum_latch = value; |
809 break; | 798 break; |
810 } | 799 } |
811 case REG_FNUM_LOW_CH3: | 800 case REG_FNUM_LOW_CH3: |
812 if (channel < 3) { | 801 if (channel < 3) { |
813 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; | 802 context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7; |
814 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; | 803 context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value; |
815 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; | 804 context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7]; |
816 if (context->ch3_mode) { | |
817 ym_update_phase_inc(context, context->operators + 2*4 + channel, 2*4); | |
818 } | |
819 } | 805 } |
820 break; | 806 break; |
821 case REG_BLOCK_FN_CH3: | 807 case REG_BLOCK_FN_CH3: |
822 if (channel < 3) { | 808 if (channel < 3) { |
823 context->ch3_supp[channel].block_fnum_latch = value; | 809 context->ch3_supp[channel].block_fnum_latch = value; |