Mercurial > repos > blastem
comparison ym2612.c @ 1692:5dacaef602a7 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 05 Jan 2019 00:58:08 -0800 |
parents | 804f13c090b4 |
children | 5278b6e44fc1 |
comparison
equal
deleted
inserted
replaced
1504:95b3a1a8b26c | 1692:5dacaef602a7 |
---|---|
114 wave_finalize(log_context->channels[i].logfile); | 114 wave_finalize(log_context->channels[i].logfile); |
115 } | 115 } |
116 } | 116 } |
117 log_context = NULL; | 117 log_context = NULL; |
118 } | 118 } |
119 #define BUFFER_INC_RES 0x40000000UL | |
120 | 119 |
121 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) | 120 void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) |
122 { | 121 { |
123 uint64_t old_inc = context->buffer_inc; | 122 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); |
124 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc * NUM_OPERATORS; | |
125 } | 123 } |
126 | 124 |
127 #ifdef __ANDROID__ | 125 #ifdef __ANDROID__ |
128 #define log2(x) (log(x)/log(2)) | 126 #define log2(x) (log(x)/log(2)) |
129 #endif | 127 #endif |
135 void ym_reset(ym2612_context *context) | 133 void ym_reset(ym2612_context *context) |
136 { | 134 { |
137 memset(context->part1_regs, 0, sizeof(context->part1_regs)); | 135 memset(context->part1_regs, 0, sizeof(context->part1_regs)); |
138 memset(context->part2_regs, 0, sizeof(context->part2_regs)); | 136 memset(context->part2_regs, 0, sizeof(context->part2_regs)); |
139 memset(context->operators, 0, sizeof(context->operators)); | 137 memset(context->operators, 0, sizeof(context->operators)); |
138 FILE* savedlogs[NUM_CHANNELS]; | |
139 for (int i = 0; i < NUM_CHANNELS; i++) | |
140 { | |
141 savedlogs[i] = context->channels[i].logfile; | |
142 } | |
140 memset(context->channels, 0, sizeof(context->channels)); | 143 memset(context->channels, 0, sizeof(context->channels)); |
141 memset(context->ch3_supp, 0, sizeof(context->ch3_supp)); | 144 memset(context->ch3_supp, 0, sizeof(context->ch3_supp)); |
142 context->selected_reg = 0; | 145 context->selected_reg = 0; |
143 context->csm_keyon = 0; | 146 context->csm_keyon = 0; |
144 context->ch3_mode = 0; | 147 context->ch3_mode = 0; |
153 //TODO: Reset LFO state | 156 //TODO: Reset LFO state |
154 | 157 |
155 //some games seem to expect that the LR flags start out as 1 | 158 //some games seem to expect that the LR flags start out as 1 |
156 for (int i = 0; i < NUM_CHANNELS; i++) { | 159 for (int i = 0; i < NUM_CHANNELS; i++) { |
157 context->channels[i].lr = 0xC0; | 160 context->channels[i].lr = 0xC0; |
161 context->channels[i].logfile = savedlogs[i]; | |
158 } | 162 } |
159 context->write_cycle = CYCLE_NEVER; | 163 context->write_cycle = CYCLE_NEVER; |
160 for (int i = 0; i < NUM_OPERATORS; i++) { | 164 for (int i = 0; i < NUM_OPERATORS; i++) { |
161 context->operators[i].envelope = MAX_ENVELOPE; | 165 context->operators[i].envelope = MAX_ENVELOPE; |
162 context->operators[i].env_phase = PHASE_RELEASE; | 166 context->operators[i].env_phase = PHASE_RELEASE; |
163 } | 167 } |
164 } | 168 } |
165 | 169 |
166 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit, uint32_t options, uint32_t lowpass_cutoff) | 170 void ym_init(ym2612_context * context, uint32_t master_clock, uint32_t clock_div, uint32_t options) |
167 { | 171 { |
168 static uint8_t registered_finalize; | 172 static uint8_t registered_finalize; |
169 dfopen(debug_file, "ym_debug.txt", "w"); | 173 dfopen(debug_file, "ym_debug.txt", "w"); |
170 memset(context, 0, sizeof(*context)); | 174 memset(context, 0, sizeof(*context)); |
171 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | |
172 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | |
173 context->sample_rate = sample_rate; | |
174 context->clock_inc = clock_div * 6; | 175 context->clock_inc = clock_div * 6; |
175 ym_adjust_master_clock(context, master_clock); | 176 context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); |
176 | |
177 double rc = (1.0 / (double)lowpass_cutoff) / (2.0 * M_PI); | |
178 double dt = 1.0 / ((double)master_clock / (double)(context->clock_inc * NUM_OPERATORS)); | |
179 double alpha = dt / (dt + rc); | |
180 context->lowpass_alpha = (int32_t)(((double)0x10000) * alpha); | |
181 | |
182 context->sample_limit = sample_limit*2; | |
183 | 177 |
184 //some games seem to expect that the LR flags start out as 1 | 178 //some games seem to expect that the LR flags start out as 1 |
185 for (int i = 0; i < NUM_CHANNELS; i++) { | 179 for (int i = 0; i < NUM_CHANNELS; i++) { |
186 if (options & YM_OPT_WAVE_LOG) { | 180 if (options & YM_OPT_WAVE_LOG) { |
187 char fname[64]; | 181 char fname[64]; |
189 FILE * f = context->channels[i].logfile = fopen(fname, "wb"); | 183 FILE * f = context->channels[i].logfile = fopen(fname, "wb"); |
190 if (!f) { | 184 if (!f) { |
191 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname); | 185 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname); |
192 continue; | 186 continue; |
193 } | 187 } |
194 if (!wave_init(f, sample_rate, 16, 1)) { | 188 if (!wave_init(f, master_clock / (context->clock_inc * NUM_OPERATORS), 16, 1)) { |
195 fclose(f); | 189 fclose(f); |
196 context->channels[i].logfile = NULL; | 190 context->channels[i].logfile = NULL; |
197 } | 191 } |
198 } | 192 } |
199 } | 193 } |
264 ym_reset(context); | 258 ym_reset(context); |
265 } | 259 } |
266 | 260 |
267 void ym_free(ym2612_context *context) | 261 void ym_free(ym2612_context *context) |
268 { | 262 { |
263 render_free_source(context->audio); | |
269 if (context == log_context) { | 264 if (context == log_context) { |
270 ym_finalize_log(); | 265 ym_finalize_log(); |
271 } | 266 } |
272 free(context->audio_buffer); | |
273 //TODO: Figure out how to make this 100% safe | |
274 //audio thread could still be using this | |
275 free(context->back_buffer); | |
276 free(context); | 267 free(context); |
277 } | 268 } |
278 | 269 |
279 #define YM_VOLUME_MULTIPLIER 2 | 270 #define YM_VOLUME_MULTIPLIER 2 |
280 #define YM_VOLUME_DIVIDER 3 | 271 #define YM_VOLUME_DIVIDER 3 |
473 ym_operator * operator = context->operators + op; | 464 ym_operator * operator = context->operators + op; |
474 ym_channel * chan = context->channels + channel; | 465 ym_channel * chan = context->channels + channel; |
475 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | 466 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; |
476 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); | 467 operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); |
477 int16_t mod = 0; | 468 int16_t mod = 0; |
478 switch (op % 4) | 469 if (op & 3) { |
479 { | 470 if (operator->mod_src[0]) { |
480 case 0://Operator 1 | 471 mod = *operator->mod_src[0]; |
472 if (operator->mod_src[1]) { | |
473 mod += * | |
474 operator->mod_src[1]; | |
475 } | |
476 mod >>= YM_MOD_SHIFT; | |
477 } | |
478 } else { | |
481 if (chan->feedback) { | 479 if (chan->feedback) { |
482 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); | 480 mod = (chan->op1_old + operator->output) >> (10-chan->feedback); |
483 } | 481 } |
484 break; | |
485 case 1://Operator 3 | |
486 switch(chan->algorithm) | |
487 { | |
488 case 0: | |
489 case 2: | |
490 //modulate by operator 2 | |
491 mod = context->operators[op+1].output >> YM_MOD_SHIFT; | |
492 break; | |
493 case 1: | |
494 //modulate by operator 1+2 | |
495 mod = (context->operators[op-1].output + context->operators[op+1].output) >> YM_MOD_SHIFT; | |
496 break; | |
497 case 5: | |
498 //modulate by operator 1 | |
499 mod = context->operators[op-1].output >> YM_MOD_SHIFT; | |
500 } | |
501 break; | |
502 case 2://Operator 2 | |
503 if (chan->algorithm != 1 && chan->algorithm != 2 && chan->algorithm != 7) { | |
504 //modulate by Operator 1 | |
505 mod = context->operators[op-2].output >> YM_MOD_SHIFT; | |
506 } | |
507 break; | |
508 case 3://Operator 4 | |
509 switch(chan->algorithm) | |
510 { | |
511 case 0: | |
512 case 1: | |
513 case 4: | |
514 //modulate by operator 3 | |
515 mod = context->operators[op-2].output >> YM_MOD_SHIFT; | |
516 break; | |
517 case 2: | |
518 //modulate by operator 1+3 | |
519 mod = (context->operators[op-3].output + context->operators[op-2].output) >> YM_MOD_SHIFT; | |
520 break; | |
521 case 3: | |
522 //modulate by operator 2+3 | |
523 mod = (context->operators[op-1].output + context->operators[op-2].output) >> YM_MOD_SHIFT; | |
524 break; | |
525 case 5: | |
526 //modulate by operator 1 | |
527 mod = context->operators[op-3].output >> YM_MOD_SHIFT; | |
528 break; | |
529 } | |
530 break; | |
531 } | 482 } |
532 uint16_t env = operator->envelope; | 483 uint16_t env = operator->envelope; |
533 if (operator->ssg) { | 484 if (operator->ssg) { |
534 if (env >= SSG_CENTER) { | 485 if (env >= SSG_CENTER) { |
535 if (operator->ssg & SSG_ALTERNATE) { | 486 if (operator->ssg & SSG_ALTERNATE) { |
605 } | 556 } |
606 context->current_op++; | 557 context->current_op++; |
607 if (context->current_op == NUM_OPERATORS) { | 558 if (context->current_op == NUM_OPERATORS) { |
608 context->current_op = 0; | 559 context->current_op = 0; |
609 | 560 |
610 context->buffer_fraction += context->buffer_inc; | |
611 int16_t left = 0, right = 0; | 561 int16_t left = 0, right = 0; |
612 for (int i = 0; i < NUM_CHANNELS; i++) { | 562 for (int i = 0; i < NUM_CHANNELS; i++) { |
613 int16_t value = context->channels[i].output; | 563 int16_t value = context->channels[i].output; |
614 if (value > 0x1FE0) { | 564 if (value > 0x1FE0) { |
615 value = 0x1FE0; | 565 value = 0x1FE0; |
619 value &= 0x3FE0; | 569 value &= 0x3FE0; |
620 if (value & 0x2000) { | 570 if (value & 0x2000) { |
621 value |= 0xC000; | 571 value |= 0xC000; |
622 } | 572 } |
623 } | 573 } |
624 if (context->channels[i].logfile && context->buffer_fraction > BUFFER_INC_RES) { | 574 if (context->channels[i].logfile) { |
625 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); | 575 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); |
626 } | 576 } |
627 if (context->channels[i].lr & 0x80) { | 577 if (context->channels[i].lr & 0x80) { |
628 left += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; | 578 left += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; |
629 } | 579 } |
630 if (context->channels[i].lr & 0x40) { | 580 if (context->channels[i].lr & 0x40) { |
631 right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; | 581 right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; |
632 } | 582 } |
633 } | 583 } |
634 int32_t tmp = left * context->lowpass_alpha + context->last_left * (0x10000 - context->lowpass_alpha); | 584 render_put_stereo_sample(context->audio, left, right); |
635 left = tmp >> 16; | |
636 tmp = right * context->lowpass_alpha + context->last_right * (0x10000 - context->lowpass_alpha); | |
637 right = tmp >> 16; | |
638 while (context->buffer_fraction > BUFFER_INC_RES) { | |
639 context->buffer_fraction -= BUFFER_INC_RES; | |
640 | |
641 int64_t tmp = context->last_left * ((context->buffer_fraction << 16) / context->buffer_inc); | |
642 tmp += left * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc)); | |
643 context->audio_buffer[context->buffer_pos] = tmp >> 16; | |
644 | |
645 tmp = context->last_right * ((context->buffer_fraction << 16) / context->buffer_inc); | |
646 tmp += right * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc)); | |
647 context->audio_buffer[context->buffer_pos+1] = tmp >> 16; | |
648 | |
649 context->buffer_pos += 2; | |
650 if (context->buffer_pos == context->sample_limit) { | |
651 if (!headless) { | |
652 render_wait_ym(context); | |
653 } | |
654 } | |
655 } | |
656 context->last_left = left; | |
657 context->last_right = right; | |
658 } | 585 } |
659 | 586 |
660 } | 587 } |
661 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { | 588 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { |
662 context->status &= 0x7F; | 589 context->status &= 0x7F; |
967 context->ch3_supp[channel].block_fnum_latch = value; | 894 context->ch3_supp[channel].block_fnum_latch = value; |
968 } | 895 } |
969 break; | 896 break; |
970 case REG_ALG_FEEDBACK: | 897 case REG_ALG_FEEDBACK: |
971 context->channels[channel].algorithm = value & 0x7; | 898 context->channels[channel].algorithm = value & 0x7; |
899 switch (context->channels[channel].algorithm) | |
900 { | |
901 case 0: | |
902 //operator 3 modulated by operator 2 | |
903 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; | |
904 context->operators[channel*4+1].mod_src[1] = NULL; | |
905 | |
906 //operator 2 modulated by operator 1 | |
907 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; | |
908 | |
909 //operator 4 modulated by operator 3 | |
910 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; | |
911 context->operators[channel*4+3].mod_src[1] = NULL; | |
912 break; | |
913 case 1: | |
914 //operator 3 modulated by operator 1+2 | |
915 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; | |
916 context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output; | |
917 | |
918 //operator 2 unmodulated | |
919 context->operators[channel*4+2].mod_src[0] = NULL; | |
920 | |
921 //operator 4 modulated by operator 3 | |
922 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; | |
923 context->operators[channel*4+3].mod_src[1] = NULL; | |
924 break; | |
925 case 2: | |
926 //operator 3 modulated by operator 2 | |
927 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; | |
928 context->operators[channel*4+1].mod_src[1] = NULL; | |
929 | |
930 //operator 2 unmodulated | |
931 context->operators[channel*4+2].mod_src[0] = NULL; | |
932 | |
933 //operator 4 modulated by operator 1+3 | |
934 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; | |
935 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; | |
936 break; | |
937 case 3: | |
938 //operator 3 unmodulated | |
939 context->operators[channel*4+1].mod_src[0] = NULL; | |
940 context->operators[channel*4+1].mod_src[1] = NULL; | |
941 | |
942 //operator 2 modulated by operator 1 | |
943 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; | |
944 | |
945 //operator 4 modulated by operator 2+3 | |
946 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+2].output; | |
947 context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; | |
948 break; | |
949 case 4: | |
950 //operator 3 unmodulated | |
951 context->operators[channel*4+1].mod_src[0] = NULL; | |
952 context->operators[channel*4+1].mod_src[1] = NULL; | |
953 | |
954 //operator 2 modulated by operator 1 | |
955 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; | |
956 | |
957 //operator 4 modulated by operator 3 | |
958 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; | |
959 context->operators[channel*4+3].mod_src[1] = NULL; | |
960 break; | |
961 case 5: | |
962 //operator 3 modulated by operator 1 | |
963 context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; | |
964 context->operators[channel*4+1].mod_src[1] = NULL; | |
965 | |
966 //operator 2 modulated by operator 1 | |
967 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; | |
968 | |
969 //operator 4 modulated by operator 1 | |
970 context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; | |
971 context->operators[channel*4+3].mod_src[1] = NULL; | |
972 break; | |
973 case 6: | |
974 //operator 3 unmodulated | |
975 context->operators[channel*4+1].mod_src[0] = NULL; | |
976 context->operators[channel*4+1].mod_src[1] = NULL; | |
977 | |
978 //operator 2 modulated by operator 1 | |
979 context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; | |
980 | |
981 //operator 4 unmodulated | |
982 context->operators[channel*4+3].mod_src[0] = NULL; | |
983 context->operators[channel*4+3].mod_src[1] = NULL; | |
984 break; | |
985 case 7: | |
986 //everything is an output so no modulation (except for op 1 feedback) | |
987 context->operators[channel*4+1].mod_src[0] = NULL; | |
988 context->operators[channel*4+1].mod_src[1] = NULL; | |
989 | |
990 context->operators[channel*4+2].mod_src[0] = NULL; | |
991 | |
992 context->operators[channel*4+3].mod_src[0] = NULL; | |
993 context->operators[channel*4+3].mod_src[1] = NULL; | |
994 break; | |
995 } | |
972 context->channels[channel].feedback = value >> 3 & 0x7; | 996 context->channels[channel].feedback = value >> 3 & 0x7; |
973 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); | 997 //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); |
974 break; | 998 break; |
975 case REG_LR_AMS_PMS: | 999 case REG_LR_AMS_PMS: |
976 context->channels[channel].pms = (value & 0x7) * 32; | 1000 context->channels[channel].pms = (value & 0x7) * 32; |