ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/SDL/audio_sdl.cpp
Revision: 1.6
Committed: 2010-10-06T00:30:23Z (14 years, 1 month ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +12 -0 lines
Log Message:
[Geoffrey Brown]

Add bin/cue support. The following should work:

1) Basilisk and SheepShaver with sdl-audio and bincue on linux and os x
2) SheepShaver with bincue and core audio on os x

File Contents

# Content
1 /*
2 * audio_sdl.cpp - Audio support, SDL implementation
3 *
4 * Basilisk II (C) 1997-2008 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sysdeps.h"
22 #include "cpu_emulation.h"
23 #include "main.h"
24 #include "prefs.h"
25 #include "user_strings.h"
26 #include "audio.h"
27 #include "audio_defs.h"
28
29 #include <SDL_mutex.h>
30 #include <SDL_audio.h>
31
32 #define DEBUG 0
33 #include "debug.h"
34
35 #if defined(BINCUE)
36 #include "bincue_unix.h"
37 #endif
38
39
40 // The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors)
41 static int audio_sample_rate_index = 0;
42 static int audio_sample_size_index = 0;
43 static int audio_channel_count_index = 0;
44
45 // Global variables
46 static SDL_sem *audio_irq_done_sem = NULL; // Signal from interrupt to streaming thread: data block read
47 static uint8 silence_byte; // Byte value to use to fill sound buffers with silence
48
49 // Prototypes
50 static void stream_func(void *arg, uint8 *stream, int stream_len);
51
52
53 /*
54 * Initialization
55 */
56
57 // Set AudioStatus to reflect current audio stream format
58 static void set_audio_status_format(void)
59 {
60 AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
61 AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
62 AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
63 }
64
65 // Init SDL audio system
66 static bool open_sdl_audio(void)
67 {
68 // SDL supports a variety of twisted little audio formats, all different
69 if (audio_sample_sizes.empty()) {
70 audio_sample_rates.push_back(11025 << 16);
71 audio_sample_rates.push_back(22050 << 16);
72 audio_sample_rates.push_back(44100 << 16);
73 audio_sample_sizes.push_back(8);
74 audio_sample_sizes.push_back(16);
75 audio_channel_counts.push_back(1);
76 audio_channel_counts.push_back(2);
77
78 // Default to highest supported values
79 audio_sample_rate_index = audio_sample_rates.size() - 1;
80 audio_sample_size_index = audio_sample_sizes.size() - 1;
81 audio_channel_count_index = audio_channel_counts.size() - 1;
82 }
83
84 SDL_AudioSpec audio_spec;
85 audio_spec.freq = audio_sample_rates[audio_sample_rate_index] >> 16;
86 audio_spec.format = (audio_sample_sizes[audio_sample_size_index] == 8) ? AUDIO_U8 : AUDIO_S16MSB;
87 audio_spec.channels = audio_channel_counts[audio_channel_count_index];
88 audio_spec.samples = 4096;
89 audio_spec.callback = stream_func;
90 audio_spec.userdata = NULL;
91
92 // Open the audio device, forcing the desired format
93 if (SDL_OpenAudio(&audio_spec, NULL) < 0) {
94 fprintf(stderr, "WARNING: Cannot open audio: %s\n", SDL_GetError());
95 return false;
96 }
97
98 #if defined(BINCUE)
99 OpenAudio_bincue(audio_spec.freq, audio_spec.format, audio_spec.channels,
100 audio_spec.silence);
101 #endif
102
103 char driver_name[32];
104 printf("Using SDL/%s audio output\n", SDL_AudioDriverName(driver_name, sizeof(driver_name) - 1));
105 silence_byte = audio_spec.silence;
106 SDL_PauseAudio(0);
107
108 // Sound buffer size = 4096 frames
109 audio_frames_per_block = audio_spec.samples;
110 return true;
111 }
112
113 static bool open_audio(void)
114 {
115 // Try to open SDL audio
116 if (!open_sdl_audio()) {
117 WarningAlert(GetString(STR_NO_AUDIO_WARN));
118 return false;
119 }
120
121 // Device opened, set AudioStatus
122 set_audio_status_format();
123
124 // Everything went fine
125 audio_open = true;
126 return true;
127 }
128
129 void AudioInit(void)
130 {
131 // Init audio status and feature flags
132 AudioStatus.sample_rate = 44100 << 16;
133 AudioStatus.sample_size = 16;
134 AudioStatus.channels = 2;
135 AudioStatus.mixer = 0;
136 AudioStatus.num_sources = 0;
137 audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
138
139 // Sound disabled in prefs? Then do nothing
140 if (PrefsFindBool("nosound"))
141 return;
142
143 // Init semaphore
144 audio_irq_done_sem = SDL_CreateSemaphore(0);
145
146 // Open and initialize audio device
147 open_audio();
148 }
149
150
151 /*
152 * Deinitialization
153 */
154
155 static void close_audio(void)
156 {
157 // Close audio device
158 SDL_CloseAudio();
159 audio_open = false;
160 }
161
162 void AudioExit(void)
163 {
164 // Close audio device
165 close_audio();
166
167 // Delete semaphore
168 if (audio_irq_done_sem)
169 SDL_DestroySemaphore(audio_irq_done_sem);
170 }
171
172
173 /*
174 * First source added, start audio stream
175 */
176
177 void audio_enter_stream()
178 {
179 }
180
181
182 /*
183 * Last source removed, stop audio stream
184 */
185
186 void audio_exit_stream()
187 {
188 }
189
190
191 /*
192 * Streaming function
193 */
194
195 static void stream_func(void *arg, uint8 *stream, int stream_len)
196 {
197 if (AudioStatus.num_sources) {
198
199 // Trigger audio interrupt to get new buffer
200 D(bug("stream: triggering irq\n"));
201 SetInterruptFlag(INTFLAG_AUDIO);
202 TriggerInterrupt();
203 D(bug("stream: waiting for ack\n"));
204 SDL_SemWait(audio_irq_done_sem);
205 D(bug("stream: ack received\n"));
206
207 // Get size of audio data
208 uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
209 if (apple_stream_info) {
210 int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
211 D(bug("stream: work_size %d\n", work_size));
212 if (work_size > stream_len)
213 work_size = stream_len;
214 if (work_size == 0)
215 goto silence;
216
217 // Send data to audio device
218 Mac2Host_memcpy(stream, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
219 if (work_size != stream_len)
220 memset((uint8 *)stream + work_size, silence_byte, stream_len - work_size);
221 D(bug("stream: data written\n"));
222 } else
223 goto silence;
224
225 } else {
226
227 // Audio not active, play silence
228 silence: memset(stream, silence_byte, stream_len);
229 }
230 #if defined(BINCUE)
231 MixAudio_bincue(stream, stream_len);
232 #endif
233 }
234
235
236 /*
237 * MacOS audio interrupt, read next data block
238 */
239
240 void AudioInterrupt(void)
241 {
242 D(bug("AudioInterrupt\n"));
243
244 // Get data from apple mixer
245 if (AudioStatus.mixer) {
246 M68kRegisters r;
247 r.a[0] = audio_data + adatStreamInfo;
248 r.a[1] = AudioStatus.mixer;
249 Execute68k(audio_data + adatGetSourceData, &r);
250 D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
251 } else
252 WriteMacInt32(audio_data + adatStreamInfo, 0);
253
254 // Signal stream function
255 SDL_SemPost(audio_irq_done_sem);
256 D(bug("AudioInterrupt done\n"));
257 }
258
259
260 /*
261 * Set sampling parameters
262 * "index" is an index into the audio_sample_rates[] etc. vectors
263 * It is guaranteed that AudioStatus.num_sources == 0
264 */
265
266 bool audio_set_sample_rate(int index)
267 {
268 close_audio();
269 audio_sample_rate_index = index;
270 return open_audio();
271 }
272
273 bool audio_set_sample_size(int index)
274 {
275 close_audio();
276 audio_sample_size_index = index;
277 return open_audio();
278 }
279
280 bool audio_set_channels(int index)
281 {
282 close_audio();
283 audio_channel_count_index = index;
284 return open_audio();
285 }
286
287
288 /*
289 * Get/set volume controls (volume values received/returned have the left channel
290 * volume in the upper 16 bits and the right channel volume in the lower 16 bits;
291 * both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
292 */
293
294 bool audio_get_main_mute(void)
295 {
296 return false;
297 }
298
299 uint32 audio_get_main_volume(void)
300 {
301 return 0x01000100;
302 }
303
304 bool audio_get_speaker_mute(void)
305 {
306 return false;
307 }
308
309 uint32 audio_get_speaker_volume(void)
310 {
311 return 0x01000100;
312 }
313
314 void audio_set_main_mute(bool mute)
315 {
316 }
317
318 void audio_set_main_volume(uint32 vol)
319 {
320 }
321
322 void audio_set_speaker_mute(bool mute)
323 {
324 }
325
326 void audio_set_speaker_volume(uint32 vol)
327 {
328 }