Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/ym2612.c Tue Dec 19 00:49:13 2017 -0800 +++ b/ym2612.c Sat Jan 05 00:58:08 2019 -0800 @@ -116,12 +116,10 @@ } log_context = NULL; } -#define BUFFER_INC_RES 0x40000000UL void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock) { - uint64_t old_inc = context->buffer_inc; - context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc * NUM_OPERATORS; + render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS); } #ifdef __ANDROID__ @@ -137,6 +135,11 @@ memset(context->part1_regs, 0, sizeof(context->part1_regs)); memset(context->part2_regs, 0, sizeof(context->part2_regs)); memset(context->operators, 0, sizeof(context->operators)); + FILE* savedlogs[NUM_CHANNELS]; + for (int i = 0; i < NUM_CHANNELS; i++) + { + savedlogs[i] = context->channels[i].logfile; + } memset(context->channels, 0, sizeof(context->channels)); memset(context->ch3_supp, 0, sizeof(context->ch3_supp)); context->selected_reg = 0; @@ -155,6 +158,7 @@ //some games seem to expect that the LR flags start out as 1 for (int i = 0; i < NUM_CHANNELS; i++) { context->channels[i].lr = 0xC0; + context->channels[i].logfile = savedlogs[i]; } context->write_cycle = CYCLE_NEVER; for (int i = 0; i < NUM_OPERATORS; i++) { @@ -163,23 +167,13 @@ } } -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) +void ym_init(ym2612_context * context, uint32_t master_clock, uint32_t clock_div, uint32_t options) { static uint8_t registered_finalize; dfopen(debug_file, "ym_debug.txt", "w"); memset(context, 0, sizeof(*context)); - context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); - context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); - context->sample_rate = sample_rate; context->clock_inc = clock_div * 6; - ym_adjust_master_clock(context, master_clock); - - double rc = (1.0 / (double)lowpass_cutoff) / (2.0 * M_PI); - double dt = 1.0 / ((double)master_clock / (double)(context->clock_inc * NUM_OPERATORS)); - double alpha = dt / (dt + rc); - context->lowpass_alpha = (int32_t)(((double)0x10000) * alpha); - - context->sample_limit = sample_limit*2; + context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2); //some games seem to expect that the LR flags start out as 1 for (int i = 0; i < NUM_CHANNELS; i++) { @@ -191,7 +185,7 @@ fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname); continue; } - if (!wave_init(f, sample_rate, 16, 1)) { + if (!wave_init(f, master_clock / (context->clock_inc * NUM_OPERATORS), 16, 1)) { fclose(f); context->channels[i].logfile = NULL; } @@ -266,13 +260,10 @@ void ym_free(ym2612_context *context) { + render_free_source(context->audio); if (context == log_context) { ym_finalize_log(); } - free(context->audio_buffer); - //TODO: Figure out how to make this 100% safe - //audio thread could still be using this - free(context->back_buffer); free(context); } @@ -475,59 +466,19 @@ uint16_t phase = operator->phase_counter >> 10 & 0x3FF; operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op); int16_t mod = 0; - switch (op % 4) - { - case 0://Operator 1 + if (op & 3) { + if (operator->mod_src[0]) { + mod = *operator->mod_src[0]; + if (operator->mod_src[1]) { + mod += * + operator->mod_src[1]; + } + mod >>= YM_MOD_SHIFT; + } + } else { if (chan->feedback) { mod = (chan->op1_old + operator->output) >> (10-chan->feedback); } - break; - case 1://Operator 3 - switch(chan->algorithm) - { - case 0: - case 2: - //modulate by operator 2 - mod = context->operators[op+1].output >> YM_MOD_SHIFT; - break; - case 1: - //modulate by operator 1+2 - mod = (context->operators[op-1].output + context->operators[op+1].output) >> YM_MOD_SHIFT; - break; - case 5: - //modulate by operator 1 - mod = context->operators[op-1].output >> YM_MOD_SHIFT; - } - break; - case 2://Operator 2 - if (chan->algorithm != 1 && chan->algorithm != 2 && chan->algorithm != 7) { - //modulate by Operator 1 - mod = context->operators[op-2].output >> YM_MOD_SHIFT; - } - break; - case 3://Operator 4 - switch(chan->algorithm) - { - case 0: - case 1: - case 4: - //modulate by operator 3 - mod = context->operators[op-2].output >> YM_MOD_SHIFT; - break; - case 2: - //modulate by operator 1+3 - mod = (context->operators[op-3].output + context->operators[op-2].output) >> YM_MOD_SHIFT; - break; - case 3: - //modulate by operator 2+3 - mod = (context->operators[op-1].output + context->operators[op-2].output) >> YM_MOD_SHIFT; - break; - case 5: - //modulate by operator 1 - mod = context->operators[op-3].output >> YM_MOD_SHIFT; - break; - } - break; } uint16_t env = operator->envelope; if (operator->ssg) { @@ -607,7 +558,6 @@ if (context->current_op == NUM_OPERATORS) { context->current_op = 0; - context->buffer_fraction += context->buffer_inc; int16_t left = 0, right = 0; for (int i = 0; i < NUM_CHANNELS; i++) { int16_t value = context->channels[i].output; @@ -621,7 +571,7 @@ value |= 0xC000; } } - if (context->channels[i].logfile && context->buffer_fraction > BUFFER_INC_RES) { + if (context->channels[i].logfile) { fwrite(&value, sizeof(value), 1, context->channels[i].logfile); } if (context->channels[i].lr & 0x80) { @@ -631,30 +581,7 @@ right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; } } - int32_t tmp = left * context->lowpass_alpha + context->last_left * (0x10000 - context->lowpass_alpha); - left = tmp >> 16; - tmp = right * context->lowpass_alpha + context->last_right * (0x10000 - context->lowpass_alpha); - right = tmp >> 16; - while (context->buffer_fraction > BUFFER_INC_RES) { - context->buffer_fraction -= BUFFER_INC_RES; - - int64_t tmp = context->last_left * ((context->buffer_fraction << 16) / context->buffer_inc); - tmp += left * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc)); - context->audio_buffer[context->buffer_pos] = tmp >> 16; - - tmp = context->last_right * ((context->buffer_fraction << 16) / context->buffer_inc); - tmp += right * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc)); - context->audio_buffer[context->buffer_pos+1] = tmp >> 16; - - context->buffer_pos += 2; - if (context->buffer_pos == context->sample_limit) { - if (!headless) { - render_wait_ym(context); - } - } - } - context->last_left = left; - context->last_right = right; + render_put_stereo_sample(context->audio, left, right); } } @@ -969,6 +896,103 @@ break; case REG_ALG_FEEDBACK: context->channels[channel].algorithm = value & 0x7; + switch (context->channels[channel].algorithm) + { + case 0: + //operator 3 modulated by operator 2 + context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 modulated by operator 1 + context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; + + //operator 4 modulated by operator 3 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + case 1: + //operator 3 modulated by operator 1+2 + context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; + context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output; + + //operator 2 unmodulated + context->operators[channel*4+2].mod_src[0] = NULL; + + //operator 4 modulated by operator 3 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + case 2: + //operator 3 modulated by operator 2 + context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 unmodulated + context->operators[channel*4+2].mod_src[0] = NULL; + + //operator 4 modulated by operator 1+3 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; + context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; + break; + case 3: + //operator 3 unmodulated + context->operators[channel*4+1].mod_src[0] = NULL; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 modulated by operator 1 + context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; + + //operator 4 modulated by operator 2+3 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+2].output; + context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output; + break; + case 4: + //operator 3 unmodulated + context->operators[channel*4+1].mod_src[0] = NULL; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 modulated by operator 1 + context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; + + //operator 4 modulated by operator 3 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + case 5: + //operator 3 modulated by operator 1 + context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 modulated by operator 1 + context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; + + //operator 4 modulated by operator 1 + context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + case 6: + //operator 3 unmodulated + context->operators[channel*4+1].mod_src[0] = NULL; + context->operators[channel*4+1].mod_src[1] = NULL; + + //operator 2 modulated by operator 1 + context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output; + + //operator 4 unmodulated + context->operators[channel*4+3].mod_src[0] = NULL; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + case 7: + //everything is an output so no modulation (except for op 1 feedback) + context->operators[channel*4+1].mod_src[0] = NULL; + context->operators[channel*4+1].mod_src[1] = NULL; + + context->operators[channel*4+2].mod_src[0] = NULL; + + context->operators[channel*4+3].mod_src[0] = NULL; + context->operators[channel*4+3].mod_src[1] = NULL; + break; + } context->channels[channel].feedback = value >> 3 & 0x7; //printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel); break;