|
|
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;
64: spec.channels = currprefs.stereo ? 2 : 1;
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;
90: spec.channels = currprefs.stereo ? 2 : 1;
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). */
96: size >>= 2;
97: while (size & (size - 1))
98: size &= size - 1;
99: if (size < 512)
100: size = 512;
101: spec.samples = size;
102: spec.callback = sound_callback;
103: spec.userdata = 0;
104:
105: if (SDL_OpenAudio (&spec, NULL) < 0) {
106: write_log (stderr, "Couldn't open audio: %s\n", SDL_GetError());
107: return 0;
108: }
109: have_sound = 1;
110:
1.1.1.2 ! root 111: scaled_sample_evtime = (unsigned long)MAXHPOS_PAL * MAXVPOS_PAL * VBLANK_HZ_PAL * CYCLE_UNIT / spec.freq;
1.1 root 112: scaled_sample_evtime_ok = 1;
113:
114: if (spec.format == AUDIO_S16) {
115: init_sound_table16 ();
116: sample_handler = currprefs.stereo ? sample16s_handler : sample16_handler;
117: } else {
118: init_sound_table8 ();
119: sample_handler = currprefs.stereo ? sample8s_handler : sample8_handler;
120: }
121: sound_available = 1;
122: write_log ("SDL sound driver found and configured for %d bits at %d Hz, buffer is %d samples\n",
123: currprefs.sound_bits, spec.freq, spec.samples);
124: sndbufpt = sndbuffer;
125: sndbufsize = size * currprefs.sound_bits / 8 * spec.channels;
126: return 1;
127: }
128:
129: static void *sound_thread (void *dummy)
130: {
131: for (;;) {
132: int cmd = read_comm_pipe_int_blocking (&to_sound_pipe);
133: int n;
134:
135: switch (cmd) {
136: case 0:
137: open_sound ();
138: uae_sem_post (&sound_init_sem);
139: break;
140: case 1:
141: uae_sem_post (&sound_init_sem);
142: return 0;
143: }
144: }
145: }
146:
147: /* We need a thread for this, since communication between finish_sound_buffer
148: and the callback works through semaphores. In theory, this is unnecessary,
149: since SDL uses a sound thread internally, and the callback runs in its
150: context. But we don't want to depend on SDL's internals too much. */
151: static void init_sound_thread (void)
152: {
153: uae_thread_id tid;
154:
155: init_comm_pipe (&to_sound_pipe, 20, 1);
156: uae_sem_init (&data_available_sem, 0, 0);
157: uae_sem_init (&callback_done_sem, 0, 0);
158: uae_sem_init (&sound_init_sem, 0, 0);
159: uae_start_thread (sound_thread, NULL, &tid);
160: }
161:
162: void close_sound (void)
163: {
164: if (! have_sound)
165: return;
166:
167: SDL_PauseAudio (1);
168: if (in_callback) {
169: closing_sound = 1;
170: uae_sem_post (&data_available_sem);
171: }
172: write_comm_pipe_int (&to_sound_pipe, 1, 1);
173: uae_sem_wait (&sound_init_sem);
174: SDL_CloseAudio ();
175: uae_sem_destroy (&data_available_sem);
176: uae_sem_destroy (&sound_init_sem);
177: uae_sem_destroy (&callback_done_sem);
178: have_sound = 0;
179: }
180:
181: int init_sound (void)
182: {
183: in_callback = 0;
184: closing_sound = 0;
185:
186: init_sound_thread ();
187: write_comm_pipe_int (&to_sound_pipe, 0, 1);
188: uae_sem_wait (&sound_init_sem);
189: SDL_PauseAudio (0);
190:
191: return have_sound;
192: }
193:
194: void pause_sound (void)
195: {
196: SDL_PauseAudio (1);
197: }
198:
199: void resume_sound (void)
200: {
201: SDL_PauseAudio (0);
202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.