|
|
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: * BUGS: certainly
10: * TODO:
11: * - if setup_sound() fails, there may still be hope to get the
12: * sound device, but we totally give up.. see sd-uss.
13: */
14:
15: #include "sysconfig.h"
16: #include "sysdeps.h"
17:
18: #include "config.h"
19: #include "options.h"
20: #include "memory.h"
21: #include "events.h"
22: #include "custom.h"
23: #include "gensound.h"
24: #include "sounddep/sound.h"
25:
26: #include <alsa/asoundlib.h>
27:
28: int sound_fd;
29: static int have_sound = 0;
30: static unsigned long formats;
31:
32: uae_u16 sndbuffer[44100];
33: uae_u16 *sndbufpt;
34: int sndbufsize;
35:
36: snd_pcm_t *alsa_playback_handle = 0;
37: int alsa_to_frames_divisor = 4;
38:
39: void close_sound (void)
40: {
41: if (alsa_playback_handle) {
42: snd_pcm_close (alsa_playback_handle);
43: alsa_playback_handle = 0;
44: }
45: }
46:
47: static int open_sound(void)
48: {
49: return snd_pcm_open (&alsa_playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
50: }
51:
52: /* Try to determine whether sound is available. This is only for GUI purposes. */
53: int setup_sound (void)
54: {
55: int err;
56: sound_available = 0;
57: if ((err = open_sound()) < 0) {
58: /* TODO: if the pcm was busy, we should the same as sd-uss does.
59: tell the caller that sound is available. in any other
60: condition we should just return 0. */
61: fprintf (stderr, "cannot open audio device (%s)\n", snd_strerror (err));
62: return 0;
63: }
64: snd_pcm_close (alsa_playback_handle);
65: alsa_playback_handle = 0;
66: sound_available = 1;
67: return 1;
68: }
69:
70: int init_sound (void)
71: {
72: int tmp;
73: int rate;
74: int dspbits;
75: int alsamode;
76: int channels;
77: int err;
78: snd_pcm_hw_params_t *hw_params;
79: snd_pcm_uframes_t buffer_frames;
80:
81: dspbits = currprefs.sound_bits;
82: channels = currprefs.sound_stereo ? 2 : 1;
83: rate = currprefs.sound_freq;
84:
85: have_sound = 0;
86: alsa_playback_handle = 0;
87: if ((err = open_sound()) < 0) {
88: fprintf (stderr, "cannot open audio device (%s)\n", snd_strerror (err));
89: goto nosound;
90: }
91:
92: if (currprefs.sound_maxbsiz < 128 || currprefs.sound_maxbsiz > 16384) {
93: fprintf (stderr, "Sound buffer size %d out of range.\n", currprefs.sound_maxbsiz);
94: currprefs.sound_maxbsiz = 8192;
95: }
96: sndbufsize = currprefs.sound_maxbsiz;
97:
98: if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
99: fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
100: snd_strerror (err));
101: goto nosound;
102: }
103:
104: if ((err = snd_pcm_hw_params_any (alsa_playback_handle, hw_params)) < 0) {
105: fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
106: snd_strerror (err));
107: goto nosound;
108: }
109:
110: if ((err = snd_pcm_hw_params_set_access (alsa_playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
111: fprintf (stderr, "cannot set access type (%s)\n",
112: snd_strerror (err));
113: goto nosound;
114: }
115:
116: switch (dspbits) {
117: case 8:
118: alsamode = SND_PCM_FORMAT_U8;
119: break;
120: case 16:
121: alsamode = SND_PCM_FORMAT_S16;
122: break;
123: default:
124: fprintf(stderr, "%d bit samples not supported with uae's alsa\n", dspbits);
125: goto nosound;
126: }
127:
128: if ((err = snd_pcm_hw_params_set_format (alsa_playback_handle, hw_params, alsamode)) < 0) {
129: fprintf (stderr, "cannot set sample format (%s)\n",
130: snd_strerror (err));
131: goto nosound;
132: }
133:
134: if ((err = snd_pcm_hw_params_set_channels (alsa_playback_handle, hw_params, channels)) < 0) {
135: fprintf (stderr, "cannot set channel count (%s)\n",
136: snd_strerror (err));
137: goto nosound;
138: }
139:
140: if ((err = snd_pcm_hw_params_set_rate_near (alsa_playback_handle, hw_params, &rate, 0)) < 0) {
141: fprintf (stderr, "cannot set sample rate (%s)\n",
142: snd_strerror (err));
143: goto nosound;
144: }
145:
146: alsa_to_frames_divisor = channels * dspbits / 8;
147: buffer_frames = sndbufsize / alsa_to_frames_divisor;
148: if ((err = snd_pcm_hw_params_set_period_size_near(alsa_playback_handle, hw_params, &buffer_frames, 0)) < 0) {
149: fprintf (stderr, "cannot set period size near (%s)\n", snd_strerror (err));
150: goto nosound;
151: }
152:
153: if ((err = snd_pcm_hw_params (alsa_playback_handle, hw_params)) < 0) {
154: fprintf (stderr, "cannot set parameters (%s)\n",
155: snd_strerror (err));
156: goto nosound;
157: }
158:
159: snd_pcm_hw_params_free (hw_params);
160:
161: if ((err = snd_pcm_prepare (alsa_playback_handle)) < 0) {
162: fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
163: snd_strerror (err));
164: goto nosound;
165: }
166:
167: scaled_sample_evtime = (unsigned long) MAXHPOS_PAL * MAXVPOS_PAL * VBLANK_HZ_PAL * CYCLE_UNIT / rate;
168: scaled_sample_evtime_ok = 1;
169:
170: if (dspbits == 16) {
171: init_sound_table16 ();
172: sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
173: } else {
174: init_sound_table8 ();
175: sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler;
176: }
177: have_sound = 1;
178: sound_available = 1;
179: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
180:
181: sndbufpt = sndbuffer;
182: return 1;
183:
184: nosound:
185: have_sound = 0;
186: close_sound();
187: return 0;
188: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.