libfusefdc: reformatted UDI i/o code
[zymosis.git] / src / ZXEmuT / snd_alsa.c
blobea7877090646176b1441fd3eadc77304011c5322
1 /*
2 sound.c: Sound support
3 Copyright (c) 2000-2016 Russell Marks, Matan Ziv-Av, Philip Kendall,
4 Fredrick Meunier, Patrik Rak
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 Author contact information:
22 E-mail: philip-fuse@shadowmagic.org.uk
24 ALSA part by Ketmar // Invisible Vector
26 #include "libvideo/video.h"
27 #include "snd_alsa.h"
28 #include "blipbuffer.h"
29 #include "emuvars.h"
30 #include "console.h"
33 static int sndUsing = 0;
34 static int sndBlipOverflowWarned = 0;
37 int soundIsWorking (void) {
38 return sndUsing;
42 typedef struct {
43 int tstate;
44 uint8_t reg, val;
45 } SndAYChanges;
47 #define MAX_AY_CHANGES (32768)
49 static SndAYChanges sndAYChanges[MAX_AY_CHANGES];
50 static int sndAYChangeCount = 0;
51 static int sndAYJustReset = 0;
54 #ifdef USE_SOUND
55 #include <alsa/asoundlib.h>
57 int sndAllowUseToggle = 1;
59 static char *alsaDev = "default";
60 static snd_pcm_t *playback_handle = NULL;
62 #define AMPL_BEEPER (50*256*15/10)
63 #define AMPL_TAPE (2*256*0*15/10)
64 #define AMPL_AY_TONE (24*256*15/10) /* three of these */
67 #define SND_BUFFERS_IN_RING (4)
70 static int16_t sndBuffer16[SND_BUFFERS_IN_RING*48000];
71 static int16_t sndBuffer16AY[SND_BUFFERS_IN_RING*48000];
72 static int sndOldVal = 0;
73 static int sndBeeperLastSubVol = 0;
74 static int sndFrameSize = 1; // samples per frame
75 static int sndBufFillPos = 0;
76 static int sndBufPlayPos = 0;
78 static Blip_Buffer *left_buf = NULL;
79 static Blip_Buffer *right_buf = NULL;
81 static Blip_Synth *left_beeper_synth = NULL, *right_beeper_synth = NULL;
83 static Blip_Synth *ay_a_synth = NULL, *ay_b_synth = NULL, *ay_c_synth = NULL;
84 static Blip_Synth *ay_a_synth_r = NULL, *ay_b_synth_r = NULL, *ay_c_synth_r = NULL;
87 typedef struct {
88 int bass;
89 double treble;
90 } SpeakerTypeInfo;
92 static const SpeakerTypeInfo speaker_type_info[5] = {
93 { 200, -37.0 }, /* TV */
94 { 1000, -67.0 }, /* beeper */
95 { 16, -8.0f}, /* AY_SPEAKER_DEFAULT */
96 { 1, 0.0f}, /* flat */
97 { 1, 5.0f}, /* crisp */
100 static unsigned speaker_type = SOUND_FILTER_DEFAULT;
102 static unsigned sound_stereo_ay = SOUND_STEREO_AY_ABC;
104 /* returns the emulation speed adjusted processor speed, in Hz */
105 static unsigned sound_get_effective_processor_speed (void) {
106 return machineInfo.cpuSpeed*optSpeed/100;
110 static inline double convert_volume_intr (int vol) {
111 if (vol <= 0) return 0;
112 if (vol > 500) vol = 500;
113 return (double)vol/100.0;
117 static inline double convert_volume (int vol) {
118 double v0 = convert_volume_intr(vol);
119 double v1 = convert_volume_intr(optSoundVolume);
120 return v0*v1;
124 static int sound_init_blip (Blip_Buffer **buf, Blip_Synth **synth, int srate) {
125 sndBlipOverflowWarned = 0;
127 *buf = new_Blip_Buffer();
129 blip_buffer_set_clock_rate(*buf, sound_get_effective_processor_speed());
130 /* Allow up to 1s of playback buffer - this allows us to cope with slowing
131 down to 2% of speed where a single Speccy frame generates just under 1s
132 of sound */
133 if (blip_buffer_set_sample_rate(*buf, srate, 1000) < 0) {
134 cprintf("\4ERROR: cannot init blip buffer!\n");
135 return -1;
138 *synth = new_Blip_Synth();
139 // output should be assigned first, so other calls will know the sampling rate
140 blip_synth_set_output(*synth, *buf);
142 blip_synth_set_volume(*synth, convert_volume(optSoundVolumeBeeper));
143 blip_buffer_set_bass_freq(*buf, speaker_type_info[speaker_type].bass);
144 blip_synth_set_treble_eq(*synth, speaker_type_info[speaker_type].treble);
146 return 0;
150 void deinitSound (void) {
151 if (playback_handle != NULL) {
152 snd_pcm_drop(playback_handle);
153 snd_pcm_close(playback_handle);
154 playback_handle = NULL;
155 sndSampleRate = 0;
156 sndUsing = 0;
158 delete_Blip_Synth(&left_beeper_synth);
159 delete_Blip_Synth(&right_beeper_synth);
161 delete_Blip_Synth(&ay_a_synth);
162 delete_Blip_Synth(&ay_b_synth);
163 delete_Blip_Synth(&ay_c_synth);
164 delete_Blip_Synth(&ay_a_synth_r);
165 delete_Blip_Synth(&ay_b_synth_r);
166 delete_Blip_Synth(&ay_c_synth_r);
168 delete_Blip_Buffer(&left_buf);
169 delete_Blip_Buffer(&right_buf);
174 #define ALSA_ISND_CALL(fcl,msg,...) do { \
175 int err; \
176 if ((err = (fcl)) < 0) { \
177 fprintf(stderr, msg, ##__VA_ARGS__, snd_strerror(err)); \
178 deinitSound(); \
179 return -1; \
181 } while (0)
184 static int initSoundHW (int samplerate) {
185 const int numchans = 2;
186 const int bytespersample = 2;
188 Blip_Synth **ay_left_synth = NULL;
189 Blip_Synth **ay_mid_synth = NULL;
190 Blip_Synth **ay_mid_synth_r = NULL;
191 Blip_Synth **ay_right_synth = NULL;
193 snd_pcm_hw_params_t *hw_params = NULL;
194 snd_pcm_sw_params_t *sw_params = NULL;
195 unsigned int sr;
196 snd_pcm_uframes_t buffer_size;
198 sndSampleRate = samplerate;
199 sndBytesPerSample = (bytespersample > 1 ? 2 : 1);
200 sndChannels = (numchans > 1 ? 2 : 1);
201 sndFrameSize = sndSampleRate/50;
202 sr = sndSampleRate;
204 memset(sndBuffer16, 0, sizeof(sndBuffer16));
205 memset(sndBuffer16AY, 0, sizeof(sndBuffer16AY));
207 if (speaker_type < 0 || speaker_type > SOUND_FILTER_MAX_VALUE) speaker_type = SOUND_FILTER_DEFAULT;
209 sndBeeperLastSubVol = 0;
210 sndOldVal = 0;
211 sndBufFillPos = 0;
212 sndBufPlayPos = 0;
213 sndUsing = 0;
214 sndAYChangeCount = 0;
215 sndAYJustReset = 0;
216 buffer_size = sndFrameSize*SND_BUFFERS_IN_RING;
218 ALSA_ISND_CALL(snd_pcm_open(&playback_handle, alsaDev, SND_PCM_STREAM_PLAYBACK, 0), "cannot open audio device %s (%s)\n", alsaDev);
219 ALSA_ISND_CALL(snd_pcm_hw_params_malloc(&hw_params), "cannot allocate hardware parameter structure (%s)\n");
220 ALSA_ISND_CALL(snd_pcm_hw_params_any(playback_handle, hw_params), "cannot initialize hardware parameter structure (%s)\n");
221 ALSA_ISND_CALL(snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "cannot set access type (%s)\n");
222 ALSA_ISND_CALL(snd_pcm_hw_params_set_format(playback_handle, hw_params, sndBytesPerSample==1?SND_PCM_FORMAT_S8:SND_PCM_FORMAT_S16_LE), "cannot set sample format (%s)\n");
223 ALSA_ISND_CALL(snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &sr, 0), "cannot set sample rate (%s)\n");
224 ALSA_ISND_CALL(snd_pcm_hw_params_set_buffer_size_near(playback_handle, hw_params, &buffer_size), "cannot set buffer size (%s)\n");
225 cprintf("real soundcard sample rate: %u\nsound buffer sizes (render/real): %d/%d\n", sr, sndFrameSize*SND_BUFFERS_IN_RING, (int)buffer_size);
226 //printf("sample rate: %u\n", sr);
227 sndSampleRate = sr;
228 sndFrameSize = sndSampleRate/50;
229 ALSA_ISND_CALL(snd_pcm_hw_params_set_channels(playback_handle, hw_params, sndChannels), "cannot set channel count (%s)\n");
230 ALSA_ISND_CALL(snd_pcm_hw_params(playback_handle, hw_params), "cannot set parameters (%s)\n");
231 snd_pcm_hw_params_free(hw_params);
233 ALSA_ISND_CALL(snd_pcm_sw_params_malloc(&sw_params), "cannot allocate software parameters structure (%s)\n");
234 ALSA_ISND_CALL(snd_pcm_sw_params_current(playback_handle, sw_params), "cannot initialize software parameters structure (%s)\n");
235 ALSA_ISND_CALL(snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, sndFrameSize), "cannot set minimum available count (%s)\n");
236 ALSA_ISND_CALL(snd_pcm_sw_params_set_start_threshold(playback_handle, sw_params, 0U), "cannot set start mode (%s)\n");
237 ALSA_ISND_CALL(snd_pcm_sw_params(playback_handle, sw_params), "cannot set software parameters (%s)\n");
238 ALSA_ISND_CALL(snd_pcm_nonblock(playback_handle, 0), "cannot set blocking mode (%s)\n");
239 ALSA_ISND_CALL(snd_pcm_prepare(playback_handle), "cannot prepare audio interface for use (%s)\n");
241 sndUsing = 1;
243 if (sound_init_blip(&left_buf, &left_beeper_synth, sndSampleRate) != 0) { deinitSound(); return -1; }
244 if (sound_init_blip(&right_buf, &right_beeper_synth, sndSampleRate) != 0) { deinitSound(); return -1; }
246 const double treble = speaker_type_info[speaker_type].treble;
248 ay_a_synth = new_Blip_Synth();
249 blip_synth_set_volume(ay_a_synth, convert_volume(optSoundVolumeAY));
250 blip_synth_set_treble_eq(ay_a_synth, treble);
252 ay_b_synth = new_Blip_Synth();
253 blip_synth_set_volume(ay_b_synth, convert_volume(optSoundVolumeAY));
254 blip_synth_set_treble_eq(ay_b_synth, treble);
256 ay_c_synth = new_Blip_Synth();
257 blip_synth_set_volume(ay_c_synth, convert_volume(optSoundVolumeAY));
258 blip_synth_set_treble_eq(ay_c_synth, treble);
260 ay_a_synth_r = NULL;
261 ay_b_synth_r = NULL;
262 ay_c_synth_r = NULL;
264 if (sound_stereo_ay < 0 || sound_stereo_ay > 2) sound_stereo_ay = SOUND_STEREO_AY_ABC;
266 if (sound_stereo_ay != SOUND_STEREO_AY_NONE) {
267 /* attach the Blip_Synth's we've already created as appropriate, and
268 * create one more Blip_Synth for the middle channel's right buffer */
269 if (sound_stereo_ay == SOUND_STEREO_AY_ACB) {
270 ay_left_synth = &ay_a_synth;
271 ay_mid_synth = &ay_c_synth;
272 ay_mid_synth_r = &ay_c_synth_r;
273 ay_right_synth = &ay_b_synth;
274 } else if (sound_stereo_ay == SOUND_STEREO_AY_ABC) {
275 sound_stereo_ay = SOUND_STEREO_AY_ABC;
276 ay_left_synth = &ay_a_synth;
277 ay_mid_synth = &ay_b_synth;
278 ay_mid_synth_r = &ay_b_synth_r;
279 ay_right_synth = &ay_c_synth;
282 blip_synth_set_output(*ay_left_synth, left_buf);
283 blip_synth_set_output(*ay_mid_synth, left_buf);
284 blip_synth_set_output(*ay_right_synth, right_buf);
286 *ay_mid_synth_r = new_Blip_Synth();
287 blip_synth_set_volume(*ay_mid_synth_r, convert_volume(optSoundVolumeAY));
288 blip_synth_set_output(*ay_mid_synth_r, right_buf);
289 blip_synth_set_treble_eq(*ay_mid_synth_r, treble);
290 } else {
291 blip_synth_set_output(ay_a_synth, left_buf);
292 blip_synth_set_output(ay_b_synth, left_buf);
293 blip_synth_set_output(ay_c_synth, left_buf);
296 return 0;
300 int initSound (void) {
301 const int srates[2] = {48000, 44100};
302 for (unsigned f = 0; f < 2; ++f) {
303 alsaDev = "default";
304 if (initSoundHW(srates[f]) == 0) return 0;
305 alsaDev = "plug:default";
306 if (initSoundHW(srates[f]) == 0) return 0;
308 playback_handle = NULL;
309 sndSampleRate = 0;
310 sndUsing = 0;
311 return -1;
315 int soundGetAYStereo (void) {
316 return (int)sound_stereo_ay;
320 void soundSetAYStereo (int mode) {
321 if (mode < 0 || mode > SOUND_STEREO_AY_ABC) mode = SOUND_STEREO_AY_ABC;
322 if (sound_stereo_ay != (unsigned)mode) {
323 sound_stereo_ay = (unsigned)mode;
324 if (sndUsing) {
325 deinitSound();
326 initSound();
332 void soundApplyNewVolumes (void) {
333 if (left_beeper_synth) blip_synth_set_volume(left_beeper_synth, convert_volume(optSoundVolumeBeeper));
334 if (right_beeper_synth) blip_synth_set_volume(right_beeper_synth, convert_volume(optSoundVolumeBeeper));
336 if (ay_a_synth) blip_synth_set_volume(ay_a_synth, convert_volume(optSoundVolumeAY));
337 if (ay_b_synth) blip_synth_set_volume(ay_b_synth, convert_volume(optSoundVolumeAY));
338 if (ay_c_synth) blip_synth_set_volume(ay_c_synth, convert_volume(optSoundVolumeAY));
339 if (ay_a_synth_r) blip_synth_set_volume(ay_a_synth_r, convert_volume(optSoundVolumeAY));
340 if (ay_b_synth_r) blip_synth_set_volume(ay_b_synth_r, convert_volume(optSoundVolumeAY));
341 if (ay_c_synth_r) blip_synth_set_volume(ay_c_synth_r, convert_volume(optSoundVolumeAY));
345 void soundFullRestart (void) {
346 if (sndUsing) {
347 deinitSound();
348 initSound();
353 int soundGetFilter (void) {
354 return (int)speaker_type;
358 void soundSetFilter (int mode) {
359 //FIXME: it's not the best way to do it...
360 if (mode < 0 || mode > SOUND_FILTER_MAX_VALUE) mode = SOUND_FILTER_DEFAULT;
361 if (speaker_type != (unsigned)mode) {
362 speaker_type = (unsigned)mode;
363 if (sndUsing) {
364 deinitSound();
365 initSound();
371 // ////////////////////////////////////////////////////////////////////////// //
372 // AY-8912 emulator
374 static unsigned int ay_tone_levels[16];
376 static unsigned int ay_tone_tick[3], ay_tone_high[3], ay_noise_tick;
377 static unsigned int ay_tone_cycles, ay_env_cycles;
378 static unsigned int ay_env_internal_tick, ay_env_tick;
379 static unsigned int ay_tone_period[3], ay_noise_period, ay_env_period;
381 /* local copy of the AY registers */
382 static uint8_t ay_registers[16];
385 /* bitmasks for envelope */
386 #define AY_ENV_CONT (8)
387 #define AY_ENV_ATTACK (4)
388 #define AY_ENV_ALT (2)
389 #define AY_ENV_HOLD (1)
391 /* the AY steps down the external clock by 16 for tone and noise generators */
392 #define AY_CLOCK_DIVISOR (16)
393 /* all Spectrum models and clones with an AY seem to count down the
394 master clock by 2 to drive the AY */
395 #define AY_CLOCK_RATIO (2)
398 static void ay_init (void) {
399 /* AY output doesn't match the claimed levels; these levels are based
400 * on the measurements posted to comp.sys.sinclair in Dec 2001 by
401 * Matthew Westcott, adjusted as I described in a followup to his post,
402 * then scaled to 0..0xffff.
404 const int levels[16] = {
405 0x0000, 0x0385, 0x053D, 0x0770,
406 0x0AD7, 0x0FD5, 0x15B0, 0x230C,
407 0x2B4C, 0x43C1, 0x5A4B, 0x732F,
408 0x9204, 0xAFF1, 0xD921, 0xFFFF
411 /* scale the values down to fit */
412 for (unsigned f = 0; f < 16; ++f) ay_tone_levels[f] = (levels[f]*AMPL_AY_TONE+0x8000)/0xffff;
414 ay_noise_tick = ay_noise_period = 0;
415 ay_env_internal_tick = ay_env_tick = ay_env_period = 0;
416 ay_tone_cycles = ay_env_cycles = 0;
417 for (unsigned f = 0; f < 3; ++f) { ay_tone_tick[f] = ay_tone_high[f] = 0; ay_tone_period[f] = 1; }
421 static inline void ay_do_tone (const int level, const unsigned int tone_count, int *var, const int chan) {
422 *var = 0;
423 ay_tone_tick[chan] += tone_count;
424 if (ay_tone_tick[chan] >= ay_tone_period[chan]) {
425 ay_tone_tick[chan] -= ay_tone_period[chan];
426 ay_tone_high[chan] = !ay_tone_high[chan];
428 if (level) {
429 if (ay_tone_high[chan]) *var = level; else *var = 0;
434 static void ay_mix_sound (void) {
435 static int rng = 1;
436 static int noise_toggle = 0;
437 static int env_first = 1, env_rev = 0, env_counter = 15;
438 int tone_level[3];
439 int mixer, envshape;
440 int g, level;
441 int f;
442 SndAYChanges *change_ptr = sndAYChanges;
443 int changes_left = sndAYChangeCount;
444 int reg, r;
445 int chan1, chan2, chan3;
446 int last_chan1 = 0, last_chan2 = 0, last_chan3 = 0;
447 unsigned int tone_count, noise_count;
449 /* If no AY chip, don't produce any AY sound (!) */
450 if (!optSoundAY) return;
452 for (f = 0; f < machineInfo.tsperframe; f += AY_CLOCK_DIVISOR*AY_CLOCK_RATIO) {
453 /* update ay registers */
454 while (changes_left && f >= change_ptr->tstate) {
455 reg = change_ptr->reg;
456 ay_registers[reg] = change_ptr->val;
457 ++change_ptr;
458 --changes_left;
460 /* fix things as needed for some register changes */
461 switch (reg) {
462 case 0: case 1: case 2: case 3: case 4: case 5:
463 r = reg>>1;
464 /* a zero-len period is the same as 1 */
465 ay_tone_period[r] = (ay_registers[reg&(~1)]|(ay_registers[reg|1]&15)<<8);
466 if (!ay_tone_period[r]) ++ay_tone_period[r];
467 /* important to get this right, otherwise e.g. Ghouls 'n' Ghosts
468 * has really scratchy, horrible-sounding vibrato
470 if (ay_tone_tick[r] >= ay_tone_period[r]*2) ay_tone_tick[r] %= ay_tone_period[r]*2;
471 break;
472 case 6:
473 ay_noise_tick = 0;
474 ay_noise_period = (ay_registers[reg]&31);
475 break;
476 case 11: case 12:
477 ay_env_period = ay_registers[11]|(ay_registers[12]<<8);
478 break;
479 case 13:
480 ay_env_internal_tick = ay_env_tick = ay_env_cycles = 0;
481 env_first = 1;
482 env_rev = 0;
483 env_counter = (ay_registers[13]&AY_ENV_ATTACK ? 0 : 15);
484 break;
488 /* the tone level if no enveloping is being used */
489 for (g = 0; g < 3; ++g) tone_level[g] = ay_tone_levels[ay_registers[8+g]&15];
491 /* envelope */
492 envshape = ay_registers[13];
493 level = ay_tone_levels[env_counter];
495 for (g = 0; g < 3; ++g) if (ay_registers[8+g]&16) tone_level[g] = level;
497 /* envelope output counter gets incr'd every 16 AY cycles */
498 ay_env_cycles += AY_CLOCK_DIVISOR;
499 noise_count = 0;
500 while (ay_env_cycles >= 16) {
501 ay_env_cycles -= 16;
502 ++noise_count;
503 ++ay_env_tick;
504 while (ay_env_tick >= ay_env_period) {
505 ay_env_tick -= ay_env_period;
507 /* do a 1/16th-of-period incr/decr if needed */
508 if (env_first || ((envshape&AY_ENV_CONT) && !(envshape&AY_ENV_HOLD))) {
509 if (env_rev) {
510 env_counter -= (envshape&AY_ENV_ATTACK ? 1 : -1);
511 } else {
512 env_counter += (envshape&AY_ENV_ATTACK ? 1 : -1);
514 if (env_counter < 0) env_counter = 0;
515 if (env_counter > 15) env_counter = 15;
518 ++ay_env_internal_tick;
519 while (ay_env_internal_tick >= 16) {
520 ay_env_internal_tick -= 16;
522 /* end of cycle */
523 if (!(envshape&AY_ENV_CONT)) {
524 env_counter = 0;
525 } else {
526 if (envshape&AY_ENV_HOLD) {
527 if (env_first && (envshape&AY_ENV_ALT)) env_counter = (env_counter ? 0 : 15);
528 } else {
529 /* non-hold */
530 if (envshape&AY_ENV_ALT) {
531 env_rev = !env_rev;
532 } else {
533 env_counter = (envshape&AY_ENV_ATTACK ? 0 : 15);
538 env_first = 0;
541 /* don't keep trying if period is zero */
542 if (!ay_env_period) break;
546 /* generate tone+noise... or neither
547 * (if no tone/noise is selected, the chip just shoves the level out unmodified; this is used by some sample-playing stuff)
549 chan1 = tone_level[0];
550 chan2 = tone_level[1];
551 chan3 = tone_level[2];
552 mixer = ay_registers[7];
554 ay_tone_cycles += AY_CLOCK_DIVISOR;
555 tone_count = ay_tone_cycles>>3;
556 ay_tone_cycles &= 7;
558 if ((mixer&1) == 0) {
559 level = chan1;
560 ay_do_tone(level, tone_count, &chan1, 0);
562 if ((mixer&0x08) == 0 && noise_toggle) chan1 = 0;
564 if ((mixer&2) == 0) {
565 level = chan2;
566 ay_do_tone(level, tone_count, &chan2, 1);
568 if ((mixer&0x10) == 0 && noise_toggle) chan2 = 0;
570 if ((mixer&4) == 0) {
571 level = chan3;
572 ay_do_tone(level, tone_count, &chan3, 2);
574 if ((mixer&0x20) == 0 && noise_toggle) chan3 = 0;
576 if (last_chan1 != chan1) {
577 blip_synth_update(ay_a_synth, f, chan1);
578 if (ay_a_synth_r) blip_synth_update(ay_a_synth_r, f, chan1);
579 last_chan1 = chan1;
582 if (last_chan2 != chan2) {
583 blip_synth_update(ay_b_synth, f, chan2);
584 if (ay_b_synth_r) blip_synth_update(ay_b_synth_r, f, chan2);
585 last_chan2 = chan2;
588 if (last_chan3 != chan3) {
589 blip_synth_update(ay_c_synth, f, chan3);
590 if (ay_c_synth_r) blip_synth_update(ay_c_synth_r, f, chan3);
591 last_chan3 = chan3;
594 /* update noise RNG/filter */
595 ay_noise_tick += noise_count;
596 while (ay_noise_tick >= ay_noise_period) {
597 ay_noise_tick -= ay_noise_period;
599 if ((rng&1)^(rng&2 ? 1 : 0)) noise_toggle = !noise_toggle;
601 /* rng is 17-bit shift reg, bit 0 is output; input is bit 0 xor bit 3 */
602 if (rng&1) rng ^= 0x24000;
603 rng >>= 1;
605 /* don't keep trying if period is zero */
606 if (!ay_noise_period) break;
612 /* don't make the change immediately; record it for later,
613 * to be made by `soundEndFrame()` (via `ay_mix_sound()`)
615 void soundAYWrite (const int reg, const int val, int now) {
616 if (sndAYChangeCount < MAX_AY_CHANGES) {
617 sndAYChanges[sndAYChangeCount].tstate = now;
618 sndAYChanges[sndAYChangeCount].reg = (reg&15);
619 sndAYChanges[sndAYChangeCount].val = val&0xffu;
620 ++sndAYChangeCount;
621 sndAYJustReset = 0;
626 void soundAYResetRegisters (void) {
627 if (!sndAYJustReset) {
628 sndAYChangeCount = 0;
629 for (unsigned f = 0; f < 16; ++f) soundAYWrite(f, 0, 0);
630 for (unsigned f = 0; f < 3; ++f) ay_tone_high[f] = 0;
631 ay_tone_cycles = ay_env_cycles = 0;
632 sndAYJustReset = 1;
637 /* no need to call this initially, but should be called on reset otherwise */
638 void soundAYReset (void) {
639 /* recalculate timings based on new machines ay clock */
640 ay_init();
641 soundAYResetRegisters();
645 // ////////////////////////////////////////////////////////////////////////// //
646 // beeper emulator
648 void soundBeeper (int on, int at_tstates) {
649 const int beeper_ampl[4] = { 0, AMPL_TAPE, AMPL_BEEPER, AMPL_BEEPER+AMPL_TAPE };
650 if (sndUsing) {
652 if (tape_is_playing()) {
653 // timex machines have no loading noise
654 if (!settings_current.sound_load || machine_current->timex) on = on&0x02;
655 } else {
656 // ULA book says that MIC only isn't enough to drive the speaker as output voltage is below the 1.4v threshold
657 if (on == 1) on = 0;
660 int val = beeper_ampl[(optSoundBeeper ? on&3 : 0)];
661 blip_synth_update(left_beeper_synth, at_tstates, val);
662 if (sound_stereo_ay != SOUND_STEREO_AY_NONE) {
663 blip_synth_update(right_beeper_synth, at_tstates, val);
669 void soundSilenceCurFrame (void) {
670 memset(sndBuffer16+sndBufFillPos, 0, sndFrameSize*sndChannels*sndBytesPerSample);
671 soundAYResetRegisters();
675 static inline int sndNextBufPlayPos (void) {
676 int res = sndBufPlayPos+sndFrameSize*sndChannels;
677 if (res/sndFrameSize*sndChannels >= SND_BUFFERS_IN_RING) res = 0;
678 return res;
682 static inline int sndNextBufFillPos (void) {
683 int res = sndBufFillPos+sndFrameSize*sndChannels;
684 if (res/sndFrameSize*sndChannels >= SND_BUFFERS_IN_RING) res = 0;
685 return res;
689 void soundEndFrame (void) {
690 if (!sndUsing) return;
692 /* overlay AY sound */
693 ay_mix_sound();
695 blip_buffer_end_frame(left_buf, machineInfo.tsperframe);
697 int16_t *samples = sndBuffer16+sndBufFillPos;
698 uint32_t count;
700 if (sound_stereo_ay != SOUND_STEREO_AY_NONE) {
701 blip_buffer_end_frame(right_buf, machineInfo.tsperframe);
702 /* read left channel into even samples, right channel into odd samples: LRLRLRLRLR... */
703 /* note that we setup the synths with the same params, so they are always in sync */
704 count = blip_buffer_read_samples(left_buf, samples, sndFrameSize, BLIP_READ_INTERLEAVE);
705 blip_buffer_read_samples(right_buf, samples+1, count, 1);
706 } else {
707 count = blip_buffer_read_samples(left_buf, samples, sndFrameSize, BLIP_READ_FAKE_STEREO);
711 k8: the emulator doesn't consume the whole buffer (this seems to be my rounding bug).
712 the result of that is buffer accumulating samples, and
713 it will eventually overflow, causing memory corruption.
714 so just forcefully clear the buffer, dropping all samples we didn't used on this frame.
715 it seems that sometimes there is just one extra sample left, but
716 this causes memory corruption after running the emu for ~40 minutes.
719 // warn if something is VERY wrong
720 if (!sndBlipOverflowWarned && blip_buffer_samples_avail(left_buf) >= sndFrameSize/32) {
721 sndBlipOverflowWarned = 1;
722 cprintf("WARNING! BlipBuffer overflowed by %d frames out of %d; the sound will be wildely distorted!\n",
723 (int)blip_buffer_samples_avail(left_buf), (int) sndFrameSize);
726 //fprintf(stderr, "*** count=%d; framesize=%d; avail=%d\n", (int)count, sndFrameSize, (int)blip_buffer_samples_avail(left_buf));
728 // remove rest of the samples, we don't need 'em
729 blip_buffer_remove_samples(left_buf, blip_buffer_samples_avail(left_buf));
730 if (sound_stereo_ay != SOUND_STEREO_AY_NONE) {
731 blip_buffer_remove_samples(right_buf, blip_buffer_samples_avail(right_buf));
734 sndAYChangeCount = 0;
735 sndAYJustReset = 0;
737 //fprintf(stderr, "count=%d; framesize=%d\n", (int)count, sndFrameSize);
739 if (count == 0) {
740 memset(sndBuffer16+sndBufFillPos, 0, sndFrameSize*sndChannels*sndBytesPerSample);
741 } else {
742 /* fill frame with the last rendered byte */
743 /* k8: this is wrong, but meh... */
744 int16_t *sptr = samples+count*2;
745 while (count < sndFrameSize) {
746 sptr[0] = sptr[-2];
747 sptr[1] = sptr[-1];
748 sptr += 2;
749 ++count;
755 static inline void soundMoveToNewFrame (void) {
756 sndBufFillPos = sndNextBufFillPos();
760 // ////////////////////////////////////////////////////////////////////////// //
761 // low-level sound code
764 // <0: fail!
765 static int sndWriteSoundToCard (int silent) {
766 int err, res = 0;
768 if ((err = snd_pcm_writei(playback_handle, sndBuffer16+sndBufPlayPos, sndFrameSize)) < 0) {
769 res = -1;
770 if (!debuggerActive && !optPaused && (optSoundBeeper || optSoundAY)) {
771 if (err == -EPIPE) {
772 if (!silent) fprintf(stderr, "ALSA: underrun!\n");
773 } else {
774 if (!silent) fprintf(stderr, "ALSA: write failed (%s)\n", snd_strerror(err));
777 snd_pcm_recover(playback_handle, err, 1);
778 } else {
779 sndBufPlayPos = sndNextBufPlayPos();
782 return res;
786 void soundWrite (void) {
787 if (sndUsing) {
788 int err;
789 if (debuggerActive || optPaused) soundSilenceCurFrame();
790 #if 1
792 static int64_t mcsFrameEndWanted = 0;
793 int mcsInFrame = 20*1000;
794 static int pbsgen = 0;
795 if (mcsFrameEndWanted == 0) {
796 //fprintf(stderr, "initializing sound buffers...\n");
797 for (int f = 0; f <= SND_BUFFERS_IN_RING/2; ++f) {
798 soundSilenceCurFrame();
799 if ((err = snd_pcm_writei(playback_handle, sndBuffer16+sndBufPlayPos, sndFrameSize)) < 0) {
800 snd_pcm_recover(playback_handle, err, 1);
802 sndBufPlayPos = sndNextBufPlayPos();
804 mcsFrameEndWanted = timerGetMicroSeconds()+mcsInFrame;
805 } else {
806 int64_t mcsCurFrameEnd;
807 if (sndWriteSoundToCard(1) < 0) {
808 // ALSA underrun, do something
809 int cnt = 0, ofp = sndBufFillPos;
810 while (sndBufPlayPos != sndBufFillPos) {
811 ++cnt;
812 sndBufPlayPos = sndNextBufPlayPos();
814 sndBufPlayPos = ofp;
815 if (optSndSyncDebug) fprintf(stderr, "sndsync buffered: %d\n", cnt);
816 if (cnt < SND_BUFFERS_IN_RING/2) {
817 // out of prebuffered sound, generate some
818 pbsgen = SND_BUFFERS_IN_RING/2;
820 if (optSndSyncDebug) fprintf(stderr, "sndsync: %d\n", pbsgen);
821 sndWriteSoundToCard(0);
823 mcsCurFrameEnd = timerGetMicroSeconds();
824 mcsInFrame = (pbsgen > 0 ? 17 : 20)*1000-50;
825 if (pbsgen > 0) --pbsgen;
826 if (mcsCurFrameEnd > 0) {
827 int mcsSleep = (mcsFrameEndWanted-mcsCurFrameEnd);
828 if (mcsSleep > 0) {
829 // less than 20 ms
830 usleep(mcsSleep);
831 mcsFrameEndWanted += mcsInFrame;
832 } else {
833 if (optSndSyncDebug) fprintf(stderr, "sndsync: DESYNC! (%d)\n", mcsSleep);
834 mcsFrameEndWanted = mcsCurFrameEnd+mcsInFrame;
836 } else {
837 //FIXME
838 // reinit timer
839 if (optSndSyncDebug) fprintf(stderr, "sndsync: reinit timer\n");
840 timerReinit();
841 mcsFrameEndWanted = timerGetMicroSeconds()+mcsInFrame;
845 #else
846 if ((err = snd_pcm_wait(playback_handle, 20)) < 0) {
847 fprintf(stderr, "ALSA: wait failed (%s)\n", snd_strerror(err));
848 snd_pcm_recover(playback_handle, err, 1);
851 sndWriteSoundToCard(0);
852 #endif
854 soundMoveToNewFrame();
858 void soundSetUse (int on) {
859 if (playback_handle != NULL && sndSampleRate > 0) {
860 int err;
862 if (on) {
863 if (!sndUsing) {
864 sndUsing = 1;
865 soundMoveToNewFrame();
866 soundSilenceCurFrame();
867 if ((err = snd_pcm_prepare(playback_handle)) < 0) {
868 fprintf(stderr, "ALSA: prepare failed (%s)\n", snd_strerror(err));
869 snd_pcm_recover(playback_handle, err, 1);
872 } else {
873 if (sndUsing) {
874 soundMoveToNewFrame();
875 soundSilenceCurFrame();
876 if ((err = snd_pcm_drop(playback_handle)) < 0) {
877 fprintf(stderr, "ALSA: drop failed (%s)\n", snd_strerror(err));
878 //snd_pcm_recover(playback_handle, err, 1);
880 sndUsing = 0;
883 } else {
884 sndUsing = 0;
889 #else
890 int sndAllowUseToggle = 0;
893 int initSound (void) {
894 return -1;
898 void deinitSound (void) {
902 void soundBeeper (int on, int tstates) {
906 void soundEndFrame (void) {
907 sndAYChangeCount = 0;
908 sndAYJustReset = 0;
912 void soundWrite (void) {
916 void soundSetUse (int on) {
920 void soundSilenceCurFrame (void) {
921 sndAYChangeCount = 0;
922 sndAYJustReset = 0;
924 #endif