ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/audio_beos.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:25Z (25 years, 1 month ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * audio_beos.cpp - Audio support, BeOS implementation
3     *
4     * Basilisk II (C) 1997-1999 Christian Bauer
5     * Portions (C) 1997-1999 Marc Hellwig
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     #include "sysdeps.h"
23    
24     #include <KernelKit.h>
25     #include <MediaKit.h>
26    
27     #include "cpu_emulation.h"
28     #include "main.h"
29     #include "prefs.h"
30     #include "user_strings.h"
31     #include "audio.h"
32     #include "audio_defs.h"
33    
34     #define DEBUG 0
35     #include "debug.h"
36    
37    
38     // Supported sample rates, sizes and channels
39     int audio_num_sample_rates = 1;
40     uint32 audio_sample_rates[] = {44100 << 16};
41     int audio_num_sample_sizes = 1;
42     uint16 audio_sample_sizes[] = {16};
43     int audio_num_channel_counts = 1;
44     uint16 audio_channel_counts[] = {2};
45    
46     // Global variables
47     static int audio_irq_done_sem = -1; // Signal from interrupt to streaming thread: data block read
48     static BSoundPlayer *the_player;
49    
50     // Prototypes
51     static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format);
52    
53    
54     /*
55     * Audio manager thread (for calling media kit functions;
56     * this is not safe under R4 when running on the MacOS stack in kernel space)
57     */
58    
59     // Message constants
60     const uint32 MSG_QUIT_AUDIO_MANAGER = 'quit';
61     const uint32 MSG_ENTER_STREAM = 'entr';
62     const uint32 MSG_EXIT_STREAM = 'exit';
63     const uint32 MSG_GET_VOLUME = 'getv';
64     const uint32 MSG_SET_VOLUME = 'setv';
65    
66     static thread_id am_thread = -1;
67     static sem_id am_done_sem = -1;
68    
69     static volatile float am_volume;
70    
71     static status_t audio_manager(void *arg)
72     {
73     for (;;) {
74    
75     // Receive message
76     thread_id sender;
77     uint32 code = receive_data(&sender, NULL, 0);
78     D(bug("Audio manager received %08lx\n", code));
79     switch (code) {
80     case MSG_QUIT_AUDIO_MANAGER:
81     return 0;
82    
83     case MSG_ENTER_STREAM:
84     the_player->Start();
85     break;
86    
87     case MSG_EXIT_STREAM:
88     the_player->Stop();
89     break;
90    
91     case MSG_GET_VOLUME:
92     am_volume = the_player->Volume();
93     break;
94    
95     case MSG_SET_VOLUME:
96     the_player->SetVolume(am_volume);
97     break;
98     }
99    
100     // Acknowledge
101     release_sem(am_done_sem);
102     }
103     }
104    
105    
106     /*
107     * Initialization
108     */
109    
110     void AudioInit(void)
111     {
112     // Init audio status and feature flags
113     AudioStatus.sample_rate = audio_sample_rates[0];
114     AudioStatus.sample_size = audio_sample_sizes[0];
115     AudioStatus.channels = audio_channel_counts[0];
116     AudioStatus.mixer = 0;
117     AudioStatus.num_sources = 0;
118     audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
119    
120     // Sound disabled in prefs? Then do nothing
121     if (PrefsFindBool("nosound"))
122     return;
123    
124     // Init semaphores
125     audio_irq_done_sem = create_sem(0, "Audio IRQ Done");
126     am_done_sem = create_sem(0, "Audio Manager Done");
127    
128     // Start audio manager thread
129     am_thread = spawn_thread(audio_manager, "Audio Manager", B_NORMAL_PRIORITY, NULL);
130     resume_thread(am_thread);
131    
132     // Start stream
133     media_raw_audio_format format;
134     format.frame_rate = AudioStatus.sample_rate >> 16;
135     format.channel_count = AudioStatus.channels;
136     format.format = media_raw_audio_format::B_AUDIO_SHORT;
137     format.byte_order = B_MEDIA_BIG_ENDIAN;
138     audio_frames_per_block = 4096;
139     size_t block_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
140     D(bug("AudioInit: block size %d\n", block_size));
141     format.buffer_size = block_size;
142     the_player = new BSoundPlayer(&format, "MacOS Audio", playbuffer_func, NULL, NULL);
143     if (the_player->InitCheck() != B_NO_ERROR) {
144     printf("FATAL: Cannot initialize BSoundPlayer\n");
145     delete the_player;
146     the_player = NULL;
147     return;
148     } else
149     the_player->SetHasData(true);
150    
151     // Everything OK
152     audio_open = true;
153     }
154    
155    
156     /*
157     * Deinitialization
158     */
159    
160     void AudioExit(void)
161     {
162     // Stop stream
163     if (the_player) {
164     the_player->Stop();
165     delete the_player;
166     the_player = NULL;
167     }
168    
169     // Stop audio manager
170     if (am_thread > 0) {
171     status_t l;
172     send_data(am_thread, MSG_QUIT_AUDIO_MANAGER, NULL, 0);
173     wait_for_thread(am_thread, &l);
174     }
175    
176     // Delete semaphores
177     delete_sem(am_done_sem);
178     delete_sem(audio_irq_done_sem);
179     }
180    
181    
182     /*
183     * First source added, start audio stream
184     */
185    
186     void audio_enter_stream()
187     {
188     while (send_data(am_thread, MSG_ENTER_STREAM, NULL, 0) == B_INTERRUPTED) ;
189     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
190     }
191    
192    
193     /*
194     * Last source removed, stop audio stream
195     */
196    
197     void audio_exit_stream()
198     {
199     while (send_data(am_thread, MSG_EXIT_STREAM, NULL, 0) == B_INTERRUPTED) ;
200     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
201     }
202    
203    
204     /*
205     * Streaming function
206     */
207    
208     static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer
209    
210     static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format)
211     {
212     // Check if new buffer is available
213     if (acquire_sem_etc(audio_irq_done_sem, 1, B_TIMEOUT, 0) == B_NO_ERROR) {
214    
215     // Get size of audio data
216     D(bug("stream: new buffer present\n"));
217     uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
218     if (apple_stream_info) {
219     size_t work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
220     D(bug("stream: size %d, work_size %d\n", size, work_size));
221     if (work_size > size)
222     work_size = size;
223    
224     if (format.format != media_raw_audio_format::B_AUDIO_SHORT) {
225     D(bug("Wrong audio format %04x\n", format.format));
226     return;
227     }
228    
229     // Place data into Media Kit buffer
230     memcpy(buf, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), work_size);
231     if (work_size != size)
232     memset((uint8 *)buf + work_size, 0, size - work_size);
233     }
234    
235     } else
236     memset(buf, 0, size);
237    
238     // Trigger audio interrupt to get new buffer
239     if (AudioStatus.num_sources) {
240     D(bug("stream: triggering irq\n"));
241     SetInterruptFlag(INTFLAG_AUDIO);
242     TriggerInterrupt();
243     }
244     }
245    
246    
247     /*
248     * MacOS audio interrupt, read next data block
249     */
250    
251     void AudioInterrupt(void)
252     {
253     D(bug("AudioInterrupt\n"));
254    
255     // Get data from apple mixer
256     if (AudioStatus.mixer) {
257     M68kRegisters r;
258     r.a[0] = audio_data + adatStreamInfo;
259     r.a[1] = AudioStatus.mixer;
260     Execute68k(audio_data + adatGetSourceData, &r);
261     D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
262     } else
263     WriteMacInt32(audio_data + adatStreamInfo, 0);
264    
265     // Signal stream function
266     release_sem(audio_irq_done_sem);
267     D(bug("AudioInterrupt done\n"));
268     }
269    
270    
271     /*
272     * Set sampling parameters
273     * "index" is an index into the audio_sample_rates[] etc. arrays
274     * It is guaranteed that AudioStatus.num_sources == 0
275     */
276    
277     void audio_set_sample_rate(int index)
278     {
279     }
280    
281     void audio_set_sample_size(int index)
282     {
283     }
284    
285     void audio_set_channels(int index)
286     {
287     }
288    
289    
290     /*
291     * Get/set audio info
292     */
293    
294     bool audio_get_main_mute(void)
295     {
296     return false;
297     }
298    
299     uint32 audio_get_main_volume(void)
300     {
301     if (audio_open) {
302     while (send_data(am_thread, MSG_GET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
303     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
304     return int(am_volume * 256.0) * 0x00010001;
305     } else
306     return 0x01000100;
307     }
308    
309     bool audio_get_dac_mute(void)
310     {
311     return false;
312     }
313    
314     uint32 audio_get_dac_volume(void)
315     {
316     return 0x01000100;
317     }
318    
319     void audio_set_main_mute(bool mute)
320     {
321     }
322    
323     void audio_set_main_volume(uint32 vol)
324     {
325     if (audio_open) {
326     am_volume = float((vol >> 16) + (vol & 0xffff)) / 512.0;
327     while (send_data(am_thread, MSG_SET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
328     while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
329     }
330     }
331    
332     void audio_set_dac_mute(bool mute)
333     {
334     }
335    
336     void audio_set_dac_volume(uint32 vol)
337     {
338     }