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;