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"
28 #include "blipbuffer.h"
33 static int sndUsing
= 0;
34 static int sndBlipOverflowWarned
= 0;
37 int soundIsWorking (void) {
47 #define MAX_AY_CHANGES (32768)
49 static SndAYChanges sndAYChanges
[MAX_AY_CHANGES
];
50 static int sndAYChangeCount
= 0;
51 static int sndAYJustReset
= 0;
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
;
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
);
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
133 if (blip_buffer_set_sample_rate(*buf
, srate
, 1000) < 0) {
134 cprintf("\4ERROR: cannot init blip buffer!\n");
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
);
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
;
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 { \
176 if ((err = (fcl)) < 0) { \
177 fprintf(stderr, msg, ##__VA_ARGS__, snd_strerror(err)); \
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
;
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;
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;
214 sndAYChangeCount
= 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);
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");
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
);
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
);
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
);
300 int initSound (void) {
301 const int srates
[2] = {48000, 44100};
302 for (unsigned f
= 0; f
< 2; ++f
) {
304 if (initSoundHW(srates
[f
]) == 0) return 0;
305 alsaDev
= "plug:default";
306 if (initSoundHW(srates
[f
]) == 0) return 0;
308 playback_handle
= NULL
;
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
;
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) {
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
;
371 // ////////////////////////////////////////////////////////////////////////// //
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
) {
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
];
429 if (ay_tone_high
[chan
]) *var
= level
; else *var
= 0;
434 static void ay_mix_sound (void) {
436 static int noise_toggle
= 0;
437 static int env_first
= 1, env_rev
= 0, env_counter
= 15;
442 SndAYChanges
*change_ptr
= sndAYChanges
;
443 int changes_left
= sndAYChangeCount
;
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
;
460 /* fix things as needed for some register changes */
462 case 0: case 1: case 2: case 3: case 4: case 5:
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;
474 ay_noise_period
= (ay_registers
[reg
]&31);
477 ay_env_period
= ay_registers
[11]|(ay_registers
[12]<<8);
480 ay_env_internal_tick
= ay_env_tick
= ay_env_cycles
= 0;
483 env_counter
= (ay_registers
[13]&AY_ENV_ATTACK
? 0 : 15);
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];
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
;
500 while (ay_env_cycles
>= 16) {
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
))) {
510 env_counter
-= (envshape
&AY_ENV_ATTACK
? 1 : -1);
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;
523 if (!(envshape
&AY_ENV_CONT
)) {
526 if (envshape
&AY_ENV_HOLD
) {
527 if (env_first
&& (envshape
&AY_ENV_ALT
)) env_counter
= (env_counter
? 0 : 15);
530 if (envshape
&AY_ENV_ALT
) {
533 env_counter
= (envshape
&AY_ENV_ATTACK
? 0 : 15);
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;
558 if ((mixer
&1) == 0) {
560 ay_do_tone(level
, tone_count
, &chan1
, 0);
562 if ((mixer
&0x08) == 0 && noise_toggle
) chan1
= 0;
564 if ((mixer
&2) == 0) {
566 ay_do_tone(level
, tone_count
, &chan2
, 1);
568 if ((mixer
&0x10) == 0 && noise_toggle
) chan2
= 0;
570 if ((mixer
&4) == 0) {
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
);
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
);
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
);
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;
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
;
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;
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 */
641 soundAYResetRegisters();
645 // ////////////////////////////////////////////////////////////////////////// //
648 void soundBeeper (int on
, int at_tstates
) {
649 const int beeper_ampl
[4] = { 0, AMPL_TAPE
, AMPL_BEEPER
, AMPL_BEEPER
+AMPL_TAPE
};
652 if (tape_is_playing()) {
653 // timex machines have no loading noise
654 if (!settings_current.sound_load || machine_current->timex) on = on&0x02;
656 // ULA book says that MIC only isn't enough to drive the speaker as output voltage is below the 1.4v threshold
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;
682 static inline int sndNextBufFillPos (void) {
683 int res
= sndBufFillPos
+sndFrameSize
*sndChannels
;
684 if (res
/sndFrameSize
*sndChannels
>= SND_BUFFERS_IN_RING
) res
= 0;
689 void soundEndFrame (void) {
690 if (!sndUsing
) return;
692 /* overlay AY sound */
695 blip_buffer_end_frame(left_buf
, machineInfo
.tsperframe
);
697 int16_t *samples
= sndBuffer16
+sndBufFillPos
;
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);
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;
737 //fprintf(stderr, "count=%d; framesize=%d\n", (int)count, sndFrameSize);
740 memset(sndBuffer16
+sndBufFillPos
, 0, sndFrameSize
*sndChannels
*sndBytesPerSample
);
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
) {
755 static inline void soundMoveToNewFrame (void) {
756 sndBufFillPos
= sndNextBufFillPos();
760 // ////////////////////////////////////////////////////////////////////////// //
761 // low-level sound code
765 static int sndWriteSoundToCard (int silent
) {
768 if ((err
= snd_pcm_writei(playback_handle
, sndBuffer16
+sndBufPlayPos
, sndFrameSize
)) < 0) {
770 if (!debuggerActive
&& !optPaused
&& (optSoundBeeper
|| optSoundAY
)) {
772 if (!silent
) fprintf(stderr
, "ALSA: underrun!\n");
774 if (!silent
) fprintf(stderr
, "ALSA: write failed (%s)\n", snd_strerror(err
));
777 snd_pcm_recover(playback_handle
, err
, 1);
779 sndBufPlayPos
= sndNextBufPlayPos();
786 void soundWrite (void) {
789 if (debuggerActive
|| optPaused
) soundSilenceCurFrame();
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
;
806 int64_t mcsCurFrameEnd
;
807 if (sndWriteSoundToCard(1) < 0) {
808 // ALSA underrun, do something
809 int cnt
= 0, ofp
= sndBufFillPos
;
810 while (sndBufPlayPos
!= sndBufFillPos
) {
812 sndBufPlayPos
= sndNextBufPlayPos();
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
);
831 mcsFrameEndWanted
+= mcsInFrame
;
833 if (optSndSyncDebug
) fprintf(stderr
, "sndsync: DESYNC! (%d)\n", mcsSleep
);
834 mcsFrameEndWanted
= mcsCurFrameEnd
+mcsInFrame
;
839 if (optSndSyncDebug
) fprintf(stderr
, "sndsync: reinit timer\n");
841 mcsFrameEndWanted
= timerGetMicroSeconds()+mcsInFrame
;
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);
854 soundMoveToNewFrame();
858 void soundSetUse (int on
) {
859 if (playback_handle
!= NULL
&& sndSampleRate
> 0) {
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);
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);
890 int sndAllowUseToggle
= 0;
893 int initSound (void) {
898 void deinitSound (void) {
902 void soundBeeper (int on
, int tstates
) {
906 void soundEndFrame (void) {
907 sndAYChangeCount
= 0;
912 void soundWrite (void) {
916 void soundSetUse (int on
) {
920 void soundSilenceCurFrame (void) {
921 sndAYChangeCount
= 0;