OSDN Git Service

[VM][General] Merge upstream 2016-02-13. Still don't implement OSD/Gui part of joysti...
[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         signal = false;
15         on = true;
16         mute = false;
17         changed = 0;
18         last_vol_l = last_vol_r = 0;
19         
20         register_frame_event(this);
21 }
22
23 void PCM1BIT::reset()
24 {
25         prev_clock = current_clock();
26         positive_clocks = negative_clocks = 0;
27 }
28
29 void PCM1BIT::write_signal(int id, uint32 data, uint32 mask)
30 {
31         if(id == SIG_PCM1BIT_SIGNAL) {
32                 bool next = ((data & mask) != 0);
33                 if(signal != next) {
34                         if(signal) {
35                                 positive_clocks += passed_clock(prev_clock);
36                         } else {
37                                 negative_clocks += passed_clock(prev_clock);
38                         }
39                         prev_clock = current_clock();
40                         // mute if signal is not changed in 2 frames
41                         changed = 2;
42                         signal = next;
43                 }
44         } else if(id == SIG_PCM1BIT_ON) {
45                 on = ((data & mask) != 0);
46         } else if(id == SIG_PCM1BIT_MUTE) {
47                 mute = ((data & mask) != 0);
48         }
49 }
50
51 void PCM1BIT::event_frame()
52 {
53         if(changed) {
54                 changed--;
55         }
56 }
57
58 void PCM1BIT::mix(int32* buffer, int cnt)
59 {
60         if(on && !mute && changed) {
61                 if(signal) {
62                         positive_clocks += passed_clock(prev_clock);
63                 } else {
64                         negative_clocks += passed_clock(prev_clock);
65                 }
66                 int clocks = positive_clocks + negative_clocks;
67                 int sample = clocks ? (max_vol * positive_clocks - max_vol * negative_clocks) / clocks : signal ? max_vol : -max_vol;
68                 
69                 last_vol_l = apply_volume(sample, volume_l);
70                 last_vol_r = apply_volume(sample, volume_r);
71                 
72                 for(int i = 0; i < cnt; i++) {
73                         *buffer++ += last_vol_l; // L
74                         *buffer++ += last_vol_r; // R
75                 }
76         } else {
77                 // suppress petite noise when go to mute
78                 for(int i = 0; i < cnt; i++) {
79                         *buffer++ += last_vol_l; // L
80                         *buffer++ += last_vol_r; // R
81                         
82                         if(last_vol_l > 0) {
83                                 last_vol_l--;
84                         } else if(last_vol_l < 0) {
85                                 last_vol_l++;
86                         }
87                         if(last_vol_r > 0) {
88                                 last_vol_r--;
89                         } else if(last_vol_r < 0) {
90                                 last_vol_r++;
91                         }
92                 }
93         }
94         prev_clock = current_clock();
95         positive_clocks = negative_clocks = 0;
96 }
97
98 void PCM1BIT::set_volume(int ch, int decibel_l, int decibel_r)
99 {
100         volume_l = decibel_to_volume(decibel_l);
101         volume_r = decibel_to_volume(decibel_r);
102 }
103
104 void PCM1BIT::init(int rate, int volume)
105 {
106         max_vol = volume;
107 }
108
109 #define STATE_VERSION   2
110
111 void PCM1BIT::save_state(FILEIO* state_fio)
112 {
113         state_fio->FputUint32(STATE_VERSION);
114         state_fio->FputInt32(this_device_id);
115         
116         state_fio->FputBool(signal);
117         state_fio->FputBool(on);
118         state_fio->FputBool(mute);
119         state_fio->FputInt32(changed);
120         state_fio->FputUint32(prev_clock);
121         state_fio->FputInt32(positive_clocks);
122         state_fio->FputInt32(negative_clocks);
123 }
124
125 bool PCM1BIT::load_state(FILEIO* state_fio)
126 {
127         if(state_fio->FgetUint32() != STATE_VERSION) {
128                 return false;
129         }
130         if(state_fio->FgetInt32() != this_device_id) {
131                 return false;
132         }
133         signal = state_fio->FgetBool();
134         on = state_fio->FgetBool();
135         mute = state_fio->FgetBool();
136         changed = state_fio->FgetInt32();
137         prev_clock = state_fio->FgetUint32();
138         positive_clocks = state_fio->FgetInt32();
139         negative_clocks = state_fio->FgetInt32();
140         
141         // post process
142         last_vol_l = last_vol_r = 0;
143         return true;
144 }
145