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 (24 years, 8 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# Content
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 }