|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Support for Linux/ALSA sound
5: *
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:
47: static void check_sound_buffers (void)
48: {
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;
66: }
67: sndbufpt = sndbuffer;
68: }
69: }
70:
71: #define PUT_SOUND_BYTE(b) do { *(uae_u8 *)sndbufpt = b; sndbufpt = (uae_u16 *)(((uae_u8 *)sndbufpt) + 1); } while (0)
72: #define PUT_SOUND_WORD(b) do { *(uae_u16 *)sndbufpt = b; sndbufpt = (uae_u16 *)(((uae_u8 *)sndbufpt) + 2); } while (0)
73: #define PUT_SOUND_BYTE_LEFT(b) PUT_SOUND_BYTE(b)
74: #define PUT_SOUND_WORD_LEFT(b) PUT_SOUND_WORD(b)
75: #define PUT_SOUND_BYTE_RIGHT(b) PUT_SOUND_BYTE(b)
76: #define PUT_SOUND_WORD_RIGHT(b) PUT_SOUND_WORD(b)
77: #define SOUND16_BASE_VAL 0
78: #define SOUND8_BASE_VAL 128
79:
80: #define DEFAULT_SOUND_MAXB 8192
81: #define DEFAULT_SOUND_MINB 8192
82: #define DEFAULT_SOUND_BITS 16
83: #define DEFAULT_SOUND_FREQ 44100
84: #define HAVE_STEREO_SUPPORT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.