|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Support for Linux/USS sound
5: *
6: * Copyright 1997 Bernd Schmidt
7: */
8:
9: #include "sysconfig.h"
10: #include "sysdeps.h"
11:
12: #include "config.h"
13: #include "options.h"
14: #include "memory.h"
15: #include "events.h"
16: #include "custom.h"
17: #include "gensound.h"
18: #include "sounddep/sound.h"
19: #include "threaddep/thread.h"
20: #include "SDL_audio.h"
21:
22: int sound_fd;
23: static int have_sound = 0;
24: static unsigned long formats;
25:
26: uae_u16 sndbuffer[44100];
27: uae_u16 *sndbufpt;
28: int sndbufsize;
29: static SDL_AudioSpec spec;
30:
31: static smp_comm_pipe to_sound_pipe;
32: static uae_sem_t data_available_sem, callback_done_sem, sound_init_sem;
33:
34: static int in_callback, closing_sound;
35:
36: static void sound_callback (void *userdata, Uint8 *stream, int len)
37: {
38: if (closing_sound)
39: return;
40: in_callback = 1;
41: /* Wait for data to finish. */
42: uae_sem_wait (&data_available_sem);
43: if (! closing_sound) {
44: memcpy (stream, sndbuffer, sndbufsize);
45: /* Notify writer that we're done. */
46: uae_sem_post (&callback_done_sem);
47: }
48: in_callback = 0;
49: }
50:
51: void finish_sound_buffer (void)
52: {
53: uae_sem_post (&data_available_sem);
54: uae_sem_wait (&callback_done_sem);
55: }
56:
57: /* Try to determine whether sound is available. This is only for GUI purposes. */
58: int setup_sound (void)
59: {
60: int size = currprefs.sound_maxbsiz;
61:
62: spec.freq = currprefs.sound_freq;
63: spec.format = AUDIO_S16;
1.1.1.3 ! root 64: spec.channels = currprefs.sound_stereo ? 2 : 1;
1.1 root 65: size >>= spec.channels - 1;
66: size >>= 1;
67: while (size & (size - 1))
68: size &= size - 1;
69: if (size < 512)
70: size = 512;
71: spec.samples = size;
72: spec.callback = sound_callback;
73: spec.userdata = 0;
74:
75: if (SDL_OpenAudio (&spec, NULL) < 0) {
76: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError());
77: return 0;
78: }
79: sound_available = 1;
80: SDL_CloseAudio ();
81: return 1;
82: }
83:
84: static int open_sound (void)
85: {
86: int size = currprefs.sound_maxbsiz;
87:
88: spec.freq = currprefs.sound_freq;
89: spec.format = currprefs.sound_bits == 8 ? AUDIO_U8 : AUDIO_S16;
1.1.1.3 ! root 90: spec.channels = currprefs.sound_stereo ? 2 : 1;
1.1 root 91: /* Always interpret buffer size as number of samples, not as actual
92: buffer size. Of course, since 8192 is the default, we'll have to
93: scale that to a sane value (assuming that otherwise 16 bits and
94: stereo would have been enabled and we'd have done the shift by
95: two anyway). */
1.1.1.3 ! root 96: size >>= spec.channels - 1;
! 97: size >>= currprefs.sound_bits == 8 ? 0 : 1;
1.1 root 98: while (size & (size - 1))
99: size &= size - 1;
100: if (size < 512)
101: size = 512;
102: spec.samples = size;
103: spec.callback = sound_callback;
104: spec.userdata = 0;
105:
106: if (SDL_OpenAudio (&spec, NULL) < 0) {
107: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError());
108: return 0;
109: }
110: have_sound = 1;
111:
1.1.1.2 root 112: scaled_sample_evtime = (unsigned long)MAXHPOS_PAL * MAXVPOS_PAL * VBLANK_HZ_PAL * CYCLE_UNIT / spec.freq;
1.1 root 113: scaled_sample_evtime_ok = 1;
114:
115: if (spec.format == AUDIO_S16) {
116: init_sound_table16 ();
1.1.1.3 ! root 117: sample_handler = currprefs.sound_stereo ? sample16s_handler : sample16_handler;
1.1 root 118: } else {
119: init_sound_table8 ();
1.1.1.3 ! root 120: sample_handler = currprefs.sound_stereo ? sample8s_handler : sample8_handler;
1.1 root 121: }
122: sound_available = 1;
123: write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d samples\n",
124: currprefs.sound_bits, spec.freq, spec.samples);
125: sndbufpt = sndbuffer;
126: sndbufsize = size * currprefs.sound_bits / 8 * spec.channels;
127: return 1;
128: }
129:
130: static void *sound_thread (void *dummy)
131: {
132: for (;;) {
133: int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
134: int n;
135:
136: switch (cmd) {
137: case 0:
138: open_sound ();
139: uae_sem_post (&sound_init_sem);
140: break;
141: case 1:
142: uae_sem_post (&sound_init_sem);
143: return 0;
144: }
145: }
146: }
147:
148: /* We need a thread for this, since communication between finish_sound_buffer
149: and the callback works through semaphores. In theory, this is unnecessary,
150: since SDL uses a sound thread internally, and the callback runs in its
151: context. But we don't want to depend on SDL's internals too much. */
152: static void init_sound_thread (void)
153: {
154: uae_thread_id tid;
155:
156: init_comm_pipe (&to_sound_pipe, 20, 1);
157: uae_sem_init (&data_available_sem, 0, 0);
158: uae_sem_init (&callback_done_sem, 0, 0);
159: uae_sem_init (&sound_init_sem, 0, 0);
160: uae_start_thread (sound_thread, NULL, &tid);
161: }
162:
163: void close_sound (void)
164: {
165: if (! have_sound)
166: return;
167:
168: SDL_PauseAudio (1);
169: if (in_callback) {
170: closing_sound = 1;
171: uae_sem_post (&data_available_sem);
172: }
173: write_comm_pipe_int (&to_sound_pipe, 1, 1);
174: uae_sem_wait (&sound_init_sem);
175: SDL_CloseAudio ();
176: uae_sem_destroy (&data_available_sem);
177: uae_sem_destroy (&sound_init_sem);
178: uae_sem_destroy (&callback_done_sem);
179: have_sound = 0;
180: }
181:
182: int init_sound (void)
183: {
184: in_callback = 0;
185: closing_sound = 0;
186:
187: init_sound_thread ();
188: write_comm_pipe_int (&to_sound_pipe, 0, 1);
189: uae_sem_wait (&sound_init_sem);
190: SDL_PauseAudio (0);
191:
192: return have_sound;
193: }
194:
195: void pause_sound (void)
196: {
197: SDL_PauseAudio (1);
198: }
199:
200: void resume_sound (void)
201: {
202: SDL_PauseAudio (0);
203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.