Mercurial > repos > blastem
comparison ym2612.c @ 370:5f215603d001
Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 02 Jun 2013 00:00:22 -0700 |
parents | fc820ab1394b |
children | 0f8a759f1ff4 |
comparison
equal
deleted
inserted
replaced
369:fc820ab1394b | 370:5f215603d001 |
---|---|
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 | |
8 //#define DO_DEBUG_PRINT | |
9 #ifdef DO_DEBUG_PRINT | |
10 #define dfprintf fprintf | |
11 #define dfopen(var, fname, mode) var=fopen(fname, mode) | |
12 #else | |
13 #define dfprintf | |
14 #define dfopen(var, fname, mode) | |
15 #endif | |
7 | 16 |
8 #define BUSY_CYCLES 17 | 17 #define BUSY_CYCLES 17 |
9 #define OP_UPDATE_PERIOD 144 | 18 #define OP_UPDATE_PERIOD 144 |
10 | 19 |
11 enum { | 20 enum { |
82 uint16_t round_fixed_point(double value, int dec_bits) | 91 uint16_t round_fixed_point(double value, int dec_bits) |
83 { | 92 { |
84 return value * (1 << dec_bits) + 0.5; | 93 return value * (1 << dec_bits) + 0.5; |
85 } | 94 } |
86 | 95 |
96 FILE * debug_file = NULL; | |
97 uint32_t first_key_on=0; | |
98 | |
87 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t clock_rate, uint32_t sample_limit) | 99 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t clock_rate, uint32_t sample_limit) |
88 { | 100 { |
101 dfopen(debug_file, "ym_debug.txt", "w"); | |
89 memset(context, 0, sizeof(*context)); | 102 memset(context, 0, sizeof(*context)); |
90 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | 103 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); |
91 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); | 104 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2); |
92 context->buffer_inc = (double)sample_rate / (double)(clock_rate/OP_UPDATE_PERIOD); | 105 context->buffer_inc = (double)sample_rate / (double)(clock_rate/OP_UPDATE_PERIOD); |
93 context->sample_limit = sample_limit*2; | 106 context->sample_limit = sample_limit*2; |
119 } | 132 } |
120 pow_table[i] = tmp; | 133 pow_table[i] = tmp; |
121 } | 134 } |
122 //populate envelope generator rate table, from small base table | 135 //populate envelope generator rate table, from small base table |
123 for (int rate = 0; rate < 64; rate++) { | 136 for (int rate = 0; rate < 64; rate++) { |
124 for (int cycle = 0; cycle < 7; cycle++) { | 137 for (int cycle = 0; cycle < 8; cycle++) { |
125 uint16_t value; | 138 uint16_t value; |
126 if (rate < 3) { | 139 if (rate < 2) { |
127 value = 0; | 140 value = 0; |
128 } else if (rate >= 60) { | 141 } else if (rate >= 60) { |
129 value = 8; | 142 value = 8; |
130 } else if (rate < 8) { | 143 } else if (rate < 8) { |
131 value = rate_table_base[((rate & 6) == 6 ? 16 : 8) + cycle]; | 144 value = rate_table_base[((rate & 6) == 6 ? 16 : 0) + cycle]; |
132 } else if (rate < 48) { | 145 } else if (rate < 48) { |
133 value = rate_table_base[(rate & 0x3) * 8 + cycle]; | 146 value = rate_table_base[(rate & 0x3) * 8 + cycle]; |
134 } else { | 147 } else { |
135 value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << (rate >> 2); | 148 value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << ((rate - 48) >> 2); |
136 } | 149 } |
137 rate_table[rate * 8 + cycle] = value; | 150 rate_table[rate * 8 + cycle] = value; |
138 } | 151 } |
139 } | 152 } |
140 } | 153 } |
141 } | 154 } |
155 | |
156 #define YM_VOLUME_DIVIDER 1 | |
142 | 157 |
143 void ym_run(ym2612_context * context, uint32_t to_cycle) | 158 void ym_run(ym2612_context * context, uint32_t to_cycle) |
144 { | 159 { |
145 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); | 160 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle); |
146 //TODO: Fix channel update order OR remap channels in register write | 161 //TODO: Fix channel update order OR remap channels in register write |
184 if (rate > 63) { | 199 if (rate > 63) { |
185 rate = 63; | 200 rate = 63; |
186 } | 201 } |
187 } | 202 } |
188 //Deal with "infinite" rates | 203 //Deal with "infinite" rates |
189 //It's possible this should be handled in key-on as well | 204 //According to Nemesis this should be handled in key-on instead |
190 if (rate == 63 && operator->env_phase < PHASE_SUSTAIN) { | 205 if (rate >= 62 && operator->env_phase == PHASE_ATTACK) { |
191 if (operator->env_phase == PHASE_ATTACK) { | 206 operator->env_phase = PHASE_DECAY; |
192 operator->env_phase = PHASE_DECAY; | 207 operator->envelope = 0; |
193 operator->envelope = operator->total_level; | |
194 } else { | |
195 operator->env_phase = PHASE_SUSTAIN; | |
196 operator->envelope = operator->sustain_level; | |
197 } | |
198 } else { | 208 } else { |
199 break; | 209 break; |
200 } | 210 } |
201 } | 211 } |
202 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; | 212 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0; |
213 if (first_key_on) { | |
214 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1)); | |
215 } | |
203 if (!(env_cyc & ((1 << cycle_shift) - 1))) { | 216 if (!(env_cyc & ((1 << cycle_shift) - 1))) { |
204 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; | 217 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7; |
205 //envelope value is 10-bits, but it will be used as a 4.8 value | 218 //envelope value is 10-bits, but it will be used as a 4.8 value |
206 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2; | 219 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2; |
207 if (operator->env_phase == PHASE_ATTACK) { | 220 if (operator->env_phase == PHASE_ATTACK) { |
208 //this can probably be optimized to a single shift rather than a multiply + shift | 221 //this can probably be optimized to a single shift rather than a multiply + shift |
222 if (first_key_on) { | |
223 dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc); | |
224 } | |
209 operator->envelope += (~operator->envelope * envelope_inc) >> 4; | 225 operator->envelope += (~operator->envelope * envelope_inc) >> 4; |
210 operator->envelope &= MAX_ENVELOPE; | 226 operator->envelope &= MAX_ENVELOPE; |
211 if (operator->envelope <= operator->total_level) { | 227 if (!operator->envelope) { |
212 operator->envelope = operator->total_level; | 228 operator->envelope = 0; |
213 operator->env_phase = PHASE_DECAY; | 229 operator->env_phase = PHASE_DECAY; |
214 } | 230 } |
215 } else { | 231 } else { |
232 if (first_key_on) { | |
233 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc, | |
234 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release")); | |
235 } | |
216 operator->envelope += envelope_inc; | 236 operator->envelope += envelope_inc; |
217 //clamp to max attenuation value | 237 //clamp to max attenuation value |
218 if (operator->envelope > MAX_ENVELOPE) { | 238 if (operator->envelope > MAX_ENVELOPE) { |
219 operator->envelope = MAX_ENVELOPE; | 239 operator->envelope = MAX_ENVELOPE; |
220 } | 240 } |
221 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { | 241 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) { |
222 operator->envelope = operator->sustain_level; | 242 //operator->envelope = operator->sustain_level; |
223 operator->env_phase = PHASE_SUSTAIN; | 243 operator->env_phase = PHASE_SUSTAIN; |
224 } | 244 } |
225 } | 245 } |
226 } | 246 } |
227 context->current_env_op++; | 247 context->current_env_op++; |
239 ym_operator * operator = context->operators + op; | 259 ym_operator * operator = context->operators + op; |
240 ym_channel * chan = context->channels + channel; | 260 ym_channel * chan = context->channels + channel; |
241 //TODO: Modulate phase by LFO if necessary | 261 //TODO: Modulate phase by LFO if necessary |
242 operator->phase_counter += operator->phase_inc; | 262 operator->phase_counter += operator->phase_inc; |
243 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; | 263 uint16_t phase = operator->phase_counter >> 10 & 0x3FF; |
264 uint16_t mod = 0; | |
244 switch (op % 4) | 265 switch (op % 4) |
245 { | 266 { |
246 case 0://Operator 1 | 267 case 0://Operator 1 |
247 //TODO: Feedback | 268 //TODO: Feedback |
248 break; | 269 break; |
250 switch(chan->algorithm) | 271 switch(chan->algorithm) |
251 { | 272 { |
252 case 0: | 273 case 0: |
253 case 2: | 274 case 2: |
254 //modulate by operator 2 | 275 //modulate by operator 2 |
255 phase += context->operators[op+1].output >> 4; | 276 mod = context->operators[op+1].output >> 4; |
256 break; | 277 break; |
257 case 1: | 278 case 1: |
258 //modulate by operator 1+2 | 279 //modulate by operator 1+2 |
259 phase += (context->operators[op-1].output + context->operators[op+1].output) >> 4; | 280 mod = (context->operators[op-1].output + context->operators[op+1].output) >> 4; |
260 break; | 281 break; |
261 case 5: | 282 case 5: |
262 //modulate by operator 1 | 283 //modulate by operator 1 |
263 phase += context->operators[op-1].output >> 4; | 284 mod = context->operators[op-1].output >> 4; |
264 } | 285 } |
265 break; | 286 break; |
266 case 2://Operator 2 | 287 case 2://Operator 2 |
267 if (chan->algorithm != 1 && chan->algorithm != 2 || chan->algorithm != 7) { | 288 if (chan->algorithm != 1 && chan->algorithm != 2 || chan->algorithm != 7) { |
268 //modulate by Operator 1 | 289 //modulate by Operator 1 |
269 phase += context->operators[op-2].output >> 4; | 290 mod = context->operators[op-2].output >> 4; |
270 } | 291 } |
271 break; | 292 break; |
272 case 3://Operator 4 | 293 case 3://Operator 4 |
273 switch(chan->algorithm) | 294 switch(chan->algorithm) |
274 { | 295 { |
275 case 0: | 296 case 0: |
276 case 1: | 297 case 1: |
277 case 4: | 298 case 4: |
278 //modulate by operator 3 | 299 //modulate by operator 3 |
279 phase += context->operators[op-2].output >> 4; | 300 mod = context->operators[op-2].output >> 4; |
280 break; | 301 break; |
281 case 2: | 302 case 2: |
282 //modulate by operator 1+3 | 303 //modulate by operator 1+3 |
283 phase += (context->operators[op-3].output + context->operators[op-2].output) >> 4; | 304 mod = (context->operators[op-3].output + context->operators[op-2].output) >> 4; |
284 break; | 305 break; |
285 case 3: | 306 case 3: |
286 //modulate by operator 2+3 | 307 //modulate by operator 2+3 |
287 phase += (context->operators[op-1].output + context->operators[op-2].output) >> 4; | 308 mod = (context->operators[op-1].output + context->operators[op-2].output) >> 4; |
288 break; | 309 break; |
289 case 5: | 310 case 5: |
290 //modulate by operator 1 | 311 //modulate by operator 1 |
291 phase += context->operators[op-3].output >> 4; | 312 mod = context->operators[op-3].output >> 4; |
292 break; | 313 break; |
293 } | 314 } |
294 break; | 315 break; |
295 } | 316 } |
296 //printf("sine_table[%X] + %X = %X, sizeof(pow_table)/sizeof(*pow_table) = %X\n", phase & 0x1FF, operator->envelope, sine_table[phase & 0x1FF] + operator->envelope, sizeof(pow_table)/ sizeof(*pow_table)); | 317 uint16_t env = operator->envelope + operator->total_level; |
297 uint16_t output = pow_table[sine_table[phase & 0x1FF] + operator->envelope]; | 318 if (env > MAX_ENVELOPE) { |
319 env = MAX_ENVELOPE; | |
320 } | |
321 if (first_key_on) { | |
322 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]); | |
323 } | |
324 phase += mod; | |
325 | |
326 uint16_t output = pow_table[sine_table[phase & 0x1FF] + env]; | |
298 if (phase & 0x200) { | 327 if (phase & 0x200) { |
299 output = -output; | 328 output = -output; |
300 } | 329 } |
301 operator->output = output; | 330 operator->output = output; |
302 //Update the channel output if we've updated all operators | 331 //Update the channel output if we've updated all operators |
310 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { | 339 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) { |
311 output += context->operators[op].output; | 340 output += context->operators[op].output; |
312 } | 341 } |
313 chan->output = output; | 342 chan->output = output; |
314 } | 343 } |
344 int16_t value = context->channels[channel].output & 0x3FE0; | |
345 if (value & 0x2000) { | |
346 value |= 0xC000; | |
347 } | |
348 if (first_key_on) { | |
349 dfprintf(debug_file, "channel %d output: %d\n", channel, value / 2); | |
350 } | |
315 } | 351 } |
316 //puts("operator update done"); | 352 //puts("operator update done"); |
317 } | 353 } |
318 context->current_op++; | 354 context->current_op++; |
319 if (context->current_op == NUM_OPERATORS) { | 355 if (context->current_op == NUM_OPERATORS) { |
322 if (context->buffer_fraction > 1.0) { | 358 if (context->buffer_fraction > 1.0) { |
323 context->buffer_fraction -= 1.0; | 359 context->buffer_fraction -= 1.0; |
324 context->audio_buffer[context->buffer_pos] = 0; | 360 context->audio_buffer[context->buffer_pos] = 0; |
325 context->audio_buffer[context->buffer_pos + 1] = 0; | 361 context->audio_buffer[context->buffer_pos + 1] = 0; |
326 for (int i = 0; i < NUM_CHANNELS; i++) { | 362 for (int i = 0; i < NUM_CHANNELS; i++) { |
327 uint16_t value = context->channels[i].output & 0x3FE0; | 363 int16_t value = context->channels[i].output & 0x3FE0; |
328 if (value & 0x2000) { | 364 if (value & 0x2000) { |
329 value |= 0xC000; | 365 value |= 0xC000; |
330 } | 366 } |
331 if (context->channels[i].lr & 0x80) { | 367 if (context->channels[i].lr & 0x80) { |
332 context->audio_buffer[context->buffer_pos] += value / 2; | 368 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER; |
333 } | 369 } |
334 if (context->channels[i].lr & 0x40) { | 370 if (context->channels[i].lr & 0x40) { |
335 context->audio_buffer[context->buffer_pos+1] += value / 2; | 371 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER; |
336 } | 372 } |
337 } | 373 } |
338 context->buffer_pos += 2; | 374 context->buffer_pos += 2; |
339 if (context->buffer_pos == context->sample_limit) { | 375 if (context->buffer_pos == context->sample_limit) { |
340 render_wait_ym(context); | 376 render_wait_ym(context); |
440 void ym_data_write(ym2612_context * context, uint8_t value) | 476 void ym_data_write(ym2612_context * context, uint8_t value) |
441 { | 477 { |
442 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) { | 478 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) { |
443 return; | 479 return; |
444 } | 480 } |
445 //printf("write to reg %X in part %d\n", context->selected_reg, context->selected_part+1); | 481 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1); |
446 if (context->selected_reg < 0x30) { | 482 if (context->selected_reg < 0x30) { |
447 //Shared regs | 483 //Shared regs |
448 switch (context->selected_reg) | 484 switch (context->selected_reg) |
449 { | 485 { |
450 //TODO: Test reg and LFO | 486 //TODO: Test reg and LFO |
465 case REG_KEY_ONOFF: { | 501 case REG_KEY_ONOFF: { |
466 uint8_t channel = value & 0x7; | 502 uint8_t channel = value & 0x7; |
467 if (channel < NUM_CHANNELS) { | 503 if (channel < NUM_CHANNELS) { |
468 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { | 504 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) { |
469 if (value & bit) { | 505 if (value & bit) { |
506 first_key_on = 1; | |
470 //printf("Key On for operator %d in channel %d\n", op, channel); | 507 //printf("Key On for operator %d in channel %d\n", op, channel); |
471 context->operators[op].phase_counter = 0; | 508 context->operators[op].phase_counter = 0; |
472 context->operators[op].env_phase = PHASE_ATTACK; | 509 context->operators[op].env_phase = PHASE_ATTACK; |
473 context->operators[op].envelope = MAX_ENVELOPE; | 510 context->operators[op].envelope = MAX_ENVELOPE; |
474 } else { | 511 } else { |
493 } else if (context->selected_reg < 0xA0) { | 530 } else if (context->selected_reg < 0xA0) { |
494 //part | 531 //part |
495 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0; | 532 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0; |
496 //channel in part | 533 //channel in part |
497 if ((context->selected_reg & 0x3) != 0x3) { | 534 if ((context->selected_reg & 0x3) != 0x3) { |
498 op += 4 * (context->selected_reg & 0x3); | 535 op += 4 * (context->selected_reg & 0x3) + ((context->selected_reg & 0xC) / 4); |
499 //operator in channel | |
500 switch (context->selected_reg & 0xC) | |
501 { | |
502 case 0: | |
503 break; | |
504 case 4: | |
505 op += 2; | |
506 break; | |
507 case 8: | |
508 op += 1; | |
509 break; | |
510 case 0xC: | |
511 op += 3; | |
512 break; | |
513 } | |
514 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4); | 536 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4); |
515 ym_operator * operator = context->operators + op; | 537 ym_operator * operator = context->operators + op; |
516 switch (context->selected_reg & 0xF0) | 538 switch (context->selected_reg & 0xF0) |
517 { | 539 { |
518 case REG_DETUNE_MULT: | 540 case REG_DETUNE_MULT: |