xref: /haiku/src/kits/game/SimpleGameSound.cpp (revision 3ecb7fb4415b319b6aac606551d51efad21037df)
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 		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 
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 
86 BSimpleGameSound::~BSimpleGameSound()
87 {
88 }
89 
90 
91 BGameSound *
92 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
109 BSimpleGameSound::Perform(int32 selector, void * data)
110 {
111 	return B_ERROR;
112 }
113 
114 
115 status_t
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
130 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
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 	memset(&mformat, 0, sizeof(media_format));
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
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
246 BSimpleGameSound::_Reserved_BSimpleGameSound_0(int32 arg, ...)
247 {
248 	return B_ERROR;
249 }
250 
251 
252 status_t
253 BSimpleGameSound::_Reserved_BSimpleGameSound_1(int32 arg, ...)
254 {
255 	return B_ERROR;
256 }
257 
258 
259 status_t
260 BSimpleGameSound::_Reserved_BSimpleGameSound_2(int32 arg, ...)
261 {
262 	return B_ERROR;
263 }
264 
265 
266 status_t
267 BSimpleGameSound::_Reserved_BSimpleGameSound_3(int32 arg, ...)
268 {
269 	return B_ERROR;
270 }
271 
272 
273 status_t
274 BSimpleGameSound::_Reserved_BSimpleGameSound_4(int32 arg, ...)
275 {
276 	return B_ERROR;
277 }
278 
279 
280 status_t
281 BSimpleGameSound::_Reserved_BSimpleGameSound_5(int32 arg, ...)
282 {
283 	return B_ERROR;
284 }
285 
286 
287 status_t
288 BSimpleGameSound::_Reserved_BSimpleGameSound_6(int32 arg, ...)
289 {
290 	return B_ERROR;
291 }
292 
293 
294 status_t
295 BSimpleGameSound::_Reserved_BSimpleGameSound_7(int32 arg, ...)
296 {
297 	return B_ERROR;
298 }
299 
300 
301 status_t
302 BSimpleGameSound::_Reserved_BSimpleGameSound_8(int32 arg, ...)
303 {
304 	return B_ERROR;
305 }
306 
307 
308 status_t
309 BSimpleGameSound::_Reserved_BSimpleGameSound_9(int32 arg, ...)
310 {
311 	return B_ERROR;
312 }
313 
314 
315 status_t
316 BSimpleGameSound::_Reserved_BSimpleGameSound_10(int32 arg, ...)
317 {
318 	return B_ERROR;
319 }
320 
321 
322 status_t
323 BSimpleGameSound::_Reserved_BSimpleGameSound_11(int32 arg, ...)
324 {
325 	return B_ERROR;
326 }
327 
328 
329 status_t
330 BSimpleGameSound::_Reserved_BSimpleGameSound_12(int32 arg, ...)
331 {
332 	return B_ERROR;
333 }
334 
335 
336 status_t
337 BSimpleGameSound::_Reserved_BSimpleGameSound_13(int32 arg, ...)
338 {
339 	return B_ERROR;
340 }
341 
342 
343 status_t
344 BSimpleGameSound::_Reserved_BSimpleGameSound_14(int32 arg, ...)
345 {
346 	return B_ERROR;
347 }
348 
349 
350 status_t
351 BSimpleGameSound::_Reserved_BSimpleGameSound_15(int32 arg, ...)
352 {
353 	return B_ERROR;
354 }
355 
356 
357 status_t
358 BSimpleGameSound::_Reserved_BSimpleGameSound_16(int32 arg, ...)
359 {
360 	return B_ERROR;
361 }
362 
363 
364 status_t
365 BSimpleGameSound::_Reserved_BSimpleGameSound_17(int32 arg, ...)
366 {
367 	return B_ERROR;
368 }
369 
370 
371 status_t
372 BSimpleGameSound::_Reserved_BSimpleGameSound_18(int32 arg, ...)
373 {
374 	return B_ERROR;
375 }
376 
377 
378 status_t
379 BSimpleGameSound::_Reserved_BSimpleGameSound_19(int32 arg, ...)
380 {
381 	return B_ERROR;
382 }
383 
384 
385 status_t
386 BSimpleGameSound::_Reserved_BSimpleGameSound_20(int32 arg, ...)
387 {
388 	return B_ERROR;
389 }
390 
391 
392 status_t
393 BSimpleGameSound::_Reserved_BSimpleGameSound_21(int32 arg, ...)
394 {
395 	return B_ERROR;
396 }
397 
398 
399 status_t
400 BSimpleGameSound::_Reserved_BSimpleGameSound_22(int32 arg, ...)
401 {
402 	return B_ERROR;
403 }
404 
405 
406 status_t
407 BSimpleGameSound::_Reserved_BSimpleGameSound_23(int32 arg, ...)
408 {
409 	return B_ERROR;
410 }
411