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