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 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

# User Rev Content
1 gbeauche 1.1 /*
2     * audio_sdl.cpp - Audio support, SDL implementation
3     *
4 gbeauche 1.3 * Basilisk II (C) 1997-2008 Christian Bauer
5 gbeauche 1.1 *
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 asvitkine 1.6 #if defined(BINCUE)
36     #include "bincue_unix.h"
37     #endif
38    
39 gbeauche 1.1
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 asvitkine 1.5 audio_spec.samples = 4096;
89 gbeauche 1.1 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 asvitkine 1.6 #if defined(BINCUE)
99     OpenAudio_bincue(audio_spec.freq, audio_spec.format, audio_spec.channels,
100     audio_spec.silence);
101     #endif
102    
103 gbeauche 1.1 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 asvitkine 1.6 #if defined(BINCUE)
231     MixAudio_bincue(stream, stream_len);
232     #endif
233 gbeauche 1.1 }
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     }