2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 void PCM1BIT::initialize()
20 last_vol_l = last_vol_r = 0;
22 register_frame_event(this);
27 prev_clock = get_current_clock();
28 positive_clocks = negative_clocks = 0;
31 void PCM1BIT::write_signal(int id, uint32_t data, uint32_t mask)
33 if(id == SIG_PCM1BIT_SIGNAL) {
34 bool next = ((data & mask) != 0);
38 positive_clocks += get_passed_clock(prev_clock);
40 negative_clocks += get_passed_clock(prev_clock);
42 prev_clock = get_current_clock();
43 // mute if signal is not changed in 2 frames
47 } else if(id == SIG_PCM1BIT_ON) {
49 on = ((data & mask) != 0);
50 set_realtime_render(this, on & !mute);
51 } else if(id == SIG_PCM1BIT_MUTE) {
53 mute = ((data & mask) != 0);
54 set_realtime_render(this, on & !mute);
58 void PCM1BIT::event_frame()
65 void PCM1BIT::mix(int32_t* buffer, int cnt)
67 if(on && !mute && changed) {
69 positive_clocks += get_passed_clock(prev_clock);
71 negative_clocks += get_passed_clock(prev_clock);
73 int clocks = positive_clocks + negative_clocks;
74 int sample = clocks ? (max_vol * positive_clocks - max_vol * negative_clocks) / clocks : signal ? max_vol : -max_vol;
76 last_vol_l = apply_volume(sample, volume_l);
77 last_vol_r = apply_volume(sample, volume_r);
79 for(int i = 0; i < cnt; i++) {
80 *buffer++ += last_vol_l; // L
81 *buffer++ += last_vol_r; // R
84 // suppress petite noise when go to mute
85 for(int i = 0; i < cnt; i++) {
86 *buffer++ += last_vol_l; // L
87 *buffer++ += last_vol_r; // R
91 } else if(last_vol_l < 0) {
96 } else if(last_vol_r < 0) {
101 prev_clock = get_current_clock();
102 positive_clocks = negative_clocks = 0;
105 void PCM1BIT::set_volume(int ch, int decibel_l, int decibel_r)
107 volume_l = decibel_to_volume(decibel_l);
108 volume_r = decibel_to_volume(decibel_r);
111 void PCM1BIT::initialize_sound(int rate, int volume)
116 #define STATE_VERSION 3
118 #include "../statesub.h"
120 void PCM1BIT::decl_state()
122 state_entry = new csp_state_utils(STATE_VERSION, this_device_id, _T("PCM1BIT"));
123 DECL_STATE_ENTRY_BOOL(signal);
124 DECL_STATE_ENTRY_BOOL(on);
125 DECL_STATE_ENTRY_BOOL(mute);
126 DECL_STATE_ENTRY_BOOL(realtime);
127 DECL_STATE_ENTRY_INT32(changed);
128 DECL_STATE_ENTRY_UINT32(prev_clock);
129 DECL_STATE_ENTRY_INT32(positive_clocks);
130 DECL_STATE_ENTRY_INT32(negative_clocks);
133 void PCM1BIT::save_state(FILEIO* state_fio)
135 if(state_entry != NULL) {
136 state_entry->save_state(state_fio);
138 //state_fio->FputUint32(STATE_VERSION);
139 //state_fio->FputInt32(this_device_id);
141 //state_fio->FputBool(signal);
142 //state_fio->FputBool(on);
143 //state_fio->FputBool(mute);
144 //state_fio->FputBool(realtime);
145 //state_fio->FputInt32(changed);
146 //state_fio->FputUint32(prev_clock);
147 //state_fio->FputInt32(positive_clocks);
148 //state_fio->FputInt32(negative_clocks);
151 bool PCM1BIT::load_state(FILEIO* state_fio)
154 if(state_entry != NULL) {
155 mb = state_entry->load_state(state_fio);
157 if(!mb) return false;
158 //if(state_fio->FgetUint32() != STATE_VERSION) {
161 //if(state_fio->FgetInt32() != this_device_id) {
164 //signal = state_fio->FgetBool();
165 //on = state_fio->FgetBool();
166 //mute = state_fio->FgetBool();
167 //realtime = state_fio->FgetBool();
168 //changed = state_fio->FgetInt32();
169 //prev_clock = state_fio->FgetUint32();
170 //positive_clocks = state_fio->FgetInt32();
171 //negative_clocks = state_fio->FgetInt32();
174 last_vol_l = last_vol_r = 0;
176 set_realtime_render(this, on & !mute);