Mercurial > repos > blastem
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) { |