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