1 /*
2 * Copyright 2001-2012 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Christopher ML Zumwalt May (zummy@users.sf.net)
7 */
8
9
10 #include <SimpleGameSound.h>
11
12 #include <Entry.h>
13 #include <MediaFile.h>
14 #include <MediaTrack.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "GameSoundBuffer.h"
19 #include "GameSoundDefs.h"
20 #include "GameSoundDevice.h"
21 #include "GSUtility.h"
22
23
BSimpleGameSound(const entry_ref * inFile,BGameSoundDevice * device)24 BSimpleGameSound::BSimpleGameSound(const entry_ref *inFile,
25 BGameSoundDevice *device)
26 :
27 BGameSound(device)
28 {
29 if (InitCheck() == B_OK)
30 SetInitError(Init(inFile));
31 }
32
33
BSimpleGameSound(const char * inFile,BGameSoundDevice * device)34 BSimpleGameSound::BSimpleGameSound(const char *inFile, BGameSoundDevice *device)
35 :
36 BGameSound(device)
37 {
38 if (InitCheck() == B_OK) {
39 entry_ref file;
40
41 if (get_ref_for_path(inFile, &file) != B_OK)
42 SetInitError(B_ENTRY_NOT_FOUND);
43 else
44 SetInitError(Init(&file));
45 }
46 }
47
48
BSimpleGameSound(const void * inData,size_t inFrameCount,const gs_audio_format * format,BGameSoundDevice * device)49 BSimpleGameSound::BSimpleGameSound(const void *inData, size_t inFrameCount,
50 const gs_audio_format *format, BGameSoundDevice *device)
51 :
52 BGameSound(device)
53 {
54 if (InitCheck() != B_OK)
55 return;
56
57 gs_audio_format actual = *format;
58 if (actual.byte_order == 0)
59 actual.byte_order = B_MEDIA_HOST_ENDIAN;
60
61 size_t frameSize
62 = get_sample_size(format->format) * format->channel_count;
63 uchar * data = new uchar[inFrameCount * frameSize];
64 memcpy(data, inData, inFrameCount * frameSize);
65
66 SetInitError(Init(data, inFrameCount, &actual));
67 }
68
69
BSimpleGameSound(const BSimpleGameSound & other)70 BSimpleGameSound::BSimpleGameSound(const BSimpleGameSound &other)
71 :
72 BGameSound(other)
73 {
74 gs_audio_format format;
75 void *data = NULL;
76
77 status_t error = other.Device()->Buffer(other.ID(), &format, data);
78 if (error != B_OK)
79 SetInitError(error);
80
81 Init(data, 0, &format);
82 free(data);
83 }
84
85
~BSimpleGameSound()86 BSimpleGameSound::~BSimpleGameSound()
87 {
88 }
89
90
91 BGameSound *
Clone() const92 BSimpleGameSound::Clone() const
93 {
94 gs_audio_format format;
95 void *data = NULL;
96
97 status_t error = Device()->Buffer(ID(), &format, data);
98 if (error != B_OK)
99 return NULL;
100
101 BSimpleGameSound *clone = new BSimpleGameSound(data, 0, &format, Device());
102 free(data);
103
104 return clone;
105 }
106
107
108 /* virtual */ status_t
Perform(int32 selector,void * data)109 BSimpleGameSound::Perform(int32 selector, void * data)
110 {
111 return B_ERROR;
112 }
113
114
115 status_t
SetIsLooping(bool looping)116 BSimpleGameSound::SetIsLooping(bool looping)
117 {
118 gs_attribute attribute;
119
120 attribute.attribute = B_GS_LOOPING;
121 attribute.value = (looping) ? -1.0 : 0.0;
122 attribute.duration = bigtime_t(0);
123 attribute.flags = 0;
124
125 return Device()->SetAttributes(ID(), &attribute, 1);
126 }
127
128
129 bool
IsLooping() const130 BSimpleGameSound::IsLooping() const
131 {
132 gs_attribute attribute;
133
134 attribute.attribute = B_GS_LOOPING;
135 attribute.flags = 0;
136
137 if (Device()->GetAttributes(ID(), &attribute, 1) != B_OK)
138 return false;
139
140 return bool(attribute.value);
141 }
142
143
144 status_t
Init(const entry_ref * inFile)145 BSimpleGameSound::Init(const entry_ref* inFile)
146 {
147 BMediaFile file(inFile);
148 gs_audio_format gsformat;
149 media_format mformat;
150 int64 framesRead, framesTotal = 0;
151
152 if (file.InitCheck() != B_OK)
153 return file.InitCheck();
154
155 BMediaTrack* audioStream = file.TrackAt(0);
156 audioStream->EncodedFormat(&mformat);
157 if (!mformat.IsAudio())
158 return B_ERROR;
159
160 int64 frames = audioStream->CountFrames();
161
162 mformat.Clear();
163 mformat.type = B_MEDIA_RAW_AUDIO;
164 // mformat.u.raw_audio.byte_order
165 // = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
166 status_t error = audioStream->DecodedFormat(&mformat);
167 if (error != B_OK)
168 return error;
169
170 memset(&gsformat, 0, sizeof(gs_audio_format));
171 media_to_gs_format(&gsformat, &mformat.u.raw_audio);
172
173 if (mformat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_CHAR) {
174 // The GameKit doesnt support this format so we will have to reformat
175 // the data into something the GameKit does support.
176 char * buffer = new char[gsformat.buffer_size];
177 uchar * data = new uchar[frames * gsformat.channel_count];
178
179 while (framesTotal < frames) {
180 // read the next chunck from the stream
181 memset(buffer, 0, gsformat.buffer_size);
182 audioStream->ReadFrames(buffer, &framesRead);
183
184 // refomat the buffer from
185 int64 position = framesTotal * gsformat.channel_count;
186 for (int32 i = 0; i < (int32)gsformat.buffer_size; i++)
187 data[i + position] = buffer[i] + 128;
188
189 framesTotal += framesRead;
190 }
191 delete [] buffer;
192
193 gsformat.format = gs_audio_format::B_GS_U8;
194
195 error = Init(data, frames, &gsformat);
196
197 // free the buffers we no longer need
198 } else {
199 // We need to determine the size, in bytes, of a single sample.
200 // At the same time, we will store the format of the audio buffer
201 size_t frameSize
202 = get_sample_size(gsformat.format) * gsformat.channel_count;
203 char * data = new char[frames * frameSize];
204 gsformat.buffer_size = frames * frameSize;
205
206 while (framesTotal < frames) {
207 char * position = &data[framesTotal * frameSize];
208 audioStream->ReadFrames(position, &framesRead);
209
210 framesTotal += framesRead;
211 }
212
213 error = Init(data, frames, &gsformat);
214 }
215
216 file.ReleaseTrack(audioStream);
217 return error;
218 }
219
220
221 status_t
Init(const void * inData,int64 inFrameCount,const gs_audio_format * format)222 BSimpleGameSound::Init(const void* inData, int64 inFrameCount,
223 const gs_audio_format* format)
224 {
225 gs_id sound;
226
227 status_t error
228 = Device()->CreateBuffer(&sound, format, inData, inFrameCount);
229 if (error != B_OK)
230 return error;
231
232 BGameSound::Init(sound);
233
234 return B_OK;
235 }
236
237
238 /* unimplemented for protection of the user:
239 *
240 * BSimpleGameSound::BSimpleGameSound()
241 * BSimpleGameSound &BSimpleGameSound::operator=(const BSimpleGameSound &)
242 */
243
244
245 status_t
_Reserved_BSimpleGameSound_0(int32 arg,...)246 BSimpleGameSound::_Reserved_BSimpleGameSound_0(int32 arg, ...)
247 {
248 return B_ERROR;
249 }
250
251
252 status_t
_Reserved_BSimpleGameSound_1(int32 arg,...)253 BSimpleGameSound::_Reserved_BSimpleGameSound_1(int32 arg, ...)
254 {
255 return B_ERROR;
256 }
257
258
259 status_t
_Reserved_BSimpleGameSound_2(int32 arg,...)260 BSimpleGameSound::_Reserved_BSimpleGameSound_2(int32 arg, ...)
261 {
262 return B_ERROR;
263 }
264
265
266 status_t
_Reserved_BSimpleGameSound_3(int32 arg,...)267 BSimpleGameSound::_Reserved_BSimpleGameSound_3(int32 arg, ...)
268 {
269 return B_ERROR;
270 }
271
272
273 status_t
_Reserved_BSimpleGameSound_4(int32 arg,...)274 BSimpleGameSound::_Reserved_BSimpleGameSound_4(int32 arg, ...)
275 {
276 return B_ERROR;
277 }
278
279
280 status_t
_Reserved_BSimpleGameSound_5(int32 arg,...)281 BSimpleGameSound::_Reserved_BSimpleGameSound_5(int32 arg, ...)
282 {
283 return B_ERROR;
284 }
285
286
287 status_t
_Reserved_BSimpleGameSound_6(int32 arg,...)288 BSimpleGameSound::_Reserved_BSimpleGameSound_6(int32 arg, ...)
289 {
290 return B_ERROR;
291 }
292
293
294 status_t
_Reserved_BSimpleGameSound_7(int32 arg,...)295 BSimpleGameSound::_Reserved_BSimpleGameSound_7(int32 arg, ...)
296 {
297 return B_ERROR;
298 }
299
300
301 status_t
_Reserved_BSimpleGameSound_8(int32 arg,...)302 BSimpleGameSound::_Reserved_BSimpleGameSound_8(int32 arg, ...)
303 {
304 return B_ERROR;
305 }
306
307
308 status_t
_Reserved_BSimpleGameSound_9(int32 arg,...)309 BSimpleGameSound::_Reserved_BSimpleGameSound_9(int32 arg, ...)
310 {
311 return B_ERROR;
312 }
313
314
315 status_t
_Reserved_BSimpleGameSound_10(int32 arg,...)316 BSimpleGameSound::_Reserved_BSimpleGameSound_10(int32 arg, ...)
317 {
318 return B_ERROR;
319 }
320
321
322 status_t
_Reserved_BSimpleGameSound_11(int32 arg,...)323 BSimpleGameSound::_Reserved_BSimpleGameSound_11(int32 arg, ...)
324 {
325 return B_ERROR;
326 }
327
328
329 status_t
_Reserved_BSimpleGameSound_12(int32 arg,...)330 BSimpleGameSound::_Reserved_BSimpleGameSound_12(int32 arg, ...)
331 {
332 return B_ERROR;
333 }
334
335
336 status_t
_Reserved_BSimpleGameSound_13(int32 arg,...)337 BSimpleGameSound::_Reserved_BSimpleGameSound_13(int32 arg, ...)
338 {
339 return B_ERROR;
340 }
341
342
343 status_t
_Reserved_BSimpleGameSound_14(int32 arg,...)344 BSimpleGameSound::_Reserved_BSimpleGameSound_14(int32 arg, ...)
345 {
346 return B_ERROR;
347 }
348
349
350 status_t
_Reserved_BSimpleGameSound_15(int32 arg,...)351 BSimpleGameSound::_Reserved_BSimpleGameSound_15(int32 arg, ...)
352 {
353 return B_ERROR;
354 }
355
356
357 status_t
_Reserved_BSimpleGameSound_16(int32 arg,...)358 BSimpleGameSound::_Reserved_BSimpleGameSound_16(int32 arg, ...)
359 {
360 return B_ERROR;
361 }
362
363
364 status_t
_Reserved_BSimpleGameSound_17(int32 arg,...)365 BSimpleGameSound::_Reserved_BSimpleGameSound_17(int32 arg, ...)
366 {
367 return B_ERROR;
368 }
369
370
371 status_t
_Reserved_BSimpleGameSound_18(int32 arg,...)372 BSimpleGameSound::_Reserved_BSimpleGameSound_18(int32 arg, ...)
373 {
374 return B_ERROR;
375 }
376
377
378 status_t
_Reserved_BSimpleGameSound_19(int32 arg,...)379 BSimpleGameSound::_Reserved_BSimpleGameSound_19(int32 arg, ...)
380 {
381 return B_ERROR;
382 }
383
384
385 status_t
_Reserved_BSimpleGameSound_20(int32 arg,...)386 BSimpleGameSound::_Reserved_BSimpleGameSound_20(int32 arg, ...)
387 {
388 return B_ERROR;
389 }
390
391
392 status_t
_Reserved_BSimpleGameSound_21(int32 arg,...)393 BSimpleGameSound::_Reserved_BSimpleGameSound_21(int32 arg, ...)
394 {
395 return B_ERROR;
396 }
397
398
399 status_t
_Reserved_BSimpleGameSound_22(int32 arg,...)400 BSimpleGameSound::_Reserved_BSimpleGameSound_22(int32 arg, ...)
401 {
402 return B_ERROR;
403 }
404
405
406 status_t
_Reserved_BSimpleGameSound_23(int32 arg,...)407 BSimpleGameSound::_Reserved_BSimpleGameSound_23(int32 arg, ...)
408 {
409 return B_ERROR;
410 }
411