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