OSDN Git Service

[VM][DEVICE][WIP] Updating State functions.Still cause FTBFS.
[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 bool PCM1BIT::process_state(FILEIO* state_fio, bool loading)
119 {
120         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
121                 return false;
122         }
123         if(!state_fio->StateCheckInt32(this_device_id)) {
124                 return false;
125         }
126         state_fio->StateValue(signal);
127         state_fio->StateValue(on);
128         state_fio->StateValue(mute);
129         state_fio->StateValue(realtime);
130         state_fio->StateValue(changed);
131         state_fio->StateValue(prev_clock);
132         state_fio->StateValue(positive_clocks);
133         state_fio->StateValue(negative_clocks);
134         
135         // post process
136         if(loading) {
137                 last_vol_l = last_vol_r = 0;
138                 set_realtime_render(this, on & !mute);
139                 //touch_sound();
140         }
141         return true;
142 }