comparison ym2612.c @ 380:1c8d74f2ab0b

Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
author Mike Pavone <pavone@retrodev.com>
date Mon, 03 Jun 2013 21:43:38 -0700
parents 3218e2f8d685
children 7815ebbbd705
comparison
equal deleted inserted replaced
379:3218e2f8d685 380:1c8d74f2ab0b
95 } 95 }
96 96
97 FILE * debug_file = NULL; 97 FILE * debug_file = NULL;
98 uint32_t first_key_on=0; 98 uint32_t first_key_on=0;
99 99
100 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t clock_rate, uint32_t sample_limit) 100 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit)
101 { 101 {
102 dfopen(debug_file, "ym_debug.txt", "w"); 102 dfopen(debug_file, "ym_debug.txt", "w");
103 memset(context, 0, sizeof(*context)); 103 memset(context, 0, sizeof(*context));
104 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); 104 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
105 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); 105 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
106 context->buffer_inc = (double)sample_rate / (double)(clock_rate/OP_UPDATE_PERIOD); 106 context->buffer_inc = ((double)sample_rate / (double)master_clock) * clock_div * 6;
107 context->clock_inc = clock_div * 6;
107 context->sample_limit = sample_limit*2; 108 context->sample_limit = sample_limit*2;
108 context->write_cycle = CYCLE_NEVER; 109 context->write_cycle = CYCLE_NEVER;
109 for (int i = 0; i < NUM_OPERATORS; i++) { 110 for (int i = 0; i < NUM_OPERATORS; i++) {
110 context->operators[i].envelope = MAX_ENVELOPE; 111 context->operators[i].envelope = MAX_ENVELOPE;
111 context->operators[i].env_phase = PHASE_RELEASE; 112 context->operators[i].env_phase = PHASE_RELEASE;
160 161
161 void ym_run(ym2612_context * context, uint32_t to_cycle) 162 void ym_run(ym2612_context * context, uint32_t to_cycle)
162 { 163 {
163 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); 164 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
164 //TODO: Fix channel update order OR remap channels in register write 165 //TODO: Fix channel update order OR remap channels in register write
165 for (; context->current_cycle < to_cycle; context->current_cycle += 6) { 166 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) {
166 //Update timers at beginning of 144 cycle period 167 //Update timers at beginning of 144 cycle period
167 if (!context->current_op && context->timer_control & BIT_TIMERA_ENABLE) { 168 if (!context->current_op && context->timer_control & BIT_TIMERA_ENABLE) {
168 if (context->timer_a) { 169 if (context->timer_a) {
169 context->timer_a--; 170 context->timer_a--;
170 } else { 171 } else {
355 } 356 }
356 } 357 }
357 //puts("operator update done"); 358 //puts("operator update done");
358 } 359 }
359 context->current_op++; 360 context->current_op++;
361 context->buffer_fraction += context->buffer_inc;
362 if (context->buffer_fraction > 1.0) {
363 context->buffer_fraction -= 1.0;
364 context->audio_buffer[context->buffer_pos] = 0;
365 context->audio_buffer[context->buffer_pos + 1] = 0;
366 for (int i = 0; i < NUM_CHANNELS; i++) {
367 int16_t value = context->channels[i].output & 0x3FE0;
368 if (value & 0x2000) {
369 value |= 0xC000;
370 }
371 if (context->channels[i].lr & 0x80) {
372 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER;
373 }
374 if (context->channels[i].lr & 0x40) {
375 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER;
376 }
377 }
378 context->buffer_pos += 2;
379 if (context->buffer_pos == context->sample_limit) {
380 render_wait_ym(context);
381 }
382 }
360 if (context->current_op == NUM_OPERATORS) { 383 if (context->current_op == NUM_OPERATORS) {
361 context->current_op = 0; 384 context->current_op = 0;
362 context->buffer_fraction += context->buffer_inc; 385 }
363 if (context->buffer_fraction > 1.0) { 386 }
364 context->buffer_fraction -= 1.0; 387 if (context->current_cycle >= context->write_cycle + (BUSY_CYCLES * context->clock_inc / 6)) {
365 context->audio_buffer[context->buffer_pos] = 0;
366 context->audio_buffer[context->buffer_pos + 1] = 0;
367 for (int i = 0; i < NUM_CHANNELS; i++) {
368 int16_t value = context->channels[i].output & 0x3FE0;
369 if (value & 0x2000) {
370 value |= 0xC000;
371 }
372 if (context->channels[i].lr & 0x80) {
373 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER;
374 }
375 if (context->channels[i].lr & 0x40) {
376 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER;
377 }
378 }
379 context->buffer_pos += 2;
380 if (context->buffer_pos == context->sample_limit) {
381 render_wait_ym(context);
382 }
383 }
384 }
385 }
386 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) {
387 context->status &= 0x7F; 388 context->status &= 0x7F;
388 context->write_cycle = CYCLE_NEVER; 389 context->write_cycle = CYCLE_NEVER;
389 } 390 }
390 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle); 391 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
391 } 392 }