OSDN Git Service

[VM][WIP] Apply some devices merging upstream 2018-10-05.This still not build.WIP.
[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 #if 0           
81                 wav_header_t header;
82                 wav_chunk_t chunk;
83                 pair16_t __fmt_id;
84                 pair16_t __sample_bits;
85                 pair16_t __channels;
86                 pair_t __sample_rate;
87                 pair_t __chunk_size;
88
89                 fio->Fread(&header, sizeof(header), 1);
90                 __fmt_id.set_2bytes_le_from(header.format_id);
91                 __sample_bits.set_2bytes_le_from(header.sample_bits);
92                 __chunk_size.set_4bytes_le_from(header.fmt_chunk.size);
93                 __channels.set_2bytes_le_from(header.channels);
94                 __sample_rate.set_4bytes_le_from(header.sample_rate);
95                 
96                 if((__fmt_id.w == 1) && ((__sample_bits.w == 8) || (__sample_bits.w == 16))) {
97                         fio->Fseek(__chunk_size.d - 16, FILEIO_SEEK_CUR);
98                         bool is_eof = false;
99                         while(1) {
100                                 if(fio->Fread(&chunk, sizeof(chunk), 1) != 1) {
101                                         is_eof = true;
102                                         break;
103                                 }
104                                 __chunk_size.set_4bytes_le_from(chunk.size);
105                                 if(strncmp(chunk.id, "data", 4) == 0) {
106                                         break;
107                                 }
108                                 fio->Fseek(__chunk_size.d, FILEIO_SEEK_CUR);
109                         }
110                         __chunk_size.set_4bytes_le_from(chunk.size);
111                         if(is_eof) {
112                                 buffer_l = buffer_r = NULL;
113                                 fio->Fclose();
114                                 delete fio;
115                                 return false;
116                         }
117                         if((samples = __chunk_size.d / __channels.w) > 0) {
118                                 if(__sample_bits.w == 16) {
119                                         samples /= 2;
120                                 }
121                                 sample_rate = __sample_rate.d;
122                            
123                                 buffer_l = (int16_t *)malloc(samples * sizeof(int16_t));
124                                 buffer_r = (int16_t *)malloc(samples * sizeof(int16_t));
125                                 
126                                 for(int i = 0; i < samples; i++) {
127                                         int sample_lr[2];
128                                         for(int ch = 0; ch < __channels.sw; ch++) {
129                                                 int16_t sample = 0;
130                                                 if(__sample_bits.w == 16) {
131                                                         union {
132                                                                 int16_t s16;
133                                                                 struct {
134                                                                         uint8_t l, h;
135                                                                 } b;
136                                                         } pair;
137                                                         pair.b.l = fio->FgetUint8();
138                                                         pair.b.h = fio->FgetUint8();
139                                                         sample = pair.s16;
140                                                 } else {
141                                                         sample = (int16_t)(fio->FgetUint8());
142                                                         sample = (sample - 128) * 256;
143                                                 }
144                                                 if(ch < 2) sample_lr[ch] = sample;
145                                         }
146                                         buffer_l[i] = sample_lr[0];
147                                         buffer_r[i] = sample_lr[(__channels.w > 1) ? 1 : 0];
148                                 }
149                                 result = true;
150                         }
151                 }
152 #else
153                 result = load_wav_to_stereo((void *)fio, &buffer_l, &buffer_r, &sample_rate, &samples);
154 #endif
155                 fio->Fclose();
156         }
157         delete fio;
158         
159         return result;
160 }
161
162 void NOISE::play()
163 {
164         if(samples > 0 && register_id == -1 && !mute) {
165                 touch_sound();
166 //              if(register_id == -1) {
167                         register_event(this, EVENT_SAMPLE, 1000000.0 / sample_rate, true, &register_id);
168 //              }
169                 ptr = 0;
170                 get_sample();
171                 set_realtime_render(this, true);
172         }
173 }
174
175 void NOISE::stop()
176 {
177         if(samples > 0 && register_id != -1) {
178                 touch_sound();
179 //              if(register_id != -1) {
180                         cancel_event(this, register_id);
181                         register_id = -1;
182 //              }
183                 sample_l = sample_r = 0;
184                 set_realtime_render(this, false);
185         }
186 }
187
188 void NOISE::get_sample()
189 {
190         if(buffer_l != NULL && ptr < samples) {
191                 sample_l = buffer_l[ptr];
192         } else {
193                 sample_l = 0;
194         }
195         if(buffer_r != NULL && ptr < samples) {
196                 sample_r = buffer_r[ptr];
197         } else {
198                 sample_r = 0;
199         }
200 }
201
202 #define STATE_VERSION   1
203
204 bool NOISE::process_state(FILEIO* state_fio, bool loading)
205 {
206         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
207                 return false;
208         }
209         if(!state_fio->StateCheckInt32(this_device_id)) {
210                 return false;
211         }
212         state_fio->StateInt32(register_id);
213         state_fio->StateInt32(ptr);
214         state_fio->StateInt32(sample_l);
215         state_fio->StateInt32(sample_r);
216         state_fio->StateBool(loop);
217         state_fio->StateBool(mute);
218         return true;
219 }