comparison ym2612.c @ 407:c3abc4ada43d

Add support for logging YM2612 channels to WAVE files
author Mike Pavone <pavone@retrodev.com>
date Sun, 16 Jun 2013 17:57:57 -0700
parents b1bc1947d949
children baf4688901f2
comparison
equal deleted inserted replaced
406:b1bc1947d949 407:c3abc4ada43d
2 #include <math.h> 2 #include <math.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 #include <stdlib.h> 4 #include <stdlib.h>
5 #include "ym2612.h" 5 #include "ym2612.h"
6 #include "render.h" 6 #include "render.h"
7 #include "wave.h"
7 8
8 //#define DO_DEBUG_PRINT 9 //#define DO_DEBUG_PRINT
9 #ifdef DO_DEBUG_PRINT 10 #ifdef DO_DEBUG_PRINT
10 #define dfprintf fprintf 11 #define dfprintf fprintf
11 #define dfopen(var, fname, mode) var=fopen(fname, mode) 12 #define dfopen(var, fname, mode) var=fopen(fname, mode)
95 } 96 }
96 97
97 FILE * debug_file = NULL; 98 FILE * debug_file = NULL;
98 uint32_t first_key_on=0; 99 uint32_t first_key_on=0;
99 100
100 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit) 101 ym2612_context * log_context = NULL;
102
103 void ym_finalize_log()
104 {
105 for (int i = 0; i < NUM_CHANNELS; i++) {
106 if (log_context->channels[i].logfile) {
107 wave_finalize(log_context->channels[i].logfile);
108 }
109 }
110 }
111
112 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)
101 { 113 {
102 dfopen(debug_file, "ym_debug.txt", "w"); 114 dfopen(debug_file, "ym_debug.txt", "w");
103 memset(context, 0, sizeof(*context)); 115 memset(context, 0, sizeof(*context));
104 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); 116 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
105 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); 117 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
112 context->operators[i].env_phase = PHASE_RELEASE; 124 context->operators[i].env_phase = PHASE_RELEASE;
113 } 125 }
114 //some games seem to expect that the LR flags start out as 1 126 //some games seem to expect that the LR flags start out as 1
115 for (int i = 0; i < NUM_CHANNELS; i++) { 127 for (int i = 0; i < NUM_CHANNELS; i++) {
116 context->channels[i].lr = 0xC0; 128 context->channels[i].lr = 0xC0;
129 if (options & YM_OPT_WAVE_LOG) {
130 char fname[64];
131 sprintf(fname, "ym_channel_%d.wav", i);
132 FILE * f = context->channels[i].logfile = fopen(fname, "wb");
133 if (!f) {
134 fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname);
135 continue;
136 }
137 if (!wave_init(f, sample_rate, 16, 1)) {
138 fclose(f);
139 context->channels[i].logfile = NULL;
140 }
141 }
142 }
143 if (options & YM_OPT_WAVE_LOG) {
144 log_context = context;
145 atexit(ym_finalize_log);
117 } 146 }
118 if (!did_tbl_init) { 147 if (!did_tbl_init) {
119 //populate sine table 148 //populate sine table
120 for (int32_t i = 0; i < 512; i++) { 149 for (int32_t i = 0; i < 512; i++) {
121 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 ); 150 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 );
369 context->audio_buffer[context->buffer_pos + 1] = 0; 398 context->audio_buffer[context->buffer_pos + 1] = 0;
370 for (int i = 0; i < NUM_CHANNELS; i++) { 399 for (int i = 0; i < NUM_CHANNELS; i++) {
371 int16_t value = context->channels[i].output & 0x3FE0; 400 int16_t value = context->channels[i].output & 0x3FE0;
372 if (value & 0x2000) { 401 if (value & 0x2000) {
373 value |= 0xC000; 402 value |= 0xC000;
403 }
404 if (context->channels[i].logfile) {
405 fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
374 } 406 }
375 if (context->channels[i].lr & 0x80) { 407 if (context->channels[i].lr & 0x80) {
376 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER; 408 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER;
377 } 409 }
378 if (context->channels[i].lr & 0x40) { 410 if (context->channels[i].lr & 0x40) {