ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/SDL/audio_sdl.cpp
Revision: 1.1
Committed: 2004-07-19T19:25:06Z (20 years, 4 months ago) by gbeauche
Branch: MAIN
Log Message:
SDL audio support

File Contents

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