1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * BeOS sound driver implementation.
12 *
13 * Originally by Peter Wang, rewritten to use the BSoundPlayer
14 * class by Angelo Mottola.
15 *
16 * See readme.txt for copyright information.
17 */
18
19 #include "bealleg.h"
20 #include "allegro/internal/aintern.h"
21 #include "allegro/platform/aintbeos.h"
22
23 #if !defined ALLEGRO_BEOS && !defined ALLEGRO_HAIKU
24 #error something is wrong with the makefile
25 #endif
26
27 #ifndef SCAN_DEPEND
28 #include <media/SoundPlayer.h>
29 #endif
30
31
32 #ifdef ALLEGRO_BIG_ENDIAN
33 #define BE_SOUND_ENDIAN B_MEDIA_BIG_ENDIAN
34 #else
35 #define BE_SOUND_ENDIAN B_MEDIA_LITTLE_ENDIAN
36 #endif
37
38
39 sem_id _be_sound_stream_lock = -1;
40
41 static bool be_sound_active = false;
42 static bool be_sound_stream_locked = false;
43
44 static BLocker *locker = NULL;
45 static BSoundPlayer *be_sound = NULL;
46
47 static int be_sound_bufsize;
48 static int be_sound_signed;
49
50 static char be_sound_desc[256] = EMPTY_STRING;
51
52
53
54 /* be_sound_handler:
55 * Update data.
56 */
be_sound_handler(void * cookie,void * buffer,size_t size,const media_raw_audio_format & format)57 static void be_sound_handler(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format)
58 {
59 locker->Lock();
60 acquire_sem(_be_sound_stream_lock);
61 if (be_sound_active) {
62 _mix_some_samples((unsigned long)buffer, 0, be_sound_signed);
63 }
64 else {
65 memset(buffer, 0, size);
66 }
67 release_sem(_be_sound_stream_lock);
68 locker->Unlock();
69 }
70
71
72
73 /* be_sound_detect.
74 * Return TRUE if sound available.
75 */
be_sound_detect(int input)76 extern "C" int be_sound_detect(int input)
77 {
78 BSoundPlayer *sound;
79 media_raw_audio_format format;
80 status_t status;
81
82 if (input) {
83 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
84 return FALSE;
85 }
86
87 format.frame_rate = 11025;
88 format.channel_count = 1;
89 format.format = media_raw_audio_format::B_AUDIO_UCHAR;
90 format.byte_order = BE_SOUND_ENDIAN;
91 format.buffer_size = 0;
92
93 sound = new BSoundPlayer(&format);
94 status = sound->InitCheck();
95 delete sound;
96
97 return (status == B_OK) ? TRUE : FALSE;
98 }
99
100
101
102 /* be_sound_init:
103 * Init sound driver.
104 */
be_sound_init(int input,int voices)105 extern "C" int be_sound_init(int input, int voices)
106 {
107 media_raw_audio_format format;
108 char tmp1[128], tmp2[128];
109
110 if (input) {
111 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
112 return -1;
113 }
114
115 be_sound_active = false;
116
117 /* create BPushGameSound instance */
118 format.frame_rate = (_sound_freq > 0) ? _sound_freq : 44100;
119 format.channel_count = (_sound_stereo) ? 2 : 1;
120 format.format = (_sound_bits == 8) ? (media_raw_audio_format::B_AUDIO_UCHAR) : (media_raw_audio_format::B_AUDIO_SHORT);
121 format.byte_order = BE_SOUND_ENDIAN;
122 format.buffer_size = 0;
123
124 be_sound = new BSoundPlayer(&format, "Sound player", be_sound_handler);
125
126 if (be_sound->InitCheck() != B_OK) {
127 goto cleanup;
128 }
129
130 /* read the sound format back */
131 format = be_sound->Format();
132
133 switch (format.format) {
134
135 case media_raw_audio_format::B_AUDIO_UCHAR:
136 _sound_bits = 8;
137 be_sound_signed = FALSE;
138 break;
139
140 case media_raw_audio_format::B_AUDIO_SHORT:
141 _sound_bits = 16;
142 be_sound_signed = TRUE;
143 break;
144
145 default:
146 goto cleanup;
147 }
148
149 _sound_stereo = (format.channel_count == 2) ? 1 : 0;
150 _sound_freq = (int)format.frame_rate;
151
152 /* start internal mixer */
153 be_sound_bufsize = format.buffer_size;
154 digi_beos.voices = voices;
155
156 if (_mixer_init(be_sound_bufsize / (_sound_bits / 8), _sound_freq,
157 _sound_stereo, ((_sound_bits == 16) ? 1 : 0),
158 &digi_beos.voices) != 0) {
159 goto cleanup;
160 }
161
162 /* start audio output */
163 locker = new BLocker();
164 if (!locker)
165 goto cleanup;
166
167 be_sound->Start();
168 be_sound->SetHasData(true);
169
170 uszprintf(be_sound_desc, sizeof(be_sound_desc), get_config_text("%d bits, %s, %d bps, %s"),
171 _sound_bits, uconvert_ascii(be_sound_signed ? "signed" : "unsigned", tmp1),
172 _sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp2));
173
174 digi_driver->desc = be_sound_desc;
175 be_sound_active = true;
176
177 return 0;
178
179 cleanup: {
180 be_sound_exit(input);
181 return -1;
182 }
183 }
184
185
186
187 /* be_sound_exit:
188 * Shutdown sound driver.
189 */
be_sound_exit(int input)190 extern "C" void be_sound_exit(int input)
191 {
192 if (input) {
193 return;
194 }
195 be_sound_active = false;
196 be_sound->Stop();
197
198 acquire_sem(_be_sound_stream_lock);
199 _mixer_exit();
200 release_sem(_be_sound_stream_lock);
201
202 delete be_sound;
203 delete locker;
204
205 be_sound = NULL;
206 locker = NULL;
207 }
208
209
210
211 /* be_sound_lock_voice:
212 * Locks audio stream for exclusive access.
213 */
be_sound_lock_voice(int voice,int start,int end)214 extern "C" void *be_sound_lock_voice(int voice, int start, int end)
215 {
216 if (!be_sound_stream_locked) {
217 be_sound_stream_locked = true;
218 acquire_sem(_be_sound_stream_lock);
219 }
220 return NULL;
221 }
222
223
224
225 /* be_sound_unlock_voice:
226 * Unlocks audio stream.
227 */
be_sound_unlock_voice(int voice)228 void be_sound_unlock_voice(int voice)
229 {
230 if (be_sound_stream_locked) {
231 be_sound_stream_locked = false;
232 release_sem(_be_sound_stream_lock);
233 }
234 }
235
236
237
238 /* be_sound_buffer_size:
239 * Returns the current buffer size, for use by the audiostream code.
240 */
be_sound_buffer_size()241 extern "C" int be_sound_buffer_size()
242 {
243 return be_sound_bufsize / (_sound_bits / 8) / (_sound_stereo ? 2 : 1);
244 }
245
246
247
248 /* be_sound_set_mixer_volume:
249 * Set mixer volume.
250 */
be_sound_set_mixer_volume(int volume)251 extern "C" int be_sound_set_mixer_volume(int volume)
252 {
253 if (!be_sound)
254 return -1;
255
256 be_sound->SetVolume((float)volume / 255.0);
257
258 return 0;
259 }
260
261
262
263 /* be_sound_get_mixer_volume:
264 * Set mixer volume.
265 */
be_sound_get_mixer_volume(void)266 extern "C" int be_sound_get_mixer_volume(void)
267 {
268 if (!be_sound)
269 return -1;
270
271 return (int)(be_sound->Volume() * 255.0);
272 }
273
274
275 /* be_sound_suspend:
276 * Pauses the sound output.
277 */
be_sound_suspend(void)278 extern "C" void be_sound_suspend(void)
279 {
280 if (!be_sound)
281 return;
282 locker->Lock();
283 be_sound_active = false;
284 locker->Unlock();
285 }
286
287
288
289 /* be_sound_resume:
290 * Resumes the sound output.
291 */
be_sound_resume(void)292 extern "C" void be_sound_resume(void)
293 {
294 if (!be_sound)
295 return;
296 locker->Lock();
297 be_sound_active = true;
298 locker->Unlock();
299 }
300