OSDN Git Service

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