OSDN Git Service

[VM][STATE] Apply new state framework to some devices a lot (excepts some devices...
[csp-qt/common_source_project-fm7.git] / source / src / vm / noise.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2017.03.08-
6
7         [ noise player ]
8 */
9
10 #include "noise.h"
11
12 #define EVENT_SAMPLE    0
13
14 void NOISE::initialize()
15 {
16         DEVICE::initialize();
17         register_id = -1;
18         ptr = 0;
19         sample_l = sample_r = 0;
20 }
21
22 void NOISE::release()
23 {
24         if(buffer_l != NULL) {
25                 free(buffer_l);
26                 buffer_l = NULL;
27         }
28         if(buffer_r != NULL) {
29                 free(buffer_r);
30                 buffer_r = NULL;
31         }
32 }
33
34 void NOISE::reset()
35 {
36         stop();
37 }
38
39 void NOISE::event_callback(int event_id, int err)
40 {
41         if(++ptr < samples) {
42                 get_sample();
43         } else if(loop) {
44                 ptr = 0;
45                 get_sample();
46         } else {
47                 stop();
48         }
49 }
50
51 void NOISE::mix(int32_t* buffer, int cnt)
52 {
53         if(register_id != -1 && !mute) {
54                 int32_t val_l = apply_volume(sample_l, volume_l);
55                 int32_t val_r = apply_volume(sample_r, volume_r);
56                 
57                 for(int i = 0; i < cnt; i++) {
58                         *buffer++ += val_l; // L
59                         *buffer++ += val_r; // R
60                 }
61         }
62 }
63
64 void NOISE::set_volume(int ch, int decibel_l, int decibel_r)
65 {
66         volume_l = decibel_to_volume(decibel_l);
67         volume_r = decibel_to_volume(decibel_r);
68 }
69
70 bool NOISE::load_wav_file(const _TCHAR *file_name)
71 {
72         if(samples != 0) {
73                 // already loaded
74                 return true;
75         }
76         FILEIO *fio = new FILEIO();
77         bool result = false;
78         
79         if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
80                 wav_header_t header;
81                 wav_chunk_t chunk;
82                 
83                 fio->Fread(&header, sizeof(header), 1);
84                 
85                 if(header.format_id == 1 && (header.sample_bits == 8 || header.sample_bits == 16)) {
86                         fio->Fseek(header.fmt_chunk.size - 16, FILEIO_SEEK_CUR);
87                         while(1) {
88                                 fio->Fread(&chunk, sizeof(chunk), 1);
89                                 if(strncmp(chunk.id, "data", 4) == 0) {
90                                         break;
91                                 }
92                                 fio->Fseek(chunk.size, FILEIO_SEEK_CUR);
93                         }
94                         if((samples = chunk.size / header.channels) > 0) {
95                                 if(header.sample_bits == 16) {
96                                         samples /= 2;
97                                 }
98                                 sample_rate = header.sample_rate;
99                                 
100                                 buffer_l = (int16_t *)malloc(samples * sizeof(int16_t));
101                                 buffer_r = (int16_t *)malloc(samples * sizeof(int16_t));
102                                 
103                                 for(int i = 0; i < samples; i++) {
104                                         int sample_lr[2];
105                                         for(int ch = 0; ch < header.channels; ch++) {
106                                                 int16_t sample = 0;
107                                                 if(header.sample_bits == 16) {
108                                                         union {
109                                                                 int16_t s16;
110                                                                 struct {
111                                                                         uint8_t l, h;
112                                                                 } b;
113                                                         } pair;
114                                                         pair.b.l = fio->FgetUint8();
115                                                         pair.b.h = fio->FgetUint8();
116                                                         sample = pair.s16;
117                                                 } else {
118                                                         sample = (int16_t)(fio->FgetUint8());
119                                                         sample = (sample - 128) * 256;
120                                                 }
121                                                 if(ch < 2) sample_lr[ch] = sample;
122                                         }
123                                         buffer_l[i] = sample_lr[0];
124                                         buffer_r[i] = sample_lr[(header.channels > 1) ? 1 : 0];
125                                 }
126                                 result = true;
127                         }
128                 }
129                 fio->Fclose();
130         }
131         delete fio;
132         
133         return result;
134 }
135
136 void NOISE::play()
137 {
138         if(samples > 0 && register_id == -1 && !mute) {
139                 touch_sound();
140 //              if(register_id == -1) {
141                         register_event(this, EVENT_SAMPLE, 1000000.0 / sample_rate, true, &register_id);
142 //              }
143                 ptr = 0;
144                 get_sample();
145                 set_realtime_render(this, true);
146         }
147 }
148
149 void NOISE::stop()
150 {
151         if(samples > 0 && register_id != -1) {
152                 touch_sound();
153 //              if(register_id != -1) {
154                         cancel_event(this, register_id);
155                         register_id = -1;
156 //              }
157                 sample_l = sample_r = 0;
158                 set_realtime_render(this, false);
159         }
160 }
161
162 void NOISE::get_sample()
163 {
164         if(buffer_l != NULL && ptr < samples) {
165                 sample_l = buffer_l[ptr];
166         } else {
167                 sample_l = 0;
168         }
169         if(buffer_r != NULL && ptr < samples) {
170                 sample_r = buffer_l[ptr];
171         } else {
172                 sample_r = 0;
173         }
174 }
175
176 #define STATE_VERSION   1
177
178 #include "../statesub.h"
179
180 void NOISE::decl_state()
181 {
182         enter_decl_state(STATE_VERSION);
183
184         DECL_STATE_ENTRY_INT32(register_id);
185         DECL_STATE_ENTRY_INT32(ptr);
186         DECL_STATE_ENTRY_INT32(sample_l);
187         DECL_STATE_ENTRY_INT32(sample_r);
188         DECL_STATE_ENTRY_BOOL(loop);
189         DECL_STATE_ENTRY_BOOL(mute);
190
191         leave_decl_state();
192 }
193 void NOISE::save_state(FILEIO* state_fio)
194 {
195         if(state_entry != NULL) {
196                 state_entry->save_state(state_fio);
197         }
198         //state_fio->FputUint32(STATE_VERSION);
199         //state_fio->FputInt32(this_device_id);
200         
201         //state_fio->FputInt32(register_id);
202         //state_fio->FputInt32(ptr);
203         //state_fio->FputInt32(sample_l);
204         //state_fio->FputInt32(sample_r);
205         //state_fio->FputBool(loop);
206         //state_fio->FputBool(mute);
207 }
208
209 bool NOISE::load_state(FILEIO* state_fio)
210 {
211         bool mb = false;
212         if(state_entry != NULL) {
213                 mb = state_entry->load_state(state_fio);
214         }
215         if(!mb) return false;
216         //if(state_fio->FgetUint32() != STATE_VERSION) {
217         //      return false;
218         //}
219         //if(state_fio->FgetInt32() != this_device_id) {
220         //      return false;
221         //}
222         //register_id = state_fio->FgetInt32();
223         //ptr = state_fio->FgetInt32();
224         //sample_l = state_fio->FgetInt32();
225         //sample_r = state_fio->FgetInt32();
226         //loop = state_fio->FgetBool();
227         //mute = state_fio->FgetBool();
228         return true;
229 }
230