|
|
1.1.1.2 root 1: /*
1.1 root 2: * UAE - The Un*x Amiga Emulator
1.1.1.2 root 3: *
1.1 root 4: * Support for Linux/ALSA sound
1.1.1.2 root 5: *
1.1 root 6: * Copyright 1997 Bernd Schmidt
7: * Copyright 2004 Heikki Orsila
8: */
9:
10: #include <alsa/asoundlib.h>
11:
12: extern int sound_fd;
13: extern uae_u16 sndbuffer[];
14: extern uae_u16 *sndbufpt;
15: extern int sndbufsize;
16: extern snd_pcm_t *alsa_playback_handle;
17: extern int alsa_to_frames_divisor;
18:
19: /* alsa_xrun_recovery() function is copied from ALSA manual. why the hell did
20: they make ALSA this hard?! i bet 95% of ALSA programmers would like a
21: simpler way to do error handling.. let the 5% use tricky APIs.
22: */
23: static int alsa_xrun_recovery(snd_pcm_t *handle, int err)
24: {
25: if (err == -EPIPE) {
26: /* under-run */
27: err = snd_pcm_prepare(handle);
28: if (err < 0)
29: fprintf(stderr, "uae: no recovery with alsa from underrun, prepare failed: %s\n", snd_strerror(err));
30: return 0;
31: } else if (err == -ESTRPIPE) {
32: while ((err = snd_pcm_resume(handle)) == -EAGAIN) {
33: /* wait until the suspend flag is released */
34: fprintf(stderr, "uae: sleeping for alsa.\n");
35: sleep(1);
36: }
37: if (err < 0) {
38: err = snd_pcm_prepare(handle);
39: if (err < 0)
40: fprintf(stderr, "uae: no recovery with alsa from suspend, prepare failed: %s\n", snd_strerror(err));
41: }
42: return 0;
43: }
44: return err;
45: }
46:
1.1.1.3 ! root 47: static int check_sound_buffers (void)
1.1 root 48: {
1.1.1.3 ! root 49: if ((char *)sndbufpt - (char *)sndbuffer >= sndbufsize) {
! 50: int frames = sndbufsize / alsa_to_frames_divisor;
! 51: char *buf = (char *) sndbuffer;
! 52: int ret;
! 53: while (frames > 0) {
! 54: ret = snd_pcm_writei(alsa_playback_handle, buf, frames);
! 55: if (ret < 0) {
! 56: if (ret == -EAGAIN || ret == -EINTR)
! 57: continue;
! 58: if (alsa_xrun_recovery(alsa_playback_handle, ret) < 0) {
! 59: fprintf(stderr, "uae: write error with alsa: %s\n", snd_strerror(ret));
! 60: exit(-1);
! 61: }
! 62: continue;
! 63: }
! 64: frames -= ret;
! 65: buf += ret * alsa_to_frames_divisor;
1.1 root 66: }
1.1.1.3 ! root 67: sndbufpt = sndbuffer;
! 68: return 1;
1.1 root 69: }
1.1.1.3 ! root 70: return 0;
1.1 root 71: }
72:
73: #define PUT_SOUND_BYTE(b) do { *(uae_u8 *)sndbufpt = b; sndbufpt = (uae_u16 *)(((uae_u8 *)sndbufpt) + 1); } while (0)
74: #define PUT_SOUND_WORD(b) do { *(uae_u16 *)sndbufpt = b; sndbufpt = (uae_u16 *)(((uae_u8 *)sndbufpt) + 2); } while (0)
75: #define PUT_SOUND_BYTE_LEFT(b) PUT_SOUND_BYTE(b)
76: #define PUT_SOUND_WORD_LEFT(b) PUT_SOUND_WORD(b)
77: #define PUT_SOUND_BYTE_RIGHT(b) PUT_SOUND_BYTE(b)
78: #define PUT_SOUND_WORD_RIGHT(b) PUT_SOUND_WORD(b)
79: #define SOUND16_BASE_VAL 0
80: #define SOUND8_BASE_VAL 128
81:
82: #define DEFAULT_SOUND_MAXB 8192
83: #define DEFAULT_SOUND_MINB 8192
84: #define DEFAULT_SOUND_BITS 16
85: #define DEFAULT_SOUND_FREQ 44100
86: #define HAVE_STEREO_SUPPORT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.