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