diff options
Diffstat (limited to 'apps/codecs/libgme/nes_oscs.c')
-rw-r--r-- | apps/codecs/libgme/nes_oscs.c | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/apps/codecs/libgme/nes_oscs.c b/apps/codecs/libgme/nes_oscs.c index 4402b60a61..f97ce2176d 100644 --- a/apps/codecs/libgme/nes_oscs.c +++ b/apps/codecs/libgme/nes_oscs.c | |||
@@ -90,7 +90,7 @@ static inline nes_time_t Square_maintain_phase( struct Nes_Square* this, nes_tim | |||
90 | { | 90 | { |
91 | int count = (remain + timer_period - 1) / timer_period; | 91 | int count = (remain + timer_period - 1) / timer_period; |
92 | this->phase = (this->phase + count) & (square_phase_range - 1); | 92 | this->phase = (this->phase + count) & (square_phase_range - 1); |
93 | time += (blargg_long) count * timer_period; | 93 | time += count * timer_period; |
94 | } | 94 | } |
95 | return time; | 95 | return time; |
96 | } | 96 | } |
@@ -107,8 +107,6 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time ) | |||
107 | return; | 107 | return; |
108 | } | 108 | } |
109 | 109 | ||
110 | Blip_set_modified( osc->output ); | ||
111 | |||
112 | int offset = period >> (osc->regs [1] & shift_mask); | 110 | int offset = period >> (osc->regs [1] & shift_mask); |
113 | if ( osc->regs [1] & negate_flag ) | 111 | if ( osc->regs [1] & negate_flag ) |
114 | offset = 0; | 112 | offset = 0; |
@@ -117,6 +115,7 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time ) | |||
117 | if ( volume == 0 || period < 8 || (period + offset) >= 0x800 ) | 115 | if ( volume == 0 || period < 8 || (period + offset) >= 0x800 ) |
118 | { | 116 | { |
119 | if ( osc->last_amp ) { | 117 | if ( osc->last_amp ) { |
118 | Blip_set_modified( osc->output ); | ||
120 | Synth_offset( this->synth, time, -osc->last_amp, osc->output ); | 119 | Synth_offset( this->synth, time, -osc->last_amp, osc->output ); |
121 | osc->last_amp = 0; | 120 | osc->last_amp = 0; |
122 | } | 121 | } |
@@ -137,6 +136,7 @@ void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time ) | |||
137 | if ( this->phase < duty ) | 136 | if ( this->phase < duty ) |
138 | amp ^= volume; | 137 | amp ^= volume; |
139 | 138 | ||
139 | Blip_set_modified( osc->output ); | ||
140 | { | 140 | { |
141 | int delta = Osc_update_amp( osc, amp ); | 141 | int delta = Osc_update_amp( osc, amp ); |
142 | if ( delta ) | 142 | if ( delta ) |
@@ -201,7 +201,7 @@ static inline nes_time_t Triangle_maintain_phase( struct Nes_Triangle* this, nes | |||
201 | int count = (remain + timer_period - 1) / timer_period; | 201 | int count = (remain + timer_period - 1) / timer_period; |
202 | this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1); | 202 | this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1); |
203 | this->phase++; | 203 | this->phase++; |
204 | time += (blargg_long) count * timer_period; | 204 | time += count * timer_period; |
205 | } | 205 | } |
206 | return time; | 206 | return time; |
207 | } | 207 | } |
@@ -219,14 +219,15 @@ void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_ti | |||
219 | return; | 219 | return; |
220 | } | 220 | } |
221 | 221 | ||
222 | Blip_set_modified( osc->output ); | ||
223 | |||
224 | // to do: track phase when period < 3 | 222 | // to do: track phase when period < 3 |
225 | // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks. | 223 | // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks. |
226 | 224 | ||
227 | int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) ); | 225 | int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) ); |
228 | if ( delta ) | 226 | if ( delta ) |
227 | { | ||
228 | Blip_set_modified( osc->output ); | ||
229 | Synth_offset( &this->synth, time, delta, osc->output ); | 229 | Synth_offset( &this->synth, time, delta, osc->output ); |
230 | } | ||
230 | 231 | ||
231 | time += osc->delay; | 232 | time += osc->delay; |
232 | if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 ) | 233 | if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 ) |
@@ -243,13 +244,15 @@ void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_ti | |||
243 | phase -= Triangle_phase_range; | 244 | phase -= Triangle_phase_range; |
244 | volume = -volume; | 245 | volume = -volume; |
245 | } | 246 | } |
247 | Blip_set_modified( osc->output ); | ||
246 | 248 | ||
247 | do { | 249 | do { |
248 | if ( --phase == 0 ) { | 250 | if ( --phase == 0 ) { |
249 | phase = Triangle_phase_range; | 251 | phase = Triangle_phase_range; |
250 | volume = -volume; | 252 | volume = -volume; |
251 | } | 253 | } |
252 | else { | 254 | else |
255 | { | ||
253 | Synth_offset_inline( &this->synth, time, volume, output ); | 256 | Synth_offset_inline( &this->synth, time, volume, output ); |
254 | } | 257 | } |
255 | 258 | ||
@@ -340,18 +343,27 @@ static inline void Dmc_reload_sample( struct Nes_Dmc* this ) | |||
340 | this->osc.length_counter = this->osc.regs [3] * 0x10 + 1; | 343 | this->osc.length_counter = this->osc.regs [3] * 0x10 + 1; |
341 | } | 344 | } |
342 | 345 | ||
343 | static byte const dac_table [128] = | 346 | static int const dmc_table [128] = |
344 | { | 347 | { |
345 | 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14, | 348 | 0, 24, 48, 71, 94, 118, 141, 163, 186, 209, 231, 253, 275, 297, 319, 340, |
346 | 15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27, | 349 | 361, 383, 404, 425, 445, 466, 486, 507, 527, 547, 567, 587, 606, 626, 645, 664, |
347 | 27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38, | 350 | 683, 702, 721, 740, 758, 777, 795, 813, 832, 850, 867, 885, 903, 920, 938, 955, |
348 | 39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49, | 351 | 972, 989,1006,1023,1040,1056,1073,1089,1105,1122,1138,1154,1170,1185,1201,1217, |
349 | 50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59, | 352 | 1232,1248,1263,1278,1293,1308,1323,1338,1353,1368,1382,1397,1411,1425,1440,1454, |
350 | 59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67, | 353 | 1468,1482,1496,1510,1523,1537,1551,1564,1578,1591,1604,1618,1631,1644,1657,1670, |
351 | 68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75, | 354 | 1683,1695,1708,1721,1733,1746,1758,1771,1783,1795,1807,1819,1831,1843,1855,1867, |
352 | 76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83, | 355 | 1879,1890,1902,1914,1925,1937,1948,1959,1971,1982,1993,2004,2015,2026,2037,2048, |
353 | }; | 356 | }; |
354 | 357 | ||
358 | static inline int update_amp_nonlinear( struct Nes_Dmc* this, int in ) | ||
359 | { | ||
360 | if ( !this->nonlinear ) | ||
361 | in = dmc_table [in]; | ||
362 | int delta = in - this->osc.last_amp; | ||
363 | this->osc.last_amp = in; | ||
364 | return delta; | ||
365 | } | ||
366 | |||
355 | void Dmc_write_register( struct Nes_Dmc* this, int addr, int data ) | 367 | void Dmc_write_register( struct Nes_Dmc* this, int addr, int data ) |
356 | { | 368 | { |
357 | if ( addr == 0 ) | 369 | if ( addr == 0 ) |
@@ -363,14 +375,7 @@ void Dmc_write_register( struct Nes_Dmc* this, int addr, int data ) | |||
363 | } | 375 | } |
364 | else if ( addr == 1 ) | 376 | else if ( addr == 1 ) |
365 | { | 377 | { |
366 | int old_dac = this->dac; | ||
367 | this->dac = data & 0x7F; | 378 | this->dac = data & 0x7F; |
368 | |||
369 | // adjust last_amp so that "pop" amplitude will be properly non-linear | ||
370 | // with respect to change in dac | ||
371 | int faked_nonlinear = this->dac - (dac_table [this->dac] - dac_table [old_dac]); | ||
372 | if ( !this->nonlinear ) | ||
373 | this->osc.last_amp = faked_nonlinear; | ||
374 | } | 379 | } |
375 | } | 380 | } |
376 | 381 | ||
@@ -407,16 +412,15 @@ void Dmc_fill_buffer( struct Nes_Dmc* this ) | |||
407 | void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) | 412 | void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) |
408 | { | 413 | { |
409 | struct Nes_Osc* osc = &this->osc; | 414 | struct Nes_Osc* osc = &this->osc; |
410 | int delta = Osc_update_amp( osc, this->dac ); | 415 | int delta = update_amp_nonlinear( this, this->dac ); |
411 | if ( !osc->output ) | 416 | if ( !osc->output ) |
412 | { | 417 | { |
413 | this->silence = true; | 418 | this->silence = true; |
414 | } | 419 | } |
415 | else | 420 | else if ( delta ) |
416 | { | 421 | { |
417 | Blip_set_modified( osc->output ); | 422 | Blip_set_modified( osc->output ); |
418 | if ( delta ) | 423 | Synth_offset( &this->synth, time, delta, osc->output ); |
419 | Synth_offset( &this->synth, time, delta, osc->output ); | ||
420 | } | 424 | } |
421 | 425 | ||
422 | time += osc->delay; | 426 | time += osc->delay; |
@@ -435,6 +439,8 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) | |||
435 | const int period = this->period; | 439 | const int period = this->period; |
436 | int bits = this->bits; | 440 | int bits = this->bits; |
437 | int dac = this->dac; | 441 | int dac = this->dac; |
442 | if ( output ) | ||
443 | Blip_set_modified( output ); | ||
438 | 444 | ||
439 | do | 445 | do |
440 | { | 446 | { |
@@ -444,7 +450,7 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) | |||
444 | bits >>= 1; | 450 | bits >>= 1; |
445 | if ( (unsigned) (dac + step) <= 0x7F ) { | 451 | if ( (unsigned) (dac + step) <= 0x7F ) { |
446 | dac += step; | 452 | dac += step; |
447 | Synth_offset_inline( &this->synth, time, step, output ); | 453 | Synth_offset_inline( &this->synth, time, update_amp_nonlinear( this, dac ), output ); |
448 | } | 454 | } |
449 | } | 455 | } |
450 | 456 | ||
@@ -456,7 +462,8 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) | |||
456 | if ( !this->buf_full ) { | 462 | if ( !this->buf_full ) { |
457 | this->silence = true; | 463 | this->silence = true; |
458 | } | 464 | } |
459 | else { | 465 | else |
466 | { | ||
460 | this->silence = false; | 467 | this->silence = false; |
461 | bits = this->buf; | 468 | bits = this->buf; |
462 | this->buf_full = false; | 469 | this->buf_full = false; |
@@ -469,7 +476,7 @@ void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time ) | |||
469 | while ( time < end_time ); | 476 | while ( time < end_time ); |
470 | 477 | ||
471 | this->dac = dac; | 478 | this->dac = dac; |
472 | osc->last_amp = dac; | 479 | //osc->last_amp = dac; |
473 | this->bits = bits; | 480 | this->bits = bits; |
474 | } | 481 | } |
475 | this->bits_remain = bits_remain; | 482 | this->bits_remain = bits_remain; |
@@ -519,14 +526,15 @@ void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time ) | |||
519 | return; | 526 | return; |
520 | } | 527 | } |
521 | 528 | ||
522 | Blip_set_modified( osc->output ); | ||
523 | |||
524 | const int volume = Noise_volume( this ); | 529 | const int volume = Noise_volume( this ); |
525 | int amp = (this->noise & 1) ? volume : 0; | 530 | int amp = (this->noise & 1) ? volume : 0; |
526 | { | 531 | { |
527 | int delta = Osc_update_amp( osc, amp ); | 532 | int delta = Osc_update_amp( osc, amp ); |
528 | if ( delta ) | 533 | if ( delta ) |
534 | { | ||
535 | Blip_set_modified( osc->output ); | ||
529 | Synth_offset( &this->synth, time, delta, osc->output ); | 536 | Synth_offset( &this->synth, time, delta, osc->output ); |
537 | } | ||
530 | } | 538 | } |
531 | 539 | ||
532 | time += osc->delay; | 540 | time += osc->delay; |
@@ -557,6 +565,7 @@ void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time ) | |||
557 | int noise = this->noise; | 565 | int noise = this->noise; |
558 | int delta = amp * 2 - volume; | 566 | int delta = amp * 2 - volume; |
559 | const int tap = (osc->regs [2] & mode_flag ? 8 : 13); | 567 | const int tap = (osc->regs [2] & mode_flag ? 8 : 13); |
568 | Blip_set_modified( osc->output ); | ||
560 | 569 | ||
561 | do { | 570 | do { |
562 | int feedback = (noise << tap) ^ (noise << 14); | 571 | int feedback = (noise << tap) ^ (noise << 14); |