1 /*
2  * sound.c - General code for the sound interface.
3  *
4  * Written by
5  *  Teemu Rantanen <tvr@cs.hut.fi>
6  *  Marco van den Heuvel <blackystardust68@yahoo.com>
7  *
8  * Resource and cmdline code by
9  *  Ettore Perazzoli <ettore@comm2000.it>
10  *
11  * This file is part of VICE, the Versatile Commodore Emulator.
12  * See README for copyright notice.
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2 of the License, or
17  *  (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27  *  02111-1307  USA.
28  *
29  */
30 
31 #include "vice.h"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <assert.h>
38 
39 #ifdef HAVE_STRINGS_H
40 #include <strings.h>
41 #endif
42 
43 #include "archdep.h"
44 #include "clkguard.h"
45 #include "cmdline.h"
46 #include "debug.h"
47 #include "fixpoint.h"
48 #include "lib.h"
49 #include "log.h"
50 #include "machine.h"
51 #include "maincpu.h"
52 #include "monitor.h"
53 #include "resources.h"
54 #include "sound.h"
55 #include "types.h"
56 #include "tick.h"
57 #include "uiapi.h"
58 #include "util.h"
59 #include "vsync.h"
60 #include "math.h"
61 #include "ui.h"
62 
63 
64 static log_t sound_log = LOG_ERR;
65 
66 /* ------------------------------------------------------------------------- */
67 
68 #ifndef TRUE
69 #define TRUE 1
70 #endif
71 
72 #ifndef FALSE
73 #define FALSE 0
74 #endif
75 
76 /* ------------------------------------------------------------------------- */
77 
78 typedef struct sound_register_devices_s {
79     char *name;
80     int (*init)(void);
81     int is_playback_device;
82 } sound_register_devices_t;
83 
84 /* This table is used to specify the order of inits of the playback and recording devices */
85 static sound_register_devices_t sound_register_devices[] = {
86 
87     /* the "native" platform specific drivers should come first, sorted by
88        priority (most wanted first) */
89 
90 #ifdef USE_PULSE
91     { "pulse", sound_init_pulse_device, SOUND_PLAYBACK_DEVICE },
92 #endif
93 #ifdef USE_ARTS
94     { "arts", sound_init_arts_device, SOUND_PLAYBACK_DEVICE },
95 #endif
96 #ifdef USE_ALSA
97     { "alsa", sound_init_alsa_device, SOUND_PLAYBACK_DEVICE },
98 #endif
99 #ifdef USE_COREAUDIO
100     { "coreaudio", sound_init_coreaudio_device, SOUND_PLAYBACK_DEVICE },
101 #endif
102 
103 /* Don't use the NetBSD/SUN sound driver for OpenBSD */
104 #if defined(HAVE_SYS_AUDIOIO_H) && !defined(__OpenBSD__)
105 #if defined(__NetBSD__)
106     { "netbsd", sound_init_sun_device, SOUND_PLAYBACK_DEVICE },
107 #else
108     /* Really? */
109     { "sun", sound_init_sun_device, SOUND_PLAYBACK_DEVICE },
110 #endif /* __NetBSD__*/
111 #endif /* HAVE_SYS_AUDIOIO_H */
112 
113 #ifdef WIN32_COMPILE
114 #ifdef USE_DXSOUND
115     { "dx", sound_init_dx_device, SOUND_PLAYBACK_DEVICE },
116 #endif
117 #if !defined(__XBOX__)
118     { "wmm", sound_init_wmm_device, SOUND_PLAYBACK_DEVICE },
119 #endif
120 #endif
121 
122 #if defined(__OS2__) && !defined(USE_SDLUI)
123     { "dart", sound_init_dart_device, SOUND_PLAYBACK_DEVICE },
124 #endif
125 
126 #ifdef BEOS_COMPILE
127     { "beos", sound_init_beos_device, SOUND_PLAYBACK_DEVICE },
128     { "bsp", sound_init_bsp_device, SOUND_PLAYBACK_DEVICE },
129 #endif
130 
131 #if defined(AMIGA_SUPPORT) && defined(HAVE_DEVICES_AHI_H)
132     { "ahi", sound_init_ahi_device, SOUND_PLAYBACK_DEVICE },
133 #endif
134 
135     /* SDL driver last, after all platform specific ones */
136 #ifdef USE_SDL_AUDIO
137     { "sdl", sound_init_sdl_device, SOUND_PLAYBACK_DEVICE },
138 #endif
139 
140     /* the dummy device acts as a "guard" against the drivers that create files,
141        since the list will be searched top-down, and the dummy driver always
142        works, no files will be created accidently */
143     { "dummy", sound_init_dummy_device, SOUND_PLAYBACK_DEVICE },
144 
145     { "fs", sound_init_fs_device, SOUND_RECORD_DEVICE },
146     { "dump", sound_init_dump_device, SOUND_RECORD_DEVICE },
147     { "wav", sound_init_wav_device, SOUND_RECORD_DEVICE },
148     { "voc", sound_init_voc_device, SOUND_RECORD_DEVICE },
149     { "iff", sound_init_iff_device, SOUND_RECORD_DEVICE },
150     { "aiff", sound_init_aiff_device, SOUND_RECORD_DEVICE },
151 
152 #ifdef USE_LAMEMP3
153     { "mp3", sound_init_mp3_device, SOUND_RECORD_DEVICE },
154 #endif
155 
156 #ifdef USE_FLAC
157     { "flac", sound_init_flac_device, SOUND_RECORD_DEVICE },
158 #endif
159 
160 #ifdef USE_VORBIS
161     { "ogg", sound_init_vorbis_device, SOUND_RECORD_DEVICE },
162 #endif
163 
164     { "soundmovie", sound_init_movie_device, SOUND_RECORD_DEVICE },
165     { NULL, NULL, 0 }
166 };
167 
168 /* ------------------------------------------------------------------------- */
169 
170 static uint16_t offset = 0;
171 
172 static sound_chip_t *sound_calls[SOUND_CHIPS_MAX];
173 
sound_chip_register(sound_chip_t * chip)174 uint16_t sound_chip_register(sound_chip_t *chip)
175 {
176     assert(chip != NULL);
177 
178     sound_calls[offset >> 5] = chip;
179     offset += 0x20;
180 
181     assert((offset >> 5) < SOUND_CHIPS_MAX);
182 
183     return offset - 0x20;
184 }
185 
186 /* ------------------------------------------------------------------------- */
187 
sound_machine_open(int chipno)188 static sound_t *sound_machine_open(int chipno)
189 {
190     sound_t *retval = NULL;
191     int i;
192 
193     for (i = 0; i < (offset >> 5); i++) {
194         if (sound_calls[i]->open) {
195             retval = sound_calls[i]->open(chipno);
196         }
197     }
198     return retval;
199 }
200 
sound_machine_init(sound_t * psid,int speed,int cycles_per_sec)201 static int sound_machine_init(sound_t *psid, int speed, int cycles_per_sec)
202 {
203     int retval = 1;
204     int i;
205 
206     for (i = 0; i < (offset >> 5); i++) {
207         if (sound_calls[i]->init) {
208             retval &= sound_calls[i]->init(psid, speed, cycles_per_sec);
209         }
210     }
211     return retval;
212 }
213 
sound_machine_close(sound_t * psid)214 static void sound_machine_close(sound_t *psid)
215 {
216     int i;
217 
218     for (i = 0; i < (offset >> 5); i++) {
219         if (sound_calls[i]->close) {
220             sound_calls[i]->close(psid);
221         }
222     }
223 }
224 
225 /*
226     There is some inconsistency about when the buffer should be overwritten and
227     when mixed. Usually it's overwritten by SID and other cycle based engines,
228     and mixed by non-cycle based engines. On pet unfortunately it is always
229     mixed (unless SID is enabled) resulting in looping and distorted sound. As
230     a quick bandaid the memset was added below. This should be really cleaned
231     up someday.
232 */
sound_machine_calculate_samples(sound_t ** psid,int16_t * pbuf,int nr,int soc,int scc,int * delta_t)233 static int sound_machine_calculate_samples(sound_t **psid, int16_t *pbuf, int nr, int soc, int scc, int *delta_t)
234 {
235     int i;
236     int temp;
237     int initial_delta_t = *delta_t;
238     int delta_t_for_other_chips;
239 
240     if (sound_calls[0]->cycle_based() || (!sound_calls[0]->cycle_based() && sound_calls[0]->chip_enabled)) {
241         temp = sound_calls[0]->calculate_samples(psid, pbuf, nr, soc, scc, delta_t);
242     } else {
243         memset(pbuf, 0, nr * sizeof(int16_t) * soc); /* FIXME: see above */
244         temp = nr;
245     }
246 
247     for (i = 1; i < (offset >> 5); i++) {
248         if (sound_calls[i]->chip_enabled) {
249             delta_t_for_other_chips = initial_delta_t;
250             sound_calls[i]->calculate_samples(psid, pbuf, temp, soc, scc, &delta_t_for_other_chips);
251         }
252     }
253     return temp;
254 }
255 
sound_machine_store(sound_t * psid,uint16_t addr,uint8_t val)256 static void sound_machine_store(sound_t *psid, uint16_t addr, uint8_t val)
257 {
258     if (sound_calls[addr >> 5]->store) {
259         sound_calls[addr >> 5]->store(psid, (uint16_t)(addr & 0x1f), val);
260     }
261 }
262 
sound_machine_read(sound_t * psid,uint16_t addr)263 static uint8_t sound_machine_read(sound_t *psid, uint16_t addr)
264 {
265     if (sound_calls[addr >> 5]->read) {
266         return sound_calls[addr >> 5]->read(psid, (uint16_t)(addr & 0x1f));
267     }
268     return 0;
269 }
270 
sound_machine_reset(sound_t * psid,CLOCK cpu_clk)271 static void sound_machine_reset(sound_t *psid, CLOCK cpu_clk)
272 {
273     int i;
274 
275     for (i = 0; i < (offset >> 5); i++) {
276         if (sound_calls[i]->reset) {
277             sound_calls[i]->reset(psid, cpu_clk);
278         }
279     }
280 }
281 
sound_machine_cycle_based(void)282 static int sound_machine_cycle_based(void)
283 {
284     int i;
285     int retval = 0;
286 
287     for (i = 0; i < (offset >> 5); i++) {
288         retval |= sound_calls[i]->cycle_based();
289     }
290     return retval;
291 }
292 
sound_machine_channels(void)293 static int sound_machine_channels(void)
294 {
295     int i;
296     int retval = 0;
297     int temp;
298 
299     for (i = 0; i < (offset >> 5); i++) {
300         temp = sound_calls[i]->channels();
301         if (temp > retval) {
302             retval = temp;
303         }
304     }
305     return retval;
306 }
307 
308 /* ------------------------------------------------------------------------- */
309 
310 /* Resource handling -- Added by Ettore 98-04-26.  */
311 
312 /* FIXME: We need sanity checks!  And do we really need all of these
313    `sound_close()' calls?  */
314 
315 static int playback_enabled;           /* app_resources.sound */
316 static int sample_rate;                /* app_resources.soundSampleRate */
317 static char *device_name = NULL;       /* app_resources.soundDeviceName */
318 static char *device_arg = NULL;        /* app_resources.soundDeviceArg */
319 static char *recorddevice_name = NULL; /* app_resources.soundDeviceName */
320 static char *recorddevice_arg = NULL;  /* app_resources.soundDeviceArg */
321 static int buffer_size;                /* app_resources.soundBufferSize */
322 static int suspend_time;               /* app_resources.soundSuspendTime */
323 static int volume;
324 static int amp;
325 static int fragment_size;
326 static int output_option;
327 
328 /* divisors for fragment size calculation */
329 static int fragment_divisor[] = {
330     32, /* 100ms / 32 = 0.625ms */
331     16, /* 100ms / 16 = 1.25ms */
332      8, /* 100ms / 8 = 2.5ms */
333      4, /* 100ms / 4 = 5ms */
334      2, /* 100ms / 2 = 10 ms */
335      1  /* 100ms / 1 = 20 ms, actually unused (since it is not practical) */
336 };
337 
338 static char *playback_devices_cmdline = NULL;
339 static char *record_devices_cmdline = NULL;
340 
341 /* I need this to serialize close_sound and enablesound/sound_open in
342    the OS/2 Multithreaded environment                              */
343 static int sdev_open = FALSE;
344 
345 /* I need this to serialize close_sound and enablesound/sound_open in
346    the OS/2 Multithreaded environment                              */
347 int sound_state_changed;
348 int sid_state_changed;
349 
350 /* Sample based or cycle based sound engine. */
351 static int cycle_based = 0;
352 
353 /* If a current playback device is used to control emulator timing */
354 static int sound_is_timing_source = FALSE;
355 
set_output_option(int val,void * param)356 static int set_output_option(int val, void *param)
357 {
358     switch (val) {
359         case SOUND_OUTPUT_SYSTEM:
360         case SOUND_OUTPUT_MONO:
361         case SOUND_OUTPUT_STEREO:
362             break;
363         default:
364             return -1;
365     }
366 
367     if (output_option != val) {
368         output_option = val;
369         sound_state_changed = TRUE;
370     }
371     return 0;
372 }
373 
set_playback_enabled(int value,void * param)374 static int set_playback_enabled(int value, void *param)
375 {
376     int val = value ? 1 : 0;
377 
378     if (val) {
379         vsync_disable_timer();
380     }
381 
382     playback_enabled = val;
383     sound_machine_enable(playback_enabled);
384     return 0;
385 }
386 
set_sample_rate(int val,void * param)387 static int set_sample_rate(int val, void *param)
388 {
389     if (val <= 0) {
390         return -1;
391     }
392 
393     sample_rate = val;
394     sound_state_changed = TRUE;
395     return 0;
396 }
397 
set_device_name(const char * val,void * param)398 static int set_device_name(const char *val, void *param)
399 {
400     if (!val || val[0] == '\0') {
401         /* Use the default sound device */
402         if (archdep_is_haiku() == 0) {
403             util_string_set(&device_name, "bsp");
404         } else {
405             util_string_set(&device_name, sound_register_devices[0].name);
406         }
407     } else {
408         util_string_set(&device_name, val);
409     }
410     sound_state_changed = TRUE;
411     return 0;
412 }
413 
set_device_arg(const char * val,void * param)414 static int set_device_arg(const char *val, void *param)
415 {
416     util_string_set(&device_arg, val);
417     sound_state_changed = TRUE;
418     return 0;
419 }
420 
set_recorddevice_name(const char * val,void * param)421 static int set_recorddevice_name(const char *val, void *param)
422 {
423     util_string_set(&recorddevice_name, val);
424     sound_state_changed = TRUE;
425     return 0;
426 }
427 
set_recorddevice_arg(const char * val,void * param)428 static int set_recorddevice_arg(const char *val, void *param)
429 {
430     util_string_set(&recorddevice_arg, val);
431     sound_state_changed = TRUE;
432     return 0;
433 }
434 
set_buffer_size(int val,void * param)435 static int set_buffer_size(int val, void *param)
436 {
437     if (val > 0) {
438         buffer_size = val;
439     } else {
440         if (machine_class == VICE_MACHINE_VSID) {
441             buffer_size = SOUND_SAMPLE_MAX_BUFFER_SIZE;
442         } else {
443             buffer_size = SOUND_SAMPLE_BUFFER_SIZE;
444         }
445     }
446 
447     sound_state_changed = TRUE;
448     return 0;
449 }
450 
set_fragment_size(int val,void * param)451 static int set_fragment_size(int val, void *param)
452 {
453     if (val < SOUND_FRAGMENT_VERY_SMALL) {
454         val = SOUND_FRAGMENT_VERY_SMALL;
455     } else if (val > SOUND_FRAGMENT_VERY_LARGE) {
456         val = SOUND_FRAGMENT_VERY_LARGE;
457     }
458     fragment_size = val;
459     sound_state_changed = TRUE;
460     return 0;
461 }
462 
set_suspend_time(int val,void * param)463 static int set_suspend_time(int val, void *param)
464 {
465     suspend_time = val;
466 
467     if (suspend_time < 0) {
468         suspend_time = 0;
469     }
470 
471     sound_state_changed = TRUE;
472     return 0;
473 }
474 
set_volume(int val,void * param)475 static int set_volume(int val, void *param)
476 {
477     volume = val;
478 
479     if (volume < 0) {
480         volume = 0;
481     }
482 
483     if (volume > 100) {
484         volume = 100;
485     }
486 
487     amp = (int)((exp((double)volume / 100.0 * log(2.0)) - 1.0) * 4096.0);
488 
489     ui_display_volume(volume);
490 
491     return 0;
492 }
493 
494 static const resource_string_t resources_string[] = {
495     { "SoundDeviceName", "", RES_EVENT_NO, NULL,
496       &device_name, set_device_name, NULL },
497     { "SoundDeviceArg", "", RES_EVENT_NO, NULL,
498       &device_arg, set_device_arg, NULL },
499     { "SoundRecordDeviceName", "", RES_EVENT_STRICT, (resource_value_t)"",
500       &recorddevice_name, set_recorddevice_name, NULL },
501     { "SoundRecordDeviceArg", "", RES_EVENT_NO, NULL,
502       &recorddevice_arg, set_recorddevice_arg, NULL },
503     RESOURCE_STRING_LIST_END
504 };
505 
506 static const resource_int_t resources_int[] = {
507     { "Sound", 1, RES_EVENT_SAME, NULL,
508       (void *)&playback_enabled, set_playback_enabled, NULL },
509     { "SoundSampleRate", SOUND_SAMPLE_RATE, RES_EVENT_NO, NULL,
510       (void *)&sample_rate, set_sample_rate, NULL },
511     { "SoundBufferSize", SOUND_SAMPLE_BUFFER_SIZE, RES_EVENT_NO, NULL,
512       (void *)&buffer_size, set_buffer_size, NULL },
513     { "SoundFragmentSize", SOUND_FRAGMENT_MEDIUM, RES_EVENT_NO, NULL,
514       (void *)&fragment_size, set_fragment_size, NULL },
515     { "SoundSuspendTime", 0, RES_EVENT_NO, NULL,
516       (void *)&suspend_time, set_suspend_time, NULL },
517     { "SoundVolume", 100, RES_EVENT_NO, NULL,
518       (void *)&volume, set_volume, NULL },
519     { "SoundOutput", ARCHDEP_SOUND_OUTPUT_MODE, RES_EVENT_NO, NULL,
520       (void *)&output_option, set_output_option, NULL },
521     RESOURCE_INT_LIST_END
522 };
523 
sound_resources_init(void)524 int sound_resources_init(void)
525 {
526     if (resources_register_string(resources_string) < 0) {
527         return -1;
528     }
529 
530     return resources_register_int(resources_int);
531 }
532 
sound_resources_shutdown(void)533 void sound_resources_shutdown(void)
534 {
535     lib_free(device_name);
536     lib_free(device_arg);
537     lib_free(recorddevice_name);
538     lib_free(recorddevice_arg);
539     lib_free(playback_devices_cmdline);
540     lib_free(record_devices_cmdline);
541 }
542 
543 /* ------------------------------------------------------------------------- */
544 
545 static const cmdline_option_t cmdline_options[] =
546 {
547     { "-sound", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
548       NULL, NULL, "Sound", (resource_value_t)1,
549       NULL, "Enable sound playback" },
550     { "+sound", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
551       NULL, NULL, "Sound", (resource_value_t)0,
552       NULL, "Disable sound playback" },
553     { "-soundrate", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
554       NULL, NULL, "SoundSampleRate", NULL,
555       "<value>", "Set sound sample rate to <value> Hz" },
556     { "-soundbufsize", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
557       NULL, NULL, "SoundBufferSize", NULL,
558       "<value>", "Set sound buffer size to <value> msec" },
559     { "-soundfragsize", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
560       NULL, NULL, "SoundFragmentSize", NULL,
561       "<value>", "Set sound fragment size (0: very small, 1: small, 2: medium, 3: large, 4: very large)" },
562     { "-soundoutput", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
563       NULL, NULL, "SoundOutput", NULL,
564       "<output mode>", "Sound output mode: (0: system decides mono/stereo, 1: always mono, 2: always stereo)" },
565     { "-soundsuspend", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
566       NULL, NULL, "SoundSuspendTime", NULL,
567       "<Seconds>", "Specify the pause interval when audio underflows (clicks) happen. 0 means no pause is done." },
568     { "-soundvolume", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
569       NULL, NULL, "SoundVolume", NULL,
570       "<Volume>", "Specify the sound volume (0..100)" },
571     CMDLINE_LIST_END
572 };
573 
574 static cmdline_option_t devs_cmdline_options[] =
575 {
576     { "-sounddev", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
577       NULL, NULL, "SoundDeviceName", NULL,
578       "<Name>", NULL },
579     { "-soundarg", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
580       NULL, NULL, "SoundDeviceArg", NULL,
581       "<args>", "Specify initialization parameters for sound driver" },
582     { "-soundrecdev", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
583       NULL, NULL, "SoundRecordDeviceName", NULL,
584       "<Name>", NULL },
585     { "-soundrecarg", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
586       NULL, NULL, "SoundRecordDeviceArg", NULL,
587       "<args>", "Specify initialization parameters for recording sound driver" },
588     CMDLINE_LIST_END
589 };
590 
sound_cmdline_options_init(void)591 int sound_cmdline_options_init(void)
592 {
593     int i;
594     int started_playback = 0;
595     int started_record = 0;
596     char *temp = NULL;
597 
598     if (cmdline_register_options(cmdline_options) < 0) {
599         return -1;
600     }
601 
602     playback_devices_cmdline = lib_strdup("Specify sound driver. (");
603     record_devices_cmdline = lib_strdup("Specify recording sound driver. (");
604 
605     for (i = 0; sound_register_devices[i].name; i++) {
606         if (sound_register_devices[i].is_playback_device) {
607             if (started_playback) {
608                 temp = util_concat(playback_devices_cmdline, "/", sound_register_devices[i].name, NULL);
609             } else {
610                 temp = util_concat(playback_devices_cmdline, sound_register_devices[i].name, NULL);
611                 started_playback = 1;
612             }
613             lib_free(playback_devices_cmdline);
614             playback_devices_cmdline = temp;
615         } else {
616             if (started_record) {
617                 temp = util_concat(record_devices_cmdline, "/", sound_register_devices[i].name, NULL);
618             } else {
619                 temp = util_concat(record_devices_cmdline, sound_register_devices[i].name, NULL);
620                 started_record = 1;
621             }
622             lib_free(record_devices_cmdline);
623             record_devices_cmdline = temp;
624         }
625     }
626     temp = util_concat(playback_devices_cmdline, ")", NULL);
627     lib_free(playback_devices_cmdline);
628     playback_devices_cmdline = temp;
629 
630     temp = util_concat(record_devices_cmdline, ")", NULL);
631     lib_free(record_devices_cmdline);
632     record_devices_cmdline = temp;
633 
634     devs_cmdline_options[0].description = playback_devices_cmdline;
635     devs_cmdline_options[2].description = record_devices_cmdline;
636 
637     return cmdline_register_options(devs_cmdline_options);
638 }
639 
640 /* ------------------------------------------------------------------------- */
641 
642 /* timing constants */
643 static unsigned int cycles_per_sec;
644 static unsigned int cycles_per_rfsh;
645 static double rfsh_per_sec;
646 
647 /* Speed in percent, tracks relative_speed from vsync.c */
648 static double speed_percent;
649 
650 /* Flag: Is warp mode enabled?  */
651 static int warp_mode_enabled;
652 
653 typedef struct {
654     /* Number of sound output channels */
655     int sound_output_channels;
656 
657     /* Number of sound chip channels (for multiple SIDs) */
658     int sound_chip_channels;
659 
660     /* sid itself */
661     sound_t *psid[SOUND_SIDS_MAX];
662 
663     /* number of clocks between each sample. used value */
664     soundclk_t clkstep;
665 
666     /* number of clocks between each sample. original value */
667     soundclk_t origclkstep;
668 
669     /* factor between those two clksteps */
670     soundclk_t clkfactor;
671 
672     /* time of last sample generated */
673     soundclk_t fclk;
674 
675     /* time of last write to sid. used for pdev->dump() */
676     CLOCK wclk;
677 
678     /* time of last call to sound_run_sound() */
679     CLOCK lastclk;
680 
681     /* sample buffer */
682     int16_t *buffer;
683 
684     /* sample buffer pointer */
685     int bufptr;
686 
687     /* pointer to playback device structure in use */
688     sound_device_t *playdev;
689 
690     /* pointer to playback device structure in use */
691     sound_device_t *recdev;
692 
693     /* number of samples in a fragment */
694     int fragsize;
695 
696     /* number of fragments in kernel buffer */
697     int fragnr;
698 
699     /* number of samples in kernel buffer */
700     int bufsize;
701 
702     /* is the device suspended? */
703     int issuspended;
704     int16_t lastsample[SOUND_CHANNELS_MAX];
705 } snddata_t;
706 
707 static snddata_t snddata;
708 
709 /* device registration code */
710 #define MAX_SOUND_DEVICES 24
711 
712 static sound_device_t *sound_devices[MAX_SOUND_DEVICES];
713 
714 static int sound_device_count = 0;
715 
sound_register_device(sound_device_t * pdevice)716 int sound_register_device(sound_device_t *pdevice)
717 {
718     if (sound_device_count < MAX_SOUND_DEVICES) {
719         sound_devices[sound_device_count] = pdevice;
720         sound_device_count++;
721     } else {
722         log_error(sound_log, "available sound devices exceed VICEs storage");
723     }
724 
725     return 0;
726 }
727 
sound_device_num(void)728 unsigned int sound_device_num(void)
729 {
730     return sound_device_count;
731 }
732 
sound_device_name(unsigned int num)733 const char *sound_device_name(unsigned int num)
734 {
735     return sound_devices[num]->name;
736 }
737 
738 
739 /* code to disable sid for a given number of seconds if needed */
740 static time_t disabletime;
741 
enablesound(void)742 static void enablesound(void)
743 {
744     time_t diff;
745     if (!disabletime) {
746         return;
747     }
748     diff = time(0) - disabletime;
749     if (diff < 0 || diff >= (time_t)suspend_time) {
750         disabletime = 0;
751     }
752 }
753 
754 /* close sid device and show error dialog */
sound_error(const char * msg)755 static int sound_error(const char *msg)
756 {
757     sound_close();
758 
759     if (console_mode || video_disabled_mode) {
760         log_message(sound_log, "%s", msg);
761     } else {
762         char *txt = lib_msprintf("Sound: %s", msg);
763         ui_error(txt);
764         lib_free(txt);
765     }
766 
767     playback_enabled = 0;
768 
769     return 1;
770 }
771 
772 static int16_t *temp_buffer = NULL;
773 static int temp_buffer_size = 0;
774 
realloc_buffer(int size)775 static int16_t *realloc_buffer(int size)
776 {
777     if (temp_buffer_size < size) {
778         temp_buffer = lib_realloc(temp_buffer, size);
779         if (temp_buffer) {
780             temp_buffer_size = size;
781             memset(temp_buffer, 0, size);
782         } else {
783             temp_buffer_size = 0;
784         }
785     }
786     return temp_buffer;
787 }
788 
789 /* Fill buffer with last sample.
790  rise  < 0 : attenuation
791  rise == 0 : constant value
792  rise  > 0 : gain
793 */
fill_buffer(int size,int rise)794 static void fill_buffer(int size, int rise)
795 {
796     int c, i;
797     int16_t *p;
798     double factor;
799 
800     p = realloc_buffer(size * sizeof(int16_t) * snddata.sound_output_channels);
801     if (!p) {
802         return;
803     }
804 
805     for (c = 0; c < snddata.sound_output_channels; c++) {
806         for (i = 0; i < size; i++) {
807             if (rise < 0) {
808                 factor = (double)(size - i) / size;
809             } else {
810                 if (rise > 0) {
811                     factor = (double)i / size;
812                 } else {
813                     factor = 1.0;
814                 }
815             }
816 
817             p[i * snddata.sound_output_channels + c] = (int16_t)(snddata.lastsample[c] * factor);
818         }
819     }
820 
821     i = snddata.playdev->write(p, size * snddata.sound_output_channels);
822     if (i) {
823         sound_error("write to sound device failed.");
824     }
825 }
826 
827 
828 /* open SID engine */
sid_open(void)829 static int sid_open(void)
830 {
831     int c;
832 
833     for (c = 0; c < snddata.sound_chip_channels; c++) {
834         if (!(snddata.psid[c] = sound_machine_open(c))) {
835             return sound_error("Cannot open SID engine");
836         }
837     }
838 
839     return 0;
840 }
841 
842 /* initialize SID engine */
sid_init(void)843 static int sid_init(void)
844 {
845     double speed_factor;
846     int c, speed;
847 
848     /* Special handling for cycle based as opposed to sample based sound
849        engines. reSID is cycle based. */
850     cycle_based = sound_machine_cycle_based();
851 
852     /* "No limit" doesn't make sense for cycle based sound engines,
853        which have a fixed sampling rate. */
854     speed_factor = speed_percent ? speed_percent : 100;
855     speed = sample_rate * 100 / speed_factor;
856 
857     for (c = 0; c < snddata.sound_chip_channels; c++) {
858         if (!sound_machine_init(snddata.psid[c], speed, cycles_per_sec)) {
859             return sound_error("Cannot initialize SID engine");
860         }
861     }
862 
863     snddata.clkstep = SOUNDCLK_CONSTANT(cycles_per_sec) / sample_rate;
864 
865     snddata.origclkstep = snddata.clkstep;
866     snddata.clkfactor = SOUNDCLK_CONSTANT(1.0);
867     snddata.fclk = SOUNDCLK_CONSTANT(maincpu_clk);
868     snddata.wclk = maincpu_clk;
869     snddata.lastclk = maincpu_clk;
870 
871     return 0;
872 }
873 
874 /* close SID engine */
sid_close(void)875 static void sid_close(void)
876 {
877     int c;
878     for (c = 0; c < snddata.sound_chip_channels; c++) {
879         if (snddata.psid[c]) {
880             sound_machine_close(snddata.psid[c]);
881             snddata.psid[c] = NULL;
882         }
883     }
884 }
885 
sound_get_psid(unsigned int channel)886 sound_t *sound_get_psid(unsigned int channel)
887 {
888     return snddata.psid[channel];
889 }
890 
891 /* open sound device */
sound_open(void)892 int sound_open(void)
893 {
894     int c, i, j;
895     int channels_cap;
896     int channels;
897     sound_device_t *pdev, *rdev;
898     char *playname, *recname;
899     char *playparam, *recparam;
900     char *err;
901     int speed;
902     int fragsize;
903     int fragnr;
904     double bufsize;
905 
906     if (suspend_time > 0 && disabletime) {
907         return 1;
908     }
909 
910     if (snddata.playdev) {
911         /*
912          * This can happen when loading a snapshot with multiple sids. Whilst fixing that is a good idea,
913          * this should be safe and simpler.
914          */
915         log_warning(sound_log, "ignoring sound_open when snddata.playdev is not NULL.");
916         return 0;
917     }
918 
919     /* Opening the sound device and initializing the sound engine
920        might take some time. */
921     vsync_suspend_speed_eval();
922 
923     /* Second SID. */
924     snddata.sound_chip_channels = sound_machine_channels();
925 
926     playname = device_name;
927     if (playname && playname[0] == '\0') {
928         playname = NULL;
929     }
930 
931     playparam = device_arg;
932     if (playparam && playparam[0] == '\0') {
933         playparam = NULL;
934     }
935 
936     recname = recorddevice_name;
937     if (recname && recname[0] == '\0') {
938         recname = NULL;
939     }
940 
941     recparam = recorddevice_arg;
942     if (recparam && recparam[0] == '\0') {
943         recparam = NULL;
944     }
945 
946     /* Calculate buffer size in seconds. */
947     bufsize = ((buffer_size < 1 || buffer_size > 1000)
948                ? SOUND_SAMPLE_BUFFER_SIZE : buffer_size) / 1000.0;
949     speed = (sample_rate < 8000 || sample_rate > 96000)
950             ? SOUND_SAMPLE_RATE : sample_rate;
951 
952     switch (output_option) {
953         case SOUND_OUTPUT_SYSTEM:
954         default:
955             channels = (snddata.sound_chip_channels >= 2) ? 2 : 1;
956             break;
957         case SOUND_OUTPUT_MONO:
958             channels = 1;
959             break;
960         case SOUND_OUTPUT_STEREO:
961             channels = 2;
962             break;
963     }
964 
965     /* find pdev */
966     for (i = 0; (pdev = sound_devices[i]); i++) {
967         if (!playname || (pdev->name && !strcasecmp(playname, pdev->name))) {
968             break;
969         }
970     }
971 
972     /* Calculate reasonable fragments. Target is 2 fragments per frame,
973      * which gives a reasonable number of fillable audio chunks to avoid
974      * ugly situation where a full frame refresh needs to occur before more
975      * audio is generated. It also improves the estimate of optimal frame
976      * length for vsync, which is closely tied to audio and uses the fragment
977      * information to calculate it. */
978     /* note: in practise it is actually better to use fragments that are as
979      *       small as possible, as that will allow the whole system to catch up
980      *       faster and compensate errors better. */
981     fragsize = speed / ((rfsh_per_sec < 1.0) ? 1 : ((int)rfsh_per_sec))
982                / fragment_divisor[fragment_size];
983     if (pdev) {
984         if (channels <= pdev->max_channels) {
985             fragsize *= channels;
986         }
987     }
988 
989     for (i = 1; 1 << i < fragsize; i++) {
990     }
991     fragsize = 1 << i;
992     fragnr = (int)((speed * bufsize + fragsize - 1) / fragsize);
993 
994     if (pdev) {
995 
996         snddata.playdev = pdev;
997         snddata.fragsize = fragsize;
998         snddata.fragnr = fragnr;
999         snddata.bufsize = fragsize * fragnr;
1000         snddata.bufptr = 0;
1001 
1002         if (pdev->init) {
1003             channels_cap = channels;
1004             if (pdev->init(playparam, &speed, &fragsize, &fragnr, &channels_cap)) {
1005                 err = lib_msprintf("initialization failed for device `%s'.", pdev->name);
1006                 sound_error(err);
1007                 lib_free(err);
1008                 return 1;
1009             }
1010             if (channels_cap != channels) {
1011                 if (output_option != SOUND_OUTPUT_MONO) {
1012                     log_warning(sound_log, "sound device lacks stereo capability, switching to mono output");
1013                 }
1014                 snddata.sound_output_channels = 1;
1015             } else {
1016                 snddata.sound_output_channels = channels;
1017             }
1018         }
1019         snddata.buffer = lib_malloc(snddata.bufsize * snddata.sound_output_channels * sizeof(int16_t));
1020         snddata.issuspended = 0;
1021 
1022         for (c = 0; c < snddata.sound_output_channels; c++) {
1023             snddata.lastsample[c] = 0;
1024         }
1025 
1026         log_message(sound_log,
1027                     "Opened device `%s', speed %dHz, fragment size %.2fms, buffer size %.2fms%s",
1028                     pdev->name,
1029                     speed,
1030                     (1000.0 * fragsize / speed),
1031                     (1000.0 * snddata.bufsize / speed),
1032                     snddata.sound_output_channels > 1 ? ", stereo" : "");
1033         sample_rate = speed;
1034 
1035         if (sid_open() != 0 || sid_init() != 0) {
1036             return 1;
1037         }
1038 
1039         sound_is_timing_source = pdev->is_timing_source ? TRUE : FALSE;
1040         sid_state_changed = FALSE;
1041 
1042         /* Fill up the sound hardware buffer. */
1043         if (pdev->bufferspace) {
1044             /* Fill to bufsize - fragsize. */
1045             j = pdev->bufferspace() - snddata.fragsize;
1046             if (j > 0) {
1047                 /* Whole fragments. */
1048                 j -= j % snddata.fragsize;
1049 
1050                 fill_buffer(j, 0);
1051             }
1052         }
1053     } else {
1054         err = lib_msprintf("device '%s' not found or not supported.", playname);
1055         sound_error(err);
1056         lib_free(err);
1057         return 1;
1058     }
1059 
1060     /* now the playback sound device is open */
1061     sdev_open = TRUE;
1062     sound_state_changed = FALSE;
1063 
1064     for (i = 0; (rdev = sound_devices[i]); i++) {
1065         if (recname && rdev->name && !strcasecmp(recname, rdev->name)) {
1066             break;
1067         }
1068     }
1069 
1070     if (recname && rdev == NULL) {
1071         ui_error("Recording device %s doesn't exist!", recname);
1072     }
1073 
1074     if (rdev) {
1075         if (rdev == pdev) {
1076             ui_error("Recording device must be different from playback device");
1077             resources_set_string("SoundRecordDeviceName", "");
1078             return 0;
1079         }
1080 
1081         if (rdev->bufferspace != NULL) {
1082             ui_error("Warning! Recording device %s seems to be a realtime device!");
1083         }
1084 
1085         if (rdev->init) {
1086             channels_cap = snddata.sound_output_channels;
1087             if (rdev->init(recparam, &speed, &fragsize, &fragnr, &channels_cap)) {
1088                 ui_error("initialization failed for device `%s'.", rdev->name);
1089                 resources_set_string("SoundRecordDeviceName", "");
1090                 return 0;
1091             }
1092 
1093             if (sample_rate != speed
1094                 || snddata.fragsize != fragsize
1095                 || snddata.fragnr != fragnr
1096                 || snddata.sound_output_channels != channels_cap) {
1097                 ui_error("The recording device doesn't support current sound parameters");
1098                 rdev->close();
1099                 resources_set_string("SoundRecordDeviceName", "");
1100             } else {
1101                 snddata.recdev = rdev;
1102                 log_message(sound_log, "Opened recording device device `%s'", rdev->name);
1103             }
1104         }
1105     }
1106     return 0;
1107 }
1108 
1109 /* close sid */
sound_close(void)1110 void sound_close(void)
1111 {
1112     if (snddata.playdev) {
1113         log_message(sound_log, "Closing device `%s'", snddata.playdev->name);
1114         if (snddata.playdev->close) {
1115             snddata.playdev->close();
1116         }
1117         snddata.playdev = NULL;
1118     }
1119 
1120     if (snddata.recdev) {
1121         log_message(sound_log, "Closing recording device `%s'", snddata.recdev->name);
1122         if (snddata.recdev->close) {
1123             snddata.recdev->close();
1124         }
1125         snddata.recdev = NULL;
1126     }
1127 
1128     sid_close();
1129 
1130     sdev_open = FALSE;
1131     sound_state_changed = FALSE;
1132     sound_is_timing_source = FALSE;
1133 
1134     lib_free(snddata.buffer);
1135     snddata.buffer = NULL;
1136     snddata.bufsize = 0;
1137 
1138     if (temp_buffer) {
1139         lib_free(temp_buffer);
1140         temp_buffer = NULL;
1141         temp_buffer_size = 0;
1142     }
1143 
1144     /* Closing the sound device might take some time, and displaying
1145        UI dialogs certainly does. */
1146     vsync_suspend_speed_eval();
1147 }
1148 
1149 /* run sid */
sound_run_sound(void)1150 static int sound_run_sound(void)
1151 {
1152 #if 0
1153     static int overflow_warning_count = 0;
1154 #endif
1155 
1156     int nr = 0;
1157     int i;
1158     int delta_t = 0;
1159     int16_t *bufferptr;
1160 
1161     /* XXX: implement the exact ... */
1162     if (!playback_enabled || (suspend_time > 0 && disabletime)) {
1163         return 1;
1164     }
1165 
1166     if (!snddata.playdev) {
1167         i = sound_open();
1168         if (i) {
1169             return i;
1170         }
1171     }
1172 
1173     /* Handling of cycle based sound engines. */
1174     if (cycle_based) {
1175         delta_t = maincpu_clk - snddata.lastclk;
1176         bufferptr = snddata.buffer + snddata.bufptr * snddata.sound_output_channels;
1177         nr = sound_machine_calculate_samples(snddata.psid,
1178                                              bufferptr,
1179                                              snddata.bufsize - snddata.bufptr,
1180                                              snddata.sound_output_channels,
1181                                              snddata.sound_chip_channels,
1182                                              &delta_t);
1183         if (delta_t) {
1184             sound_error("Sound buffer overflow (cycle based)");
1185             return -1;
1186 #if 0
1187             if (overflow_warning_count < 25) {
1188                 log_warning(sound_log, "%s", "Sound buffer overflow (cycle based)");
1189                 overflow_warning_count++;
1190             } else {
1191                 if (overflow_warning_count == 25) {
1192                     log_warning(sound_log, "Buffer overflow warning repeated 25 times, will now be ignored");
1193                     overflow_warning_count++;
1194                 }
1195             }
1196 #endif
1197         }
1198      } else {
1199          /* Handling of sample based sound engines. */
1200          nr = (int)((SOUNDCLK_CONSTANT(maincpu_clk) - snddata.fclk)
1201                     / snddata.clkstep);
1202          if (!nr) {
1203              return 0;
1204          }
1205          if (nr > snddata.bufsize - snddata.bufptr) {
1206              nr = snddata.bufsize - snddata.bufptr;
1207          }
1208          bufferptr = snddata.buffer + snddata.bufptr * snddata.sound_output_channels;
1209          sound_machine_calculate_samples(snddata.psid,
1210                                          bufferptr,
1211                                          nr,
1212                                          snddata.sound_output_channels,
1213                                          snddata.sound_chip_channels,
1214                                          &delta_t);
1215          snddata.fclk += nr * snddata.clkstep;
1216      }
1217 
1218      if (amp < 4096) {
1219          if (amp) {
1220              for (i = 0; i < (nr * snddata.sound_output_channels); i++) {
1221                  bufferptr[i] = bufferptr[i] * amp / 4096;
1222              }
1223          } else {
1224              memset(bufferptr, 0, nr * snddata.sound_output_channels * sizeof(int16_t));
1225          }
1226      }
1227 
1228     snddata.bufptr += nr;
1229     snddata.lastclk = maincpu_clk;
1230 
1231     return 0;
1232 }
1233 
1234 /* reset sid */
sound_reset(void)1235 void sound_reset(void)
1236 {
1237     int c;
1238 
1239     snddata.fclk = SOUNDCLK_CONSTANT(maincpu_clk);
1240     snddata.wclk = maincpu_clk;
1241     snddata.lastclk = maincpu_clk;
1242     snddata.bufptr = 0;         /* ugly hack! */
1243     for (c = 0; c < snddata.sound_chip_channels; c++) {
1244         if (snddata.psid[c]) {
1245             sound_machine_reset(snddata.psid[c], maincpu_clk);
1246         }
1247     }
1248 }
1249 
prevent_clk_overflow_callback(CLOCK sub,void * data)1250 static void prevent_clk_overflow_callback(CLOCK sub, void *data)
1251 {
1252     int c;
1253 
1254     snddata.lastclk -= sub;
1255     snddata.fclk -= SOUNDCLK_CONSTANT(sub);
1256     snddata.wclk -= sub;
1257     for (c = 0; c < snddata.sound_chip_channels; c++) {
1258         if (snddata.psid[c]) {
1259             sound_machine_prevent_clk_overflow(snddata.psid[c], sub);
1260         }
1261     }
1262 }
1263 
1264 /* flush all generated samples from buffer to sounddevice. */
sound_flush()1265 bool sound_flush()
1266 {
1267     const unsigned long max_block_ms = 5000; /* If sound write blocks this long, assume it's broken */
1268     const unsigned long block_warn_ms = 500; /* If sound write blocks at least this long before succeeding, log a warning */
1269 
1270     static unsigned long last_restart_tick = 0;
1271 
1272     int c, i, nr, space;
1273     char *state;
1274     bool slept = false;
1275     unsigned long first_block_tick = 0;
1276     unsigned long total_block_ms;
1277 
1278     if (!playback_enabled) {
1279         if (sdev_open) {
1280             sound_close();
1281         }
1282         goto done;
1283     }
1284 
1285     if (sound_state_changed) {
1286         if (sdev_open) {
1287             sound_close();
1288         }
1289         sound_state_changed = FALSE;
1290     }
1291 
1292     if (suspend_time > 0) {
1293         enablesound();
1294     }
1295     if (sound_run_sound()) {
1296         goto done;
1297     }
1298 
1299     if (sid_state_changed) {
1300         if (sid_init() != 0) {
1301             goto done;
1302         }
1303         sid_state_changed = FALSE;
1304     }
1305 
1306     if (warp_mode_enabled && snddata.recdev == NULL) {
1307         snddata.bufptr = 0;
1308         goto done;
1309     }
1310     sound_resume();
1311 
1312     if (snddata.playdev->flush) {
1313         state = sound_machine_dump_state(snddata.psid[0]);
1314         i = snddata.playdev->flush(state);
1315         lib_free(state);
1316         if (i) {
1317             sound_error("cannot flush.");
1318             goto done;
1319         }
1320     }
1321 
1322     /* Calculate the number of samples to flush - whole fragments. */
1323     nr = snddata.bufptr - snddata.bufptr % snddata.fragsize;
1324     if (!nr) {
1325         goto done;
1326     }
1327 
1328     /*
1329      * At this point we have to block until we have written at least one fragment.
1330      *
1331      * The 'push against the audio device' sync method depends on this.
1332      */
1333 
1334     while (!warp_mode_enabled) {
1335 
1336         if (snddata.playdev->bufferspace) {
1337             space = snddata.playdev->bufferspace();
1338         } else {
1339             /*
1340              * Blocking driver like simple pulse - write everything we have.
1341              * I'm not sure if this is the right thing to do, perhaps we should
1342              * only be writin a single fragment at time?
1343              */
1344             space = nr;
1345         }
1346 
1347         space -= space % snddata.fragsize;
1348 
1349         if (space) {
1350             if (nr > space) {
1351                 /* Write as much as we can */
1352                 nr = space;
1353             }
1354 
1355             /* Flush buffer, all channels are already mixed into it. */
1356             if (snddata.playdev->write(snddata.buffer, nr * snddata.sound_output_channels)) {
1357                 sound_error("write to sound device failed.");
1358                 goto done;
1359             }
1360 
1361             if (snddata.recdev) {
1362                 if (snddata.recdev->write(snddata.buffer, nr * snddata.sound_output_channels)) {
1363                     sound_error("write to sound device failed.");
1364                     goto done;
1365                 }
1366             }
1367 
1368             if (first_block_tick) {
1369                 total_block_ms = tick_delta(first_block_tick) / (tick_per_second() / 1000);
1370                 if (total_block_ms >= block_warn_ms) {
1371                     log_warning(sound_log, "Sound device write was blocked for %lums", total_block_ms);
1372                 }
1373 
1374                 /* not blocked anymore */
1375                 first_block_tick = 0;
1376             }
1377             break;
1378         }
1379 
1380         /* Haven't written yet, try again after a minimal sleep */
1381 
1382         if (!first_block_tick) {
1383             first_block_tick = tick_now();
1384         } else {
1385             total_block_ms = tick_delta(first_block_tick) / (tick_per_second() / 1000);
1386 
1387             if (total_block_ms >= max_block_ms) {
1388 
1389                 /*
1390                  * Sound device may have stalled and might benefit from a restart.
1391                  * But only try if we haven't tried a restart recently.
1392                  */
1393 
1394                 log_message(sound_log, "Writing to sound device still blocked after %lums", total_block_ms);
1395 
1396                 if (tick_delta(last_restart_tick) / (tick_per_second() / 1000) >= 2 * max_block_ms) {
1397                     log_message(sound_log, "Attempting restart");
1398                     sound_close();
1399                     last_restart_tick = tick_now();
1400                     first_block_tick = 0;
1401                     goto done;
1402                 }
1403 
1404                 log_message(sound_log, "Last restart is too recent, disabling sound.");
1405                 sound_error("Sound device stalled");
1406                 goto done;
1407             }
1408 
1409             /* More to write, try again after a minimal sleep */
1410             tick_sleep(tick_per_second() / 1000);
1411             slept = true;
1412         }
1413     }
1414 
1415     snddata.bufptr -= nr;
1416 
1417     /*
1418      * Move any incomplete fragments back to the start of the sample buffer
1419      */
1420 
1421     for (c = 0; c < snddata.sound_output_channels; c++) {
1422         snddata.lastsample[c] = snddata.buffer[(nr - 1) * snddata.sound_output_channels + c];
1423         for (i = 0; i < snddata.bufptr; i++) {
1424             snddata.buffer[i * snddata.sound_output_channels + c] =
1425                 snddata.buffer[(i + nr) * snddata.sound_output_channels + c];
1426         }
1427     }
1428 
1429 done:
1430 
1431     if (!slept) {
1432         mainlock_yield_once();
1433     }
1434 
1435     /*
1436      * If the sound device is not a timing source, then we need
1437      * the host to sleep to sync time with the emulator.
1438      */
1439 
1440     return !sound_is_timing_source;
1441 }
1442 
1443 /* suspend sid (eg. before pause) */
sound_suspend(void)1444 void sound_suspend(void)
1445 {
1446     if (!snddata.playdev) {
1447         return;
1448     }
1449 
1450     if (snddata.playdev->write && !snddata.issuspended
1451         && snddata.playdev->need_attenuation) {
1452         /* fill buffer, but avoid overwriting */
1453         if (!snddata.playdev->bufferspace
1454             || snddata.playdev->bufferspace() >= snddata.fragsize) {
1455             fill_buffer(snddata.fragsize, -1);
1456         } else {
1457             log_warning(sound_log, "Buffer full during suspend");
1458         }
1459         /* fill_buffer() can call sound_close() */
1460         if (!snddata.playdev) {
1461             return;
1462         }
1463     }
1464 
1465     if (snddata.playdev->suspend && !snddata.issuspended) {
1466         if (snddata.playdev->suspend()) {
1467             return;
1468         }
1469     }
1470     snddata.issuspended = 1;
1471 }
1472 
1473 /* resume sid */
sound_resume(void)1474 void sound_resume(void)
1475 {
1476     if (!snddata.playdev) {
1477         return;
1478     }
1479 
1480     if (snddata.issuspended) {
1481         if (snddata.playdev->resume) {
1482             snddata.issuspended = snddata.playdev->resume();
1483         } else {
1484             snddata.issuspended = 0;
1485         }
1486 
1487         if (snddata.playdev->write && !snddata.issuspended
1488             && snddata.playdev->need_attenuation) {
1489             fill_buffer(snddata.fragsize, 1);
1490         }
1491     }
1492 }
1493 
1494 /* set PAL/NTSC clock speed */
sound_set_machine_parameter(long clock_rate,long ticks_per_frame)1495 void sound_set_machine_parameter(long clock_rate, long ticks_per_frame)
1496 {
1497     sid_state_changed = TRUE;
1498 
1499     cycles_per_sec = (unsigned int)clock_rate;
1500     cycles_per_rfsh = (unsigned int)ticks_per_frame;
1501     rfsh_per_sec = (1.0 / ((double)cycles_per_rfsh / (double)cycles_per_sec));
1502 }
1503 
1504 /* initialize sid at program start -time */
sound_init(unsigned int clock_rate,unsigned int ticks_per_frame)1505 void sound_init(unsigned int clock_rate, unsigned int ticks_per_frame)
1506 {
1507     char *devlist, *tmplist;
1508     int i;
1509 
1510     sound_log = log_open("Sound");
1511 
1512     sound_state_changed = FALSE;
1513     sid_state_changed = FALSE;
1514 
1515     cycles_per_sec = clock_rate;
1516     cycles_per_rfsh = ticks_per_frame;
1517     rfsh_per_sec = (1.0 / ((double)cycles_per_rfsh / (double)cycles_per_sec));
1518 
1519     clk_guard_add_callback(maincpu_clk_guard, prevent_clk_overflow_callback,
1520                            NULL);
1521 
1522     devlist = lib_strdup("");
1523 
1524     for (i = 0; sound_register_devices[i].name; i++) {
1525         sound_register_devices[i].init();
1526         tmplist = lib_msprintf("%s %s", devlist, sound_register_devices[i].name);
1527         lib_free(devlist);
1528         devlist = tmplist;
1529     }
1530 
1531     log_message(sound_log, "Available sound devices:%s", devlist);
1532 
1533     lib_free(devlist);
1534 
1535     archdep_sound_enable_default_device_tracking();
1536 }
1537 
sound_sample_position(void)1538 long sound_sample_position(void)
1539 {
1540     return (snddata.clkstep == 0)
1541            ? 0 : (long)((SOUNDCLK_CONSTANT(maincpu_clk) - snddata.fclk)
1542                         / snddata.clkstep);
1543 }
1544 
sound_dump(int chipno)1545 int sound_dump(int chipno)
1546 {
1547     if (chipno >= snddata.sound_chip_channels) {
1548         return -1;
1549     }
1550     mon_out("%s\n", sound_machine_dump_state(snddata.psid[chipno]));
1551     return 0;
1552 }
1553 
sound_read(uint16_t addr,int chipno)1554 int sound_read(uint16_t addr, int chipno)
1555 {
1556     if (sound_run_sound()) {
1557         return -1;
1558     }
1559 
1560     if (chipno >= snddata.sound_chip_channels) {
1561         return -1;
1562     }
1563 
1564     return sound_machine_read(snddata.psid[chipno], addr);
1565 }
1566 
sound_store(uint16_t addr,uint8_t val,int chipno)1567 void sound_store(uint16_t addr, uint8_t val, int chipno)
1568 {
1569     int i;
1570 
1571     if (sound_run_sound()) {
1572         return;
1573     }
1574 
1575     if (chipno >= snddata.sound_chip_channels) {
1576         return;
1577     }
1578 
1579     sound_machine_store(snddata.psid[chipno], addr, val);
1580 
1581     if (!snddata.playdev->dump) {
1582         return;
1583     }
1584 
1585     i = snddata.playdev->dump(addr, val, maincpu_clk - snddata.wclk);
1586 
1587     snddata.wclk = maincpu_clk;
1588 
1589     if (i) {
1590         sound_error("store to sounddevice failed.");
1591     }
1592 }
1593 
1594 
sound_set_relative_speed(int value)1595 void sound_set_relative_speed(int value)
1596 {
1597     double natural_fps;
1598     double new_percent;
1599 
1600     if (value < 0) {
1601         natural_fps = (double)machine_get_cycles_per_second() / machine_get_cycles_per_frame();
1602         new_percent = 100.0 * (double)(0 - value) / natural_fps;
1603     } else {
1604         new_percent = value;
1605     }
1606 
1607     /* printf("sound new percent: %f\n", new_percent); */
1608 
1609     if (new_percent != speed_percent) {
1610         sid_state_changed = TRUE;
1611         speed_percent = new_percent;
1612     }
1613 }
1614 
sound_set_warp_mode(int value)1615 void sound_set_warp_mode(int value)
1616 {
1617     warp_mode_enabled = value;
1618 
1619     if (value) {
1620         sound_suspend();
1621     } else {
1622         sound_resume();
1623     }
1624 }
1625 
sound_snapshot_prepare(void)1626 void sound_snapshot_prepare(void)
1627 {
1628     /* Update lastclk.  */
1629     sound_run_sound();
1630 }
1631 
sound_snapshot_finish(void)1632 void sound_snapshot_finish(void)
1633 {
1634     snddata.lastclk = maincpu_clk;
1635 }
1636 
sound_dac_init(sound_dac_t * dac,int speed)1637 void sound_dac_init(sound_dac_t *dac, int speed)
1638 {
1639     /* 20 dB/Decade high pass filter, cutoff at 5 Hz. For DC offset filtering. */
1640     dac->alpha = (float)(0.0318309886 / (0.0318309886 + 1.0 / (float)speed));
1641     dac->value = 0;
1642     dac->output = 0.0;
1643 }
1644 
1645 /* FIXME: this should use bandlimited step synthesis. Sadly, VICE does not
1646  * have an easy-to-use infrastructure for blep generation. We should write
1647  * this code. */
sound_dac_calculate_samples(sound_dac_t * dac,int16_t * pbuf,int value,int nr,int soc,int cs)1648 int sound_dac_calculate_samples(sound_dac_t *dac, int16_t *pbuf, int value, int nr, int soc, int cs)
1649 {
1650     int i, sample;
1651     int off = 0;
1652     /* A simple high pass digital filter is employed here to get rid of the DC offset,
1653        which would cause distortion when mixed with other signal. This filter is formed
1654        on the actual hardware by the combination of output decoupling capacitor and load
1655        resistance.
1656     */
1657     if (nr) {
1658         dac->output = dac->alpha * (dac->output + (float)(value - dac->value));
1659         dac->value = value;
1660         sample = (int)dac->output;
1661         if (!sample) {
1662             return nr;
1663         }
1664         if (cs & 1) {
1665             pbuf[off] = sound_audio_mix(pbuf[off], sample);
1666         }
1667         if (cs & 2) {
1668             pbuf[off + 1] = sound_audio_mix(pbuf[off + 1], sample);
1669         }
1670         off += soc;
1671     }
1672 
1673     for (i = 1; i < nr; i++) {
1674         dac->output *= dac->alpha;
1675         sample = (int)dac->output;
1676         if (cs & 1) {
1677             pbuf[off] = sound_audio_mix(pbuf[off], sample);
1678         }
1679         if (cs & 2) {
1680             pbuf[off + 1] = sound_audio_mix(pbuf[off + 1], sample);
1681         }
1682         off += soc;
1683     }
1684     return nr;
1685 }
1686 
1687 /* recording related functions, equivalent to screenshot_... */
sound_stop_recording(void)1688 void sound_stop_recording(void)
1689 {
1690     resources_set_string("SoundRecordDeviceName", "");
1691 }
1692 
sound_is_recording(void)1693 int sound_is_recording(void)
1694 {
1695     return (strlen(recorddevice_name) > 0);
1696 }
1697