Mercurial > repos > blastem
comparison psg.c @ 483:3e1573fa22cf
Implement turbo/slow motion feature that overclocks or underclocks the entire system at the push of a button
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 01 Oct 2013 23:51:16 -0700 |
parents | 140af5509ce7 |
children | b7b7a1cab44a |
comparison
equal
deleted
inserted
replaced
482:4b24260125f3 | 483:3e1573fa22cf |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Michael Pavone | 2 Copyright 2013 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "psg.h" | 6 #include "psg.h" |
7 #include "render.h" | 7 #include "render.h" |
8 #include <string.h> | 8 #include <string.h> |
11 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame) | 11 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame) |
12 { | 12 { |
13 memset(context, 0, sizeof(*context)); | 13 memset(context, 0, sizeof(*context)); |
14 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); | 14 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); |
15 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); | 15 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); |
16 double clock_rate = (double)master_clock / (double)clock_div; | |
17 context->buffer_inc = ((double)sample_rate / (double)master_clock) * clock_div; | |
18 context->clock_inc = clock_div; | 16 context->clock_inc = clock_div; |
17 context->sample_rate = sample_rate; | |
19 context->samples_frame = samples_frame; | 18 context->samples_frame = samples_frame; |
19 psg_adjust_master_clock(context, master_clock); | |
20 for (int i = 0; i < 4; i++) { | 20 for (int i = 0; i < 4; i++) { |
21 context->volume[i] = 0xF; | 21 context->volume[i] = 0xF; |
22 } | 22 } |
23 } | |
24 | |
25 #define BUFFER_INC_RES 1000000000UL | |
26 | |
27 void psg_adjust_master_clock(psg_context * context, uint32_t master_clock) | |
28 { | |
29 uint64_t old_inc = context->buffer_inc; | |
30 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc; | |
23 } | 31 } |
24 | 32 |
25 void psg_write(psg_context * context, uint8_t value) | 33 void psg_write(psg_context * context, uint8_t value) |
26 { | 34 { |
27 if (value & 0x80) { | 35 if (value & 0x80) { |
68 #define PSG_VOL_DIV 6 | 76 #define PSG_VOL_DIV 6 |
69 | 77 |
70 //table shamelessly swiped from PSG doc from smspower.org | 78 //table shamelessly swiped from PSG doc from smspower.org |
71 int16_t volume_table[16] = { | 79 int16_t volume_table[16] = { |
72 32767/PSG_VOL_DIV, 26028/PSG_VOL_DIV, 20675/PSG_VOL_DIV, 16422/PSG_VOL_DIV, 13045/PSG_VOL_DIV, 10362/PSG_VOL_DIV, | 80 32767/PSG_VOL_DIV, 26028/PSG_VOL_DIV, 20675/PSG_VOL_DIV, 16422/PSG_VOL_DIV, 13045/PSG_VOL_DIV, 10362/PSG_VOL_DIV, |
73 8231/PSG_VOL_DIV, 6568/PSG_VOL_DIV, 5193/PSG_VOL_DIV, 4125/PSG_VOL_DIV, 3277/PSG_VOL_DIV, 2603/PSG_VOL_DIV, | 81 8231/PSG_VOL_DIV, 6568/PSG_VOL_DIV, 5193/PSG_VOL_DIV, 4125/PSG_VOL_DIV, 3277/PSG_VOL_DIV, 2603/PSG_VOL_DIV, |
74 2067/PSG_VOL_DIV, 1642/PSG_VOL_DIV, 1304/PSG_VOL_DIV, 0 | 82 2067/PSG_VOL_DIV, 1642/PSG_VOL_DIV, 1304/PSG_VOL_DIV, 0 |
75 }; | 83 }; |
76 | 84 |
77 void psg_run(psg_context * context, uint32_t cycles) | 85 void psg_run(psg_context * context, uint32_t cycles) |
78 { | 86 { |
95 } | 103 } |
96 } | 104 } |
97 } | 105 } |
98 } | 106 } |
99 context->buffer_fraction += context->buffer_inc; | 107 context->buffer_fraction += context->buffer_inc; |
100 if (context->buffer_fraction >= 1.0) { | 108 if (context->buffer_fraction >= BUFFER_INC_RES) { |
101 context->buffer_fraction -= 1.0; | 109 context->buffer_fraction -= BUFFER_INC_RES; |
102 int16_t acc = 0; | 110 int16_t acc = 0; |
103 for (int i = 0; i < 3; i++) { | 111 for (int i = 0; i < 3; i++) { |
104 if (context->output_state[i]) { | 112 if (context->output_state[i]) { |
105 acc += volume_table[context->volume[i]]; | 113 acc += volume_table[context->volume[i]]; |
106 } | 114 } |