OSDN Git Service

[General] Convert sourcecode's CRLF format: DOS(WINDOWS) to Unix, to apply patches...
[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 #include "../fileio.h"
12
13 void PCM1BIT::initialize()
14 {
15         signal = false;
16         on = true;
17         mute = false;
18         
19 #ifdef PCM1BIT_HIGH_QUALITY
20         sample_count = 0;
21         prev_clock = 0;
22         prev_vol = 0;
23 #endif
24         update = 0;
25         
26         register_frame_event(this);
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 #ifdef PCM1BIT_HIGH_QUALITY
35                         if(sample_count < 1024) {
36                                 samples_signal[sample_count] = signal;
37                                 samples_out[sample_count] = (on && !mute);
38                                 samples_clock[sample_count] = passed_clock(prev_clock);
39                                 sample_count++;
40                         }
41 #endif
42                         // mute if signal is not changed in 2 frames
43                         update = 2;
44                         signal = next;
45                 }
46         } else if(id == SIG_PCM1BIT_ON) {
47                 on = ((data & mask) != 0);
48         } else if(id == SIG_PCM1BIT_MUTE) {
49                 mute = ((data & mask) != 0);
50         }
51 }
52
53 void PCM1BIT::event_frame()
54 {
55         if(update && --update == 0) {
56 #ifdef PCM1BIT_HIGH_QUALITY
57                 prev_vol = 0;
58 #endif
59         }
60 }
61
62 void PCM1BIT::mix(int32* buffer, int cnt)
63 {
64 #ifdef PCM1BIT_HIGH_QUALITY
65         uint32 cur_clock = current_clock();
66         if(update) {
67                 if(sample_count < 1024) {
68                         samples_signal[sample_count] = signal;
69                         samples_out[sample_count] = (on && !mute);
70                         samples_clock[sample_count] = passed_clock(prev_clock);
71                         sample_count++;
72                 }
73                 uint32 start_clock = 0;
74                 int start_index = 0;
75                 for(int i = 0; i < cnt; i++) {
76                         uint32 end_clock = ((cur_clock - prev_clock) * (i + 1)) / cnt;
77                         int on_clocks = 0, off_clocks = 0;
78                         for(int s = start_index; s < sample_count; s++) {
79                                 uint32 clock = samples_clock[s];
80                                 if(clock <= end_clock) {
81                                         if(samples_out[s]) {
82                                                 if(samples_signal[s]) {
83                                                         on_clocks += clock - start_clock;
84                                                 } else {
85                                                         off_clocks += clock - start_clock;
86                                                 }
87                                         }
88                                         start_clock = clock;
89                                         start_index = s + 1;
90                                 } else {
91                                         if(samples_out[s]) {
92                                                 if(samples_signal[s]) {
93                                                         on_clocks += end_clock - start_clock;
94                                                 } else {
95                                                         off_clocks += end_clock - start_clock;
96                                                 }
97                                         }
98                                         start_clock = end_clock;
99                                         start_index = s;
100                                         break;
101                                 }
102                         }
103                         int clocks = on_clocks + off_clocks;
104                         if(clocks) {
105                                 prev_vol = max_vol * (on_clocks - off_clocks) / clocks;
106                         }
107                         *buffer++ += prev_vol; // L
108                         *buffer++ += prev_vol; // R
109                 }
110         }
111         prev_clock = cur_clock;
112         sample_count = 0;
113 #else
114         if(on && !mute && signal) {
115                 for(int i = 0; i < cnt; i++) {
116                         *buffer++ += max_vol; // L
117                         *buffer++ += max_vol; // R
118                 }
119         }
120 #endif
121 }
122
123 void PCM1BIT::init(int rate, int volume)
124 {
125         max_vol = volume;
126 }
127
128 #define STATE_VERSION   1
129
130 void PCM1BIT::save_state(FILEIO* state_fio)
131 {
132         state_fio->FputUint32(STATE_VERSION);
133         state_fio->FputInt32(this_device_id);
134         
135         state_fio->FputBool(signal);
136         state_fio->FputBool(on);
137         state_fio->FputBool(mute);
138 #ifdef PCM1BIT_HIGH_QUALITY
139         state_fio->Fwrite(samples_signal, sizeof(samples_signal), 1);
140         state_fio->Fwrite(samples_out, sizeof(samples_out), 1);
141         state_fio->Fwrite(samples_clock, sizeof(samples_clock), 1);
142         state_fio->FputInt32(sample_count);
143         state_fio->FputUint32(prev_clock);
144         state_fio->FputInt32(prev_vol);
145 #endif
146         state_fio->FputInt32(update);
147 }
148
149 bool PCM1BIT::load_state(FILEIO* state_fio)
150 {
151         if(state_fio->FgetUint32() != STATE_VERSION) {
152                 return false;
153         }
154         if(state_fio->FgetInt32() != this_device_id) {
155                 return false;
156         }
157         signal = state_fio->FgetBool();
158         on = state_fio->FgetBool();
159         mute = state_fio->FgetBool();
160 #ifdef PCM1BIT_HIGH_QUALITY
161         state_fio->Fread(samples_signal, sizeof(samples_signal), 1);
162         state_fio->Fread(samples_out, sizeof(samples_out), 1);
163         state_fio->Fread(samples_clock, sizeof(samples_clock), 1);
164         sample_count = state_fio->FgetInt32();
165         prev_clock = state_fio->FgetUint32();
166         prev_vol = state_fio->FgetInt32();
167 #endif
168         update = state_fio->FgetInt32();
169         return true;
170 }
171