Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "gs.h" |
||
6 | #include "tape.h" |
||
7 | #include "config.h" |
||
8 | #include "sndrender/sndcounter.h" |
||
1099 | galstaff | 9 | #include "sndrender/dev_moonsound.h" |
784 | DimkaM | 10 | #include "sound.h" |
716 | lvd | 11 | |
12 | |||
13 | int spkr_dig = 0, mic_dig = 0, covFB_vol = 0, covDD_vol = 0, sd_l = 0, sd_r = 0; |
||
14 | |||
15 | void flush_dig_snd() |
||
16 | { |
||
17 | // __debugbreak(); |
||
18 | if (temp.sndblock) |
||
19 | return; |
||
784 | DimkaM | 20 | int mono = spkr_dig+mic_dig+covFB_vol+covDD_vol; |
716 | lvd | 21 | // printf("mono=%u\n", mono); |
22 | //[vv] |
||
784 | DimkaM | 23 | sound.update(cpu.t - temp.cpu_t_at_frame_start, unsigned(mono + sd_l), unsigned(mono + sd_r)); |
716 | lvd | 24 | } |
25 | |||
26 | void init_snd_frame() |
||
27 | { |
||
28 | temp.cpu_t_at_frame_start = cpu.t; |
||
29 | //[vv] |
||
30 | sound.start_frame(); |
||
784 | DimkaM | 31 | comp.tape.sound.start_frame(); |
716 | lvd | 32 | |
33 | if (conf.sound.ay_scheme) |
||
34 | { |
||
35 | ay[0].start_frame(); |
||
36 | if (conf.sound.ay_scheme > AY_SCHEME_SINGLE) |
||
37 | ay[1].start_frame(); |
||
38 | } |
||
39 | |||
40 | Saa1099.start_frame(); |
||
1099 | galstaff | 41 | zxmmoonsound.start_frame(); |
716 | lvd | 42 | |
43 | #ifdef MOD_GS |
||
44 | init_gs_frame(); |
||
45 | #endif |
||
46 | } |
||
47 | |||
784 | DimkaM | 48 | static float y_1[2] = { 0.0f }; |
49 | static i16 x_1[2] = { 0 }; |
||
716 | lvd | 50 | |
51 | void flush_snd_frame() |
||
52 | { |
||
53 | tape_bit(); |
||
54 | #ifdef MOD_GS |
||
55 | flush_gs_frame(); |
||
56 | #endif |
||
57 | |||
58 | if (temp.sndblock) |
||
59 | return; |
||
60 | |||
61 | unsigned endframe = cpu.t - temp.cpu_t_at_frame_start; |
||
62 | |||
63 | if (conf.sound.ay_scheme) |
||
64 | { // sound chip present |
||
65 | |||
66 | ay[0].end_frame(endframe); |
||
67 | // if (conf.sound.ay_samples) mix_dig(ay[0]); |
||
68 | |||
69 | if (conf.sound.ay_scheme > AY_SCHEME_SINGLE) |
||
70 | { |
||
71 | |||
72 | ay[1].end_frame(endframe); |
||
73 | // if (conf.sound.ay_samples) mix_dig(ay[1]); |
||
74 | |||
75 | if (conf.sound.ay_scheme == AY_SCHEME_PSEUDO) |
||
76 | { |
||
77 | unsigned char last = ay[0].get_r13_reloaded()? 13 : 12; |
||
784 | DimkaM | 78 | for(unsigned char r = 0; r <= last; r++) |
79 | { |
||
80 | ay[1].select(r); |
||
81 | ay[1].write(0, ay[0].get_reg(r)); |
||
82 | } |
||
716 | lvd | 83 | } |
84 | } |
||
85 | |||
86 | if (savesndtype == 2) |
||
87 | { |
||
88 | if (!vtxbuf) |
||
89 | { |
||
90 | vtxbuf = (unsigned char*)malloc(32768); |
||
91 | vtxbufsize = 32768; |
||
92 | vtxbuffilled = 0; |
||
93 | } |
||
94 | |||
95 | if (vtxbuffilled + 14 >= vtxbufsize) |
||
96 | { |
||
97 | vtxbufsize += 32768; |
||
98 | vtxbuf = (unsigned char*)realloc(vtxbuf, vtxbufsize); |
||
99 | } |
||
100 | |||
101 | for (unsigned char r = 0; r < 14; r++) |
||
102 | vtxbuf[vtxbuffilled+r] = ay[0].get_reg(r); |
||
103 | |||
104 | if (!ay[0].get_r13_reloaded()) |
||
105 | vtxbuf[vtxbuffilled+13] = 0xFF; |
||
106 | |||
107 | vtxbuffilled += 14; |
||
108 | } |
||
109 | } |
||
110 | Saa1099.end_frame(endframe); |
||
1099 | galstaff | 111 | zxmmoonsound.end_frame(endframe); |
716 | lvd | 112 | |
113 | sound.end_frame(endframe); |
||
114 | // if (comp.tape.play_pointer) // play tape pulses |
||
784 | DimkaM | 115 | comp.tape.sound.end_frame(endframe); |
716 | lvd | 116 | // else comp.tape.sound.end_empty_frame(endframe); |
117 | |||
118 | unsigned bufplay, n_samples; |
||
119 | sndcounter.begin(); |
||
120 | |||
121 | sndcounter.count(sound); |
||
784 | DimkaM | 122 | sndcounter.count(comp.tape.sound); |
716 | lvd | 123 | if (conf.sound.ay_scheme) |
124 | { |
||
125 | sndcounter.count(ay[0]); |
||
126 | if (conf.sound.ay_scheme > AY_SCHEME_SINGLE) |
||
127 | sndcounter.count(ay[1]); |
||
128 | } |
||
129 | |||
130 | sndcounter.count(Saa1099); |
||
1099 | galstaff | 131 | sndcounter.count(zxmmoonsound); |
716 | lvd | 132 | |
133 | #ifdef MOD_GS |
||
134 | #ifdef MOD_GSZ80 |
||
135 | if (conf.gs_type==1) |
||
136 | sndcounter.count(z80gs::sound); |
||
137 | #endif |
||
138 | |||
139 | #ifdef MOD_GSBASS |
||
140 | // if (conf.gs_type==2) { gs.mix_fx(); return; } |
||
141 | #endif |
||
142 | #endif // MOD_GS |
||
143 | sndcounter.end(bufplay, n_samples); |
||
144 | |||
145 | for (unsigned k = 0; k < n_samples; k++, bufplay++) |
||
146 | { |
||
147 | u32 v = sndbuf[bufplay & (SNDBUFSIZE-1)]; |
||
148 | u32 Y; |
||
149 | if(conf.RejectDC) // DC rejection filter |
||
150 | { |
||
151 | i16 x[2]; |
||
152 | float y[2]; |
||
153 | x[0] = i16(v & 0xFFFF); |
||
154 | x[1] = i16(v >> 16U); |
||
155 | y[0] = 0.995f * (x[0] - x_1[0]) + 0.99f * y_1[0]; |
||
156 | y[1] = 0.995f * (x[1] - x_1[1]) + 0.99f * y_1[1]; |
||
157 | x_1[0] = x[0]; |
||
158 | x_1[1] = x[1]; |
||
159 | y_1[0] = y[0]; |
||
160 | y_1[1] = y[1]; |
||
784 | DimkaM | 161 | Y = u32(((i16(y[1]) & 0xFFFF)<<16) | (i16(y[0]) & 0xFFFF)); |
716 | lvd | 162 | } |
163 | else |
||
164 | { |
||
165 | Y = v; |
||
166 | } |
||
167 | |||
168 | sndplaybuf[k] = Y; |
||
169 | sndbuf[bufplay & (SNDBUFSIZE-1)] = 0; |
||
170 | } |
||
171 | |||
172 | #if 0 |
||
173 | // printf("n_samples=%u\n", n_samples); |
||
174 | for (unsigned k = 0; k < n_samples; k++, bufplay++) |
||
175 | { |
||
176 | sndplaybuf[k] = sndbuf[bufplay & (SNDBUFSIZE-1)]; |
||
177 | /* |
||
178 | if(sndplaybuf[k] == 0x20002000) |
||
179 | __debugbreak(); |
||
180 | */ |
||
181 | sndbuf[bufplay & (SNDBUFSIZE-1)] = 0; |
||
182 | } |
||
183 | #endif |
||
184 | spbsize = n_samples*4; |
||
185 | // assert(spbsize != 0); |
||
186 | |||
187 | return; |
||
188 | |||
189 | /* |
||
190 | |||
191 | // count available samples and copy to sound buffer |
||
192 | unsigned save_ticks = temp.snd_frame_ticks; // sound output limit = 1 frame |
||
193 | save_ticks = min(save_ticks, sound.ready_samples()); |
||
194 | save_ticks = min(save_ticks, comp.ay->sound.ready_samples()); |
||
195 | save_ticks = min(save_ticks, comp.tape.sound.ready_samples()); |
||
196 | #ifdef MOD_GSZ80 |
||
197 | if (conf.gs_type == 1) |
||
198 | save_ticks = min(save_ticks, z80gs::sound.ready_samples()); |
||
199 | #endif |
||
200 | |||
201 | // fx player always gives enough samples |
||
202 | #ifdef MOD_GSBASS |
||
203 | if (conf.gs_type == 2) |
||
204 | for (int i = 0; i < 4; i++) |
||
205 | save_ticks = min(save_ticks, gs.chan[i].sound_state.ready_samples()); |
||
206 | #endif |
||
207 | */ |
||
208 | |||
209 | } |
||
210 | |||
211 | void restart_sound() |
||
212 | { |
||
213 | // printf("%s\n", __FUNCTION__); |
||
214 | |||
215 | unsigned cpufq = conf.intfq * conf.frame; |
||
216 | sound.set_timings(cpufq, conf.sound.fq); |
||
784 | DimkaM | 217 | comp.tape.sound.set_timings(cpufq, conf.sound.fq); |
716 | lvd | 218 | if (conf.sound.ay_scheme) |
219 | { |
||
220 | ay[0].set_timings(cpufq, conf.sound.ayfq, conf.sound.fq); |
||
221 | if (conf.sound.ay_scheme > AY_SCHEME_SINGLE) ay[1].set_timings(cpufq, conf.sound.ayfq, conf.sound.fq); |
||
222 | } |
||
223 | |||
224 | Saa1099.set_timings(cpufq, conf.sound.saa1099fq, conf.sound.fq); |
||
1099 | galstaff | 225 | zxmmoonsound.set_timings(cpufq, 33868800, conf.sound.fq); |
716 | lvd | 226 | |
227 | // comp.tape.sound.clear(); |
||
228 | #ifdef MOD_GS |
||
229 | reset_gs_sound(); |
||
230 | #endif |
||
231 | |||
232 | sndcounter.reset(); |
||
233 | |||
234 | memset(sndbuf, 0, sizeof sndbuf); |
||
235 | } |
||
236 | |||
237 | void apply_sound() |
||
238 | { |
||
239 | if (conf.sound.ay_scheme < AY_SCHEME_QUADRO) comp.active_ay = 0; |
||
240 | |||
241 | load_ay_stereo(); |
||
242 | load_ay_vols(); |
||
243 | |||
244 | ay[0].set_chip((SNDCHIP::CHIP_TYPE)conf.sound.ay_chip); |
||
245 | ay[1].set_chip((SNDCHIP::CHIP_TYPE)conf.sound.ay_chip); |
||
246 | |||
247 | const SNDCHIP_VOLTAB *voltab = (SNDCHIP_VOLTAB*)&conf.sound.ay_voltab; |
||
248 | const SNDCHIP_PANTAB *stereo = (SNDCHIP_PANTAB*)&conf.sound.ay_stereo_tab; |
||
784 | DimkaM | 249 | ay[0].set_volumes(unsigned(conf.sound.ay_vol), voltab, stereo); |
716 | lvd | 250 | |
251 | SNDCHIP_PANTAB reversed; |
||
252 | if (conf.sound.ay_scheme == AY_SCHEME_PSEUDO) { |
||
253 | for (int i = 0; i < 6; i++) |
||
254 | reversed.raw[i] = stereo->raw[i^1]; // swap left/right |
||
255 | stereo = &reversed; |
||
256 | } |
||
784 | DimkaM | 257 | ay[1].set_volumes(unsigned(conf.sound.ay_vol), voltab, stereo); |
716 | lvd | 258 | |
259 | |||
260 | #ifdef MOD_GS |
||
261 | apply_gs(); |
||
262 | #endif |
||
263 | |||
264 | restart_sound(); |
||
265 | } |
||
266 | |||
267 | /* |
||
268 | #define SAMPLE_SIZE (1024*3) |
||
269 | #define SAMPLE_T 256 |
||
270 | int waveA[SAMPLE_SIZE], waveB[SAMPLE_SIZE], waveC[SAMPLE_SIZE]; |
||
271 | |||
272 | void mix_dig(SNDCHIP &chip) |
||
273 | { |
||
274 | unsigned base = sb_start_frame >> TICK_FF; |
||
275 | for (unsigned i = 0; i < temp.snd_frame_samples; i++) { |
||
276 | |||
277 | ta += fa; while (ta >= SAMPLE_SIZE*0x100) ta -= SAMPLE_SIZE*0x100; |
||
278 | tb += fb; while (tb >= SAMPLE_SIZE*0x100) tb -= SAMPLE_SIZE*0x100; |
||
279 | tc += fc; while (tc >= SAMPLE_SIZE*0x100) tc -= SAMPLE_SIZE*0x100; |
||
280 | tn += fn; |
||
281 | while (tn >= 0x10000) { |
||
282 | ns = (ns*2+1) ^ (((ns>>16)^(ns>>13)) & 1); |
||
283 | bitN = 0 - ((ns >> 16) & 1); |
||
284 | tn -= 0x10000; |
||
285 | } |
||
286 | te += fe; |
||
287 | while (te >= 0x10000) { |
||
288 | env += denv; |
||
289 | if (env & ~31) { |
||
290 | unsigned mask = 1 << r_env; |
||
291 | if (mask & ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<9)|(1<<15))) |
||
292 | env = denv = 0; |
||
293 | else if (mask & ((1<<8)|(1<<12))) |
||
294 | env &= 31; |
||
295 | else if (mask & ((1<<10)|(1<<14))) |
||
296 | denv = -(int)denv, env = env + denv; |
||
297 | else env = 31, denv = 0; //11,13 |
||
298 | } |
||
299 | te -= 0x10000; |
||
300 | } |
||
301 | |||
302 | unsigned left = 0, right = 0, en, vol; |
||
303 | |||
304 | en = (r_vA & 0x10) ? env : (r_vA & 0x0F)*2+1; |
||
305 | vol = (bitN | bit3) & (waveA[ta/0x100] | bit0) & 0xFFFF; |
||
306 | left += vol*vols[0][en], right += vol*vols[1][en]; |
||
307 | |||
308 | en = (r_vB & 0x10) ? env : (r_vB & 0x0F)*2+1; |
||
309 | vol = (bitN | bit4) & (waveB[tb/0x100] | bit1) & 0xFFFF; |
||
310 | left += vol*vols[2][en], right += vol*vols[3][en]; |
||
311 | |||
312 | en = (r_vC & 0x10) ? env : (r_vC & 0x0F)*2+1; |
||
313 | vol = (bitN | bit5) & (waveC[tc/0x100] | bit2) & 0xFFFF; |
||
314 | left += vol*vols[4][en], right += vol*vols[5][en]; |
||
315 | |||
316 | *(unsigned*)&sndbuf[(i+base) & (SNDBUFSIZE-1)] += (left >> 16) + (right & 0xFFFF0000); |
||
317 | } |
||
318 | sound.flush_empty(); |
||
319 | } |
||
320 | |||
321 | #define PI 3.14159265359 |
||
322 | |||
323 | double sin1(int i) { |
||
324 | while (i > SAMPLE_SIZE) i -= SAMPLE_SIZE; |
||
325 | if (i < SAMPLE_SIZE/2) return (double)i*2/SAMPLE_SIZE; |
||
326 | return 2-(double)i*2/SAMPLE_SIZE; |
||
327 | } |
||
328 | double cos1(int i) { |
||
329 | return 1-sin1(i); |
||
330 | } |
||
331 | |||
332 | int *wavs[3] = { waveA, waveB, waveC }; |
||
333 | void make_samples() |
||
334 | { |
||
335 | #define cl (0.35) |
||
336 | #define cl2 (0.25) |
||
337 | #define clip(x) (((x>cl) ? cl : (x < cl) ? -cl : x)/cl) |
||
338 | #define clip2(x) ((x < -cl2) ? 0 : (x+cl2)) |
||
339 | for (int i = 0; i < SAMPLE_SIZE; i++) { |
||
340 | double p1 = 0.8+0.2*sin1(i*4); |
||
341 | double p2 = 0.7+0.3*cos1(i*2); |
||
342 | double p3 = 0.9+0.1*sin1(i); |
||
343 | double t = (double)(i % SAMPLE_T)*2*PI/SAMPLE_T; |
||
344 | // #define fabs(x) (x) |
||
345 | waveA[i] = (unsigned)(fabs(p1*clip(1+sin(3*t/2))*0.7+p3*clip(sin(t))+p1*sin(4*t)*0.25+p2*clip2(cos(1+6*t)))*0x3FFF); |
||
346 | waveB[i] = (unsigned)(fabs(p1*clip(2+sin(3*t/2))*0.7+p3*clip(sin(t))+p1*sin(1+7*t/2)*0.4+p2*clip2(cos(2+5*t)))*0x3FFF); |
||
347 | waveC[i] = (unsigned)(fabs(p1*clip(0.5+sin(3*t/2))*0.7+p3*clip(sin(t))+p1*sin(0.2+9*t/2)*0.6+p2*clip2(cos(3+5*t)))*0x3FFF); |
||
348 | // #undef fabs |
||
349 | } |
||
350 | #undef clip |
||
351 | #undef cl |
||
352 | #undef cl2 |
||
353 | #undef clip2 |
||
354 | for (int ind = 0; ind < 3; ind++) { |
||
355 | int *arr = wavs[ind], max = -0x7FFFFFFF, min = 0x7FFFFFFF; |
||
356 | for (int i1 = 0; i1 < SAMPLE_SIZE; i1++) { |
||
357 | if (arr[i1] > max) max = arr[i1]; |
||
358 | if (arr[i1] < min) min = arr[i1]; |
||
359 | } |
||
360 | for (i1 = 0; i1 < SAMPLE_SIZE; i1++) |
||
361 | arr[i1] = (int)(((double)arr[i1] - min)*0x10000/(max-min)); |
||
362 | } |
||
363 | } |
||
364 | */ |