comparison ym2612.c @ 1648:b7ecd0d6a77b mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Tue, 25 Dec 2018 11:12:26 -0800
parents 6ce36c3f250b
children 4637ab86be8c
comparison
equal deleted inserted replaced
1509:36732f5c2281 1648:b7ecd0d6a77b
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
161 context->operators[i].envelope = MAX_ENVELOPE; 159 context->operators[i].envelope = MAX_ENVELOPE;
162 context->operators[i].env_phase = PHASE_RELEASE; 160 context->operators[i].env_phase = PHASE_RELEASE;
163 } 161 }
164 } 162 }
165 163
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) 164 void ym_init(ym2612_context * context, uint32_t master_clock, uint32_t clock_div, uint32_t options)
167 { 165 {
168 static uint8_t registered_finalize; 166 static uint8_t registered_finalize;
169 dfopen(debug_file, "ym_debug.txt", "w"); 167 dfopen(debug_file, "ym_debug.txt", "w");
170 memset(context, 0, sizeof(*context)); 168 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; 169 context->clock_inc = clock_div * 6;
175 ym_adjust_master_clock(context, master_clock); 170 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 171
184 //some games seem to expect that the LR flags start out as 1 172 //some games seem to expect that the LR flags start out as 1
185 for (int i = 0; i < NUM_CHANNELS; i++) { 173 for (int i = 0; i < NUM_CHANNELS; i++) {
186 if (options & YM_OPT_WAVE_LOG) { 174 if (options & YM_OPT_WAVE_LOG) {
187 char fname[64]; 175 char fname[64];
189 FILE * f = context->channels[i].logfile = fopen(fname, "wb"); 177 FILE * f = context->channels[i].logfile = fopen(fname, "wb");
190 if (!f) { 178 if (!f) {
191 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname); 179 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname);
192 continue; 180 continue;
193 } 181 }
194 if (!wave_init(f, sample_rate, 16, 1)) { 182 if (!wave_init(f, master_clock / (context->clock_inc * NUM_OPERATORS), 16, 1)) {
195 fclose(f); 183 fclose(f);
196 context->channels[i].logfile = NULL; 184 context->channels[i].logfile = NULL;
197 } 185 }
198 } 186 }
199 } 187 }
264 ym_reset(context); 252 ym_reset(context);
265 } 253 }
266 254
267 void ym_free(ym2612_context *context) 255 void ym_free(ym2612_context *context)
268 { 256 {
257 render_free_source(context->audio);
269 if (context == log_context) { 258 if (context == log_context) {
270 ym_finalize_log(); 259 ym_finalize_log();
271 } 260 }
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); 261 free(context);
277 } 262 }
278 263
279 #define YM_VOLUME_MULTIPLIER 2 264 #define YM_VOLUME_MULTIPLIER 2
280 #define YM_VOLUME_DIVIDER 3 265 #define YM_VOLUME_DIVIDER 3
605 } 590 }
606 context->current_op++; 591 context->current_op++;
607 if (context->current_op == NUM_OPERATORS) { 592 if (context->current_op == NUM_OPERATORS) {
608 context->current_op = 0; 593 context->current_op = 0;
609 594
610 context->buffer_fraction += context->buffer_inc;
611 int16_t left = 0, right = 0; 595 int16_t left = 0, right = 0;
612 for (int i = 0; i < NUM_CHANNELS; i++) { 596 for (int i = 0; i < NUM_CHANNELS; i++) {
613 int16_t value = context->channels[i].output; 597 int16_t value = context->channels[i].output;
614 if (value > 0x1FE0) { 598 if (value > 0x1FE0) {
615 value = 0x1FE0; 599 value = 0x1FE0;
619 value &= 0x3FE0; 603 value &= 0x3FE0;
620 if (value & 0x2000) { 604 if (value & 0x2000) {
621 value |= 0xC000; 605 value |= 0xC000;
622 } 606 }
623 } 607 }
624 if (context->channels[i].logfile && context->buffer_fraction > BUFFER_INC_RES) { 608 if (context->channels[i].logfile) {
625 fwrite(&value, sizeof(value), 1, context->channels[i].logfile); 609 fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
626 } 610 }
627 if (context->channels[i].lr & 0x80) { 611 if (context->channels[i].lr & 0x80) {
628 left += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; 612 left += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER;
629 } 613 }
630 if (context->channels[i].lr & 0x40) { 614 if (context->channels[i].lr & 0x40) {
631 right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER; 615 right += (value * YM_VOLUME_MULTIPLIER) / YM_VOLUME_DIVIDER;
632 } 616 }
633 } 617 }
634 int32_t tmp = left * context->lowpass_alpha + context->last_left * (0x10000 - context->lowpass_alpha); 618 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 } 619 }
659 620
660 } 621 }
661 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) { 622 if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) {
662 context->status &= 0x7F; 623 context->status &= 0x7F;