OSDN Git Service

[VM][STATE] Apply new state framework to some devices.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pcm1bit.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2007.02.09 -
6
7         [ 1bit PCM ]
8 */
9
10 #include "pcm1bit.h"
11
12 void PCM1BIT::initialize()
13 {
14         DEVICE::initialize();
15         signal = false;
16         on = true;
17         mute = false;
18         realtime = false;
19         changed = 0;
20         last_vol_l = last_vol_r = 0;
21         
22         register_frame_event(this);
23 }
24
25 void PCM1BIT::reset()
26 {
27         prev_clock = get_current_clock();
28         positive_clocks = negative_clocks = 0;
29 }
30
31 void PCM1BIT::write_signal(int id, uint32_t data, uint32_t mask)
32 {
33         if(id == SIG_PCM1BIT_SIGNAL) {
34                 bool next = ((data & mask) != 0);
35                 if(signal != next) {
36                         touch_sound();
37                         if(signal) {
38                                 positive_clocks += get_passed_clock(prev_clock);
39                         } else {
40                                 negative_clocks += get_passed_clock(prev_clock);
41                         }
42                         prev_clock = get_current_clock();
43                         // mute if signal is not changed in 2 frames
44                         changed = 2;
45                         signal = next;
46                 }
47         } else if(id == SIG_PCM1BIT_ON) {
48                 touch_sound();
49                 on = ((data & mask) != 0);
50                 set_realtime_render(this, on & !mute);
51         } else if(id == SIG_PCM1BIT_MUTE) {
52                 touch_sound();
53                 mute = ((data & mask) != 0);
54                 set_realtime_render(this, on & !mute);
55         }
56 }
57
58 void PCM1BIT::event_frame()
59 {
60         if(changed) {
61                 changed--;
62         }
63 }
64
65 void PCM1BIT::mix(int32_t* buffer, int cnt)
66 {
67         if(on && !mute && changed) {
68                 if(signal) {
69                         positive_clocks += get_passed_clock(prev_clock);
70                 } else {
71                         negative_clocks += get_passed_clock(prev_clock);
72                 }
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;
75                 
76                 last_vol_l = apply_volume(sample, volume_l);
77                 last_vol_r = apply_volume(sample, volume_r);
78                 
79                 for(int i = 0; i < cnt; i++) {
80                         *buffer++ += last_vol_l; // L
81                         *buffer++ += last_vol_r; // R
82                 }
83         } else {
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
88                         
89                         if(last_vol_l > 0) {
90                                 last_vol_l--;
91                         } else if(last_vol_l < 0) {
92                                 last_vol_l++;
93                         }
94                         if(last_vol_r > 0) {
95                                 last_vol_r--;
96                         } else if(last_vol_r < 0) {
97                                 last_vol_r++;
98                         }
99                 }
100         }
101         prev_clock = get_current_clock();
102         positive_clocks = negative_clocks = 0;
103 }
104
105 void PCM1BIT::set_volume(int ch, int decibel_l, int decibel_r)
106 {
107         volume_l = decibel_to_volume(decibel_l);
108         volume_r = decibel_to_volume(decibel_r);
109 }
110
111 void PCM1BIT::initialize_sound(int rate, int volume)
112 {
113         max_vol = volume;
114 }
115
116 #define STATE_VERSION   3
117
118 #include "../statesub.h"
119
120 void PCM1BIT::decl_state()
121 {
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);
131 }
132
133 void PCM1BIT::save_state(FILEIO* state_fio)
134 {
135         if(state_entry != NULL) {
136                 state_entry->save_state(state_fio);
137         }
138         //state_fio->FputUint32(STATE_VERSION);
139         //state_fio->FputInt32(this_device_id);
140         
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);
149 }
150
151 bool PCM1BIT::load_state(FILEIO* state_fio)
152 {
153         bool mb = false;
154         if(state_entry != NULL) {
155                 mb = state_entry->load_state(state_fio);
156         }
157         if(!mb) return false;
158         //if(state_fio->FgetUint32() != STATE_VERSION) {
159         //      return false;
160         //}
161         //if(state_fio->FgetInt32() != this_device_id) {
162         //      return false;
163         //}
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();
172         
173         // post process
174         last_vol_l = last_vol_r = 0;
175         //touch_sound();
176         set_realtime_render(this, on & !mute);
177         return true;
178 }
179