comparison ym2612.c @ 1879:43a6cee4fd00

Split ym_run into a few different functions to enhance clarity
author Michael Pavone <pavone@retrodev.com>
date Fri, 06 Sep 2019 09:13:44 -0700
parents ce6881d64eef
children e77f7a7c79a5
comparison
equal deleted inserted replaced
1878:881083d76212 1879:43a6cee4fd00
336 keyoff(context->operators + op); 336 keyoff(context->operators + op);
337 } 337 }
338 } 338 }
339 } 339 }
340 340
341 void ym_run_timers(ym2612_context *context)
342 {
343 if (context->timer_control & BIT_TIMERA_ENABLE) {
344 if (context->timer_a != TIMER_A_MAX) {
345 context->timer_a++;
346 if (context->csm_keyon) {
347 csm_keyoff(context);
348 }
349 } else {
350 if (context->timer_control & BIT_TIMERA_LOAD) {
351 context->timer_control &= ~BIT_TIMERA_LOAD;
352 } else if (context->timer_control & BIT_TIMERA_OVEREN) {
353 context->status |= BIT_STATUS_TIMERA;
354 }
355 context->timer_a = context->timer_a_load;
356 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) {
357 context->csm_keyon = 0xF0;
358 uint8_t changes = 0xF0 ^ context->channels[2].keyon;;
359 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
360 {
361 if (changes & keyon_bits[bit]) {
362 keyon(context->operators + op, context->channels + 2);
363 }
364 }
365 }
366 }
367 }
368 if (!context->sub_timer_b) {
369 if (context->timer_control & BIT_TIMERB_ENABLE) {
370 if (context->timer_b != TIMER_B_MAX) {
371 context->timer_b++;
372 } else {
373 if (context->timer_control & BIT_TIMERB_LOAD) {
374 context->timer_control &= ~BIT_TIMERB_LOAD;
375 } else if (context->timer_control & BIT_TIMERB_OVEREN) {
376 context->status |= BIT_STATUS_TIMERB;
377 }
378 context->timer_b = context->timer_b_load;
379 }
380 }
381 }
382 context->sub_timer_b += 0x10;
383 //Update LFO
384 if (context->lfo_enable) {
385 if (context->lfo_counter) {
386 context->lfo_counter--;
387 } else {
388 context->lfo_counter = lfo_timer_values[context->lfo_freq];
389 context->lfo_am_step += 2;
390 context->lfo_am_step &= 0xFE;
391 context->lfo_pm_step = context->lfo_am_step / 8;
392 }
393 }
394 }
395
396 void ym_run_envelope(ym2612_context *context, ym_channel *channel, ym_operator *operator)
397 {
398 uint32_t env_cyc = context->env_counter;
399 uint8_t rate;
400 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
401 //operator->envelope = operator->sustain_level;
402 operator->env_phase = PHASE_SUSTAIN;
403 }
404 rate = operator->rates[operator->env_phase];
405 if (rate) {
406 uint8_t ks = channel->keycode >> operator->key_scaling;;
407 rate = rate*2 + ks;
408 if (rate > 63) {
409 rate = 63;
410 }
411 }
412 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
413 if (!(env_cyc & ((1 << cycle_shift) - 1))) {
414 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
415 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle];
416 if (operator->env_phase == PHASE_ATTACK) {
417 //this can probably be optimized to a single shift rather than a multiply + shift
418 uint16_t old_env = operator->envelope;
419 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC;
420 if (operator->envelope > old_env) {
421 //Handle overflow
422 operator->envelope = 0;
423 }
424 if (!operator->envelope) {
425 operator->env_phase = PHASE_DECAY;
426 }
427 } else {
428 if (operator->ssg) {
429 if (operator->envelope < SSG_CENTER) {
430 envelope_inc *= 4;
431 } else {
432 envelope_inc = 0;
433 }
434 }
435 //envelope value is 10-bits, but it will be used as a 4.8 value
436 operator->envelope += envelope_inc << 2;
437 //clamp to max attenuation value
438 if (
439 operator->envelope > MAX_ENVELOPE
440 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER)
441 ) {
442 operator->envelope = MAX_ENVELOPE;
443 }
444 }
445 }
446 }
447
448 void ym_run_phase(ym2612_context *context, uint32_t channel, uint32_t op)
449 {
450 if (channel != 5 || !context->dac_enable) {
451 //printf("updating operator %d of channel %d\n", op, channel);
452 ym_operator * operator = context->operators + op;
453 ym_channel * chan = context->channels + channel;
454 uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
455 operator->phase_counter += ym_calc_phase_inc(context, operator, op);
456 int16_t mod = 0;
457 if (op & 3) {
458 if (operator->mod_src[0]) {
459 mod = *operator->mod_src[0];
460 if (operator->mod_src[1]) {
461 mod += *operator->mod_src[1];
462 }
463 mod >>= YM_MOD_SHIFT;
464 }
465 } else {
466 if (chan->feedback) {
467 mod = (chan->op1_old + operator->output) >> (10-chan->feedback);
468 }
469 }
470 uint16_t env = operator->envelope;
471 if (operator->ssg) {
472 if (env >= SSG_CENTER) {
473 if (operator->ssg & SSG_ALTERNATE) {
474 if (operator->env_phase != PHASE_RELEASE && (
475 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0
476 )) {
477 operator->inverted ^= SSG_INVERT;
478 }
479 } else if (!(operator->ssg & SSG_HOLD)) {
480 phase = operator->phase_counter = 0;
481 }
482 if (
483 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN)
484 && !(operator->ssg & SSG_HOLD)
485 ) {
486 start_envelope(operator, chan);
487 env = operator->envelope;
488 }
489 }
490 if (operator->inverted) {
491 env = (SSG_CENTER - env) & MAX_ENVELOPE;
492 }
493 }
494 env += operator->total_level;
495 if (operator->am) {
496 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E;
497 if (ams_shift[chan->ams] >= 0) {
498 env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE;
499 } else {
500 env += base_am << (-ams_shift[chan->ams]);
501 }
502 }
503 if (env > MAX_ENVELOPE) {
504 env = MAX_ENVELOPE;
505 }
506 if (first_key_on) {
507 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]);
508 }
509 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) {
510 phase += mod;
511 //}
512
513 int16_t output = pow_table[sine_table[phase & 0x1FF] + env];
514 if (phase & 0x200) {
515 output = -output;
516 }
517 if (op % 4 == 0) {
518 chan->op1_old = operator->output;
519 } else if (op % 4 == 2) {
520 chan->op2_old = operator->output;
521 }
522 operator->output = output;
523 //Update the channel output if we've updated all operators
524 if (op % 4 == 3) {
525 if (chan->algorithm < 4) {
526 chan->output = operator->output;
527 } else if(chan->algorithm == 4) {
528 chan->output = operator->output + context->operators[channel * 4 + 2].output;
529 } else {
530 output = 0;
531 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
532 output += context->operators[op].output;
533 }
534 chan->output = output;
535 }
536 if (first_key_on) {
537 int16_t value = context->channels[channel].output & 0x3FE0;
538 if (value & 0x2000) {
539 value |= 0xC000;
540 }
541 }
542 }
543 //puts("operator update done");
544 }
545 }
546
547 void ym_output_sample(ym2612_context *context)
548 {
549 int16_t left = 0, right = 0;
550 for (int i = 0; i < NUM_CHANNELS; i++) {
551 int16_t value = context->channels[i].output;
552 if (value > 0x1FE0) {
553 value = 0x1FE0;
554 } else if (value < -0x1FF0) {
555 value = -0x1FF0;
556 } else {
557 value &= 0x3FE0;
558 if (value & 0x2000) {
559 value |= 0xC000;
560 }
561 }
562 if (value >= 0) {
563 value += context->zero_offset;
564 } else {
565 value -= context->zero_offset;
566 }
567 if (context->channels[i].logfile) {
568 fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
569 }
570 if (context->channels[i].lr & 0x80) {
571 left += (value * context->volume_mult) / context->volume_div;
572 } else if (context->zero_offset) {
573 if (value >= 0) {
574 left += (context->zero_offset * context->volume_mult) / context->volume_div;
575 } else {
576 left -= (context->zero_offset * context->volume_mult) / context->volume_div;
577 }
578 }
579 if (context->channels[i].lr & 0x40) {
580 right += (value * context->volume_mult) / context->volume_div;
581 } else if (context->zero_offset) {
582 if (value >= 0) {
583 right += (context->zero_offset * context->volume_mult) / context->volume_div;
584 } else {
585 right -= (context->zero_offset * context->volume_mult) / context->volume_div;
586 }
587 }
588 }
589 render_put_stereo_sample(context->audio, left, right);
590 }
591
341 void ym_run(ym2612_context * context, uint32_t to_cycle) 592 void ym_run(ym2612_context * context, uint32_t to_cycle)
342 { 593 {
594 if (context->current_cycle >= to_cycle) {
595 return;
596 }
343 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); 597 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
344 //TODO: Fix channel update order OR remap channels in register write 598 //TODO: Fix channel update order OR remap channels in register write
345 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) { 599 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) {
346 //Update timers at beginning of 144 cycle period 600 //Update timers at beginning of 144 cycle period
347 if (!context->current_op) { 601 if (!context->current_op) {
348 if (context->timer_control & BIT_TIMERA_ENABLE) { 602 ym_run_timers(context);
349 if (context->timer_a != TIMER_A_MAX) {
350 context->timer_a++;
351 if (context->csm_keyon) {
352 csm_keyoff(context);
353 }
354 } else {
355 if (context->timer_control & BIT_TIMERA_LOAD) {
356 context->timer_control &= ~BIT_TIMERA_LOAD;
357 } else if (context->timer_control & BIT_TIMERA_OVEREN) {
358 context->status |= BIT_STATUS_TIMERA;
359 }
360 context->timer_a = context->timer_a_load;
361 if (!context->csm_keyon && context->ch3_mode == CSM_MODE) {
362 context->csm_keyon = 0xF0;
363 uint8_t changes = 0xF0 ^ context->channels[2].keyon;;
364 for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
365 {
366 if (changes & keyon_bits[bit]) {
367 keyon(context->operators + op, context->channels + 2);
368 }
369 }
370 }
371 }
372 }
373 if (!context->sub_timer_b) {
374 if (context->timer_control & BIT_TIMERB_ENABLE) {
375 if (context->timer_b != TIMER_B_MAX) {
376 context->timer_b++;
377 } else {
378 if (context->timer_control & BIT_TIMERB_LOAD) {
379 context->timer_control &= ~BIT_TIMERB_LOAD;
380 } else if (context->timer_control & BIT_TIMERB_OVEREN) {
381 context->status |= BIT_STATUS_TIMERB;
382 }
383 context->timer_b = context->timer_b_load;
384 }
385 }
386 }
387 context->sub_timer_b += 0x10;
388 //Update LFO
389 if (context->lfo_enable) {
390 if (context->lfo_counter) {
391 context->lfo_counter--;
392 } else {
393 context->lfo_counter = lfo_timer_values[context->lfo_freq];
394 context->lfo_am_step += 2;
395 context->lfo_am_step &= 0xFE;
396 context->lfo_pm_step = context->lfo_am_step / 8;
397 }
398 }
399 } 603 }
400 //Update Envelope Generator 604 //Update Envelope Generator
401 if (!(context->current_op % 3)) { 605 if (!(context->current_op % 3)) {
402 uint32_t env_cyc = context->env_counter;
403 uint32_t op = context->current_env_op; 606 uint32_t op = context->current_env_op;
404 ym_operator * operator = context->operators + op; 607 ym_operator * operator = context->operators + op;
405 ym_channel * channel = context->channels + op/4; 608 ym_channel * channel = context->channels + op/4;
406 uint8_t rate; 609 ym_run_envelope(context, channel, operator);
407 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
408 //operator->envelope = operator->sustain_level;
409 operator->env_phase = PHASE_SUSTAIN;
410 }
411 rate = operator->rates[operator->env_phase];
412 if (rate) {
413 uint8_t ks = channel->keycode >> operator->key_scaling;;
414 rate = rate*2 + ks;
415 if (rate > 63) {
416 rate = 63;
417 }
418 }
419 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
420 if (first_key_on) {
421 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1));
422 }
423 if (!(env_cyc & ((1 << cycle_shift) - 1))) {
424 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
425 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle];
426 if (operator->env_phase == PHASE_ATTACK) {
427 //this can probably be optimized to a single shift rather than a multiply + shift
428 if (first_key_on) {
429 dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc);
430 }
431 uint16_t old_env = operator->envelope;
432 operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC;
433 if (operator->envelope > old_env) {
434 //Handle overflow
435 operator->envelope = 0;
436 }
437 if (!operator->envelope) {
438 operator->env_phase = PHASE_DECAY;
439 }
440 } else {
441 if (first_key_on) {
442 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc,
443 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release"));
444 }
445 if (operator->ssg) {
446 if (operator->envelope < SSG_CENTER) {
447 envelope_inc *= 4;
448 } else {
449 envelope_inc = 0;
450 }
451 }
452 //envelope value is 10-bits, but it will be used as a 4.8 value
453 operator->envelope += envelope_inc << 2;
454 //clamp to max attenuation value
455 if (
456 operator->envelope > MAX_ENVELOPE
457 || (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER)
458 ) {
459 operator->envelope = MAX_ENVELOPE;
460 }
461 }
462 }
463 context->current_env_op++; 610 context->current_env_op++;
464 if (context->current_env_op == NUM_OPERATORS) { 611 if (context->current_env_op == NUM_OPERATORS) {
465 context->current_env_op = 0; 612 context->current_env_op = 0;
466 context->env_counter++; 613 context->env_counter++;
467 } 614 }
468 } 615 }
469 616
470 //Update Phase Generator 617 //Update Phase Generator
471 uint32_t channel = context->current_op / 4; 618 ym_run_phase(context, context->current_op / 4, context->current_op);
472 if (channel != 5 || !context->dac_enable) {
473 uint32_t op = context->current_op;
474 //printf("updating operator %d of channel %d\n", op, channel);
475 ym_operator * operator = context->operators + op;
476 ym_channel * chan = context->channels + channel;
477 uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
478 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op);
479 int16_t mod = 0;
480 if (op & 3) {
481 if (operator->mod_src[0]) {
482 mod = *operator->mod_src[0];
483 if (operator->mod_src[1]) {
484 mod += *operator->mod_src[1];
485 }
486 mod >>= YM_MOD_SHIFT;
487 }
488 } else {
489 if (chan->feedback) {
490 mod = (chan->op1_old + operator->output) >> (10-chan->feedback);
491 }
492 }
493 uint16_t env = operator->envelope;
494 if (operator->ssg) {
495 if (env >= SSG_CENTER) {
496 if (operator->ssg & SSG_ALTERNATE) {
497 if (operator->env_phase != PHASE_RELEASE && (
498 !(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0
499 )) {
500 operator->inverted ^= SSG_INVERT;
501 }
502 } else if (!(operator->ssg & SSG_HOLD)) {
503 phase = operator->phase_counter = 0;
504 }
505 if (
506 (operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN)
507 && !(operator->ssg & SSG_HOLD)
508 ) {
509 start_envelope(operator, chan);
510 env = operator->envelope;
511 }
512 }
513 if (operator->inverted) {
514 env = (SSG_CENTER - env) & MAX_ENVELOPE;
515 }
516 }
517 env += operator->total_level;
518 if (operator->am) {
519 uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E;
520 if (ams_shift[chan->ams] >= 0) {
521 env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE;
522 } else {
523 env += base_am << (-ams_shift[chan->ams]);
524 }
525 }
526 if (env > MAX_ENVELOPE) {
527 env = MAX_ENVELOPE;
528 }
529 if (first_key_on) {
530 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]);
531 }
532 //if ((channel != 0 && channel != 4) || chan->algorithm != 5) {
533 phase += mod;
534 //}
535
536 int16_t output = pow_table[sine_table[phase & 0x1FF] + env];
537 if (phase & 0x200) {
538 output = -output;
539 }
540 if (op % 4 == 0) {
541 chan->op1_old = operator->output;
542 } else if (op % 4 == 2) {
543 chan->op2_old = operator->output;
544 }
545 operator->output = output;
546 //Update the channel output if we've updated all operators
547 if (op % 4 == 3) {
548 if (chan->algorithm < 4) {
549 chan->output = operator->output;
550 } else if(chan->algorithm == 4) {
551 chan->output = operator->output + context->operators[channel * 4 + 2].output;
552 } else {
553 output = 0;
554 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
555 output += context->operators[op].output;
556 }
557 chan->output = output;
558 }
559 if (first_key_on) {
560 int16_t value = context->channels[channel].output & 0x3FE0;
561 if (value & 0x2000) {
562 value |= 0xC000;
563 }
564 dfprintf(debug_file, "channel %d output: %d\n", channel, (value * context->volume_mult) / context->volume_div);
565 }
566 }
567 //puts("operator update done");
568 }
569 context->current_op++; 619 context->current_op++;
570 if (context->current_op == NUM_OPERATORS) { 620 if (context->current_op == NUM_OPERATORS) {
571 context->current_op = 0; 621 context->current_op = 0;
572 622 ym_output_sample(context);
573 int16_t left = 0, right = 0;
574 for (int i = 0; i < NUM_CHANNELS; i++) {
575 int16_t value = context->channels[i].output;
576 if (value > 0x1FE0) {
577 value = 0x1FE0;
578 } else if (value < -0x1FF0) {
579 value = -0x1FF0;
580 } else {
581 value &= 0x3FE0;
582 if (value & 0x2000) {
583 value |= 0xC000;
584 }
585 }
586 if (value >= 0) {
587 value += context->zero_offset;
588 } else {
589 value -= context->zero_offset;
590 }
591 if (context->channels[i].logfile) {
592 fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
593 }
594 if (context->channels[i].lr & 0x80) {
595 left += (value * context->volume_mult) / context->volume_div;
596 } else if (context->zero_offset) {
597 if (value >= 0) {
598 left += (context->zero_offset * context->volume_mult) / context->volume_div;
599 } else {
600 left -= (context->zero_offset * context->volume_mult) / context->volume_div;
601 }
602 }
603 if (context->channels[i].lr & 0x40) {
604 right += (value * context->volume_mult) / context->volume_div;
605 } else if (context->zero_offset) {
606 if (value >= 0) {
607 right += (context->zero_offset * context->volume_mult) / context->volume_div;
608 } else {
609 right -= (context->zero_offset * context->volume_mult) / context->volume_div;
610 }
611 }
612 }
613 render_put_stereo_sample(context->audio, left, right);
614 } 623 }
615 624
616 } 625 }
617 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { 626 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) {
618 context->status &= 0x7F; 627 context->status &= 0x7F;