xref: /haiku/src/kits/game/SimpleGameSound.cpp (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		SimpleGameSound.h
23 //	Author:			Christopher ML Zumwalt May (zummy@users.sf.net)
24 //	Description:	BSimpleGameSound is a class for sound effects that are
25 //					short, and consists of non-changing samples in memory.
26 //------------------------------------------------------------------------------
27 
28 #include <malloc.h>
29 #include <memory.h>
30 
31 #include <Entry.h>
32 #include <MediaFile.h>
33 #include <MediaTrack.h>
34 
35 #include "GameSoundDefs.h"
36 #include "GameSoundBuffer.h"
37 #include "GameSoundDevice.h"
38 #include "GSUtility.h"
39 
40 #include <SimpleGameSound.h>
41 
42 BSimpleGameSound::BSimpleGameSound(const entry_ref *inFile,
43 								   BGameSoundDevice *device)
44  		:	BGameSound(device)
45 {
46 	if (InitCheck() == B_OK) SetInitError(Init(inFile));
47 }
48 
49 
50 BSimpleGameSound::BSimpleGameSound(const char *inFile,
51 								   BGameSoundDevice *device)
52  		:	BGameSound(device)
53 {
54 	if (InitCheck() == B_OK)
55 	{
56 		entry_ref file;
57 
58 		if (get_ref_for_path(inFile, &file) != B_OK)
59 			SetInitError(B_ENTRY_NOT_FOUND);
60 		else
61 			SetInitError(Init(&file));
62 	}
63 }
64 
65 
66 BSimpleGameSound::BSimpleGameSound(const void *inData,
67 								   size_t inFrameCount,
68 								   const gs_audio_format *format,
69 								   BGameSoundDevice *device)
70  	:	BGameSound(device)
71 {
72 	if (InitCheck() == B_OK) SetInitError(Init(inData, inFrameCount, format));
73 }
74 
75 
76 BSimpleGameSound::BSimpleGameSound(const BSimpleGameSound &other)
77  	:	BGameSound(other)
78 {
79 	gs_audio_format format;
80 	void * data;
81 
82 	status_t error = other.Device()->Buffer(other.ID(), &format, data);
83 	if (error != B_OK) SetInitError(error);
84 
85 	Init(data, 0, &format);
86 	free(data);
87 }
88 
89 BSimpleGameSound::~BSimpleGameSound()
90 {
91 }
92 
93 
94 BGameSound *
95 BSimpleGameSound::Clone() const
96 {
97 	gs_audio_format format;
98 	void * data;
99 
100 	status_t error = Device()->Buffer(ID(), &format, data);
101 	if (error != B_OK) return NULL;
102 
103 	BSimpleGameSound * clone = new BSimpleGameSound(data, 0, &format, Device());
104 
105 	free(data);
106 
107 	return clone;
108 }
109 
110 
111 /* virtual */ status_t
112 BSimpleGameSound::Perform(int32 selector, void * data)
113 {
114 	return B_ERROR;
115 }
116 
117 
118 status_t
119 BSimpleGameSound::SetIsLooping(bool looping)
120 {
121 	gs_attribute attribute;
122 
123 	attribute.attribute = B_GS_LOOPING;
124 	attribute.value = (looping) ? -1.0 : 0.0;
125 	attribute.duration = bigtime_t(0);
126 	attribute.flags = 0;
127 
128 	return Device()->SetAttributes(ID(), &attribute, 1);
129 }
130 
131 
132 bool
133 BSimpleGameSound::IsLooping() const
134 {
135 	gs_attribute attribute;
136 
137 	attribute.attribute = B_GS_LOOPING;
138 	attribute.flags = 0;
139 
140 	if (Device()->GetAttributes(ID(), &attribute, 1) != B_OK)
141 		return false;
142 
143 	return bool(attribute.value);
144 }
145 
146 status_t
147 BSimpleGameSound::Init(const entry_ref* inFile)
148 {
149 	BMediaFile file(inFile);
150 	gs_audio_format gsformat;
151 	media_format mformat;
152 	int64 framesRead, framesTotal = 0;
153 
154 	if (file.InitCheck() != B_OK) return file.InitCheck();
155 
156 	BMediaTrack* audioStream = file.TrackAt(0);
157 	audioStream->EncodedFormat(&mformat);
158 	if (!mformat.IsAudio()) 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 = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
165 	status_t error = audioStream->DecodedFormat(&mformat);
166 	if (error != B_OK) return error;
167 
168 	memset(&gsformat, 0, sizeof(gs_audio_format));
169 	media_to_gs_format(&gsformat, &mformat.u.raw_audio);
170 
171 	if (mformat.u.raw_audio.format == media_raw_audio_format::B_AUDIO_CHAR)
172 	{
173 		// The GameKit doesnt support this format so we will have to reformat
174 		// the data into something the GameKit does support.
175 		char * buffer = new char[gsformat.buffer_size];
176 		uchar * data = new uchar[frames * gsformat.channel_count];
177 
178 		while (framesTotal < frames)
179 		{
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 
192 		gsformat.format = gs_audio_format::B_GS_U8;
193 
194 		error = Init(data, frames, &gsformat);
195 
196 		// free the buffers we no longer need
197 		delete [] buffer;
198 		delete [] data;
199 	}
200 	else
201 	{
202 		// We need to detriman the size, in bytes, of a single sample.
203 		// At the same time, we will store the format of the audio buffer
204 		size_t frameSize = get_sample_size(gsformat.format) * gsformat.channel_count;
205 		char * data = new char[frames * frameSize];
206 		gsformat.buffer_size = frames * frameSize;
207 
208 		while(framesTotal < frames)
209 		{
210 			char * position = &data[framesTotal * frameSize];
211 			audioStream->ReadFrames(position, &framesRead);
212 
213 			framesTotal += framesRead;
214 		}
215 
216 		error = Init(data, frames, &gsformat);
217 
218 		delete [] data;
219 	}
220 
221 	file.ReleaseTrack(audioStream);
222 	return error;
223 }
224 
225 
226 status_t
227 BSimpleGameSound::Init(const void* inData,
228 						int64 inFrameCount,
229 						const gs_audio_format* format)
230 {
231 	gs_id sound;
232 
233 	status_t error = Device()->CreateBuffer(&sound, format, inData, inFrameCount);
234 	if (error != B_OK) return error;
235 
236 	BGameSound::Init(sound);
237 
238 	return B_OK;
239 }
240 
241 
242 /* unimplemented for protection of the user:
243  *
244  * BSimpleGameSound::BSimpleGameSound()
245  * BSimpleGameSound &BSimpleGameSound::operator=(const BSimpleGameSound &)
246  */
247 
248 
249 status_t
250 BSimpleGameSound::_Reserved_BSimpleGameSound_0(int32 arg, ...)
251 {
252 	return B_ERROR;
253 }
254 
255 
256 status_t
257 BSimpleGameSound::_Reserved_BSimpleGameSound_1(int32 arg, ...)
258 {
259 	return B_ERROR;
260 }
261 
262 
263 status_t
264 BSimpleGameSound::_Reserved_BSimpleGameSound_2(int32 arg, ...)
265 {
266 	return B_ERROR;
267 }
268 
269 
270 status_t
271 BSimpleGameSound::_Reserved_BSimpleGameSound_3(int32 arg, ...)
272 {
273 	return B_ERROR;
274 }
275 
276 
277 status_t
278 BSimpleGameSound::_Reserved_BSimpleGameSound_4(int32 arg, ...)
279 {
280 	return B_ERROR;
281 }
282 
283 
284 status_t
285 BSimpleGameSound::_Reserved_BSimpleGameSound_5(int32 arg, ...)
286 {
287 	return B_ERROR;
288 }
289 
290 
291 status_t
292 BSimpleGameSound::_Reserved_BSimpleGameSound_6(int32 arg, ...)
293 {
294 	return B_ERROR;
295 }
296 
297 
298 status_t
299 BSimpleGameSound::_Reserved_BSimpleGameSound_7(int32 arg, ...)
300 {
301 	return B_ERROR;
302 }
303 
304 
305 status_t
306 BSimpleGameSound::_Reserved_BSimpleGameSound_8(int32 arg, ...)
307 {
308 	return B_ERROR;
309 }
310 
311 
312 status_t
313 BSimpleGameSound::_Reserved_BSimpleGameSound_9(int32 arg, ...)
314 {
315 	return B_ERROR;
316 }
317 
318 
319 status_t
320 BSimpleGameSound::_Reserved_BSimpleGameSound_10(int32 arg, ...)
321 {
322 	return B_ERROR;
323 }
324 
325 
326 status_t
327 BSimpleGameSound::_Reserved_BSimpleGameSound_11(int32 arg, ...)
328 {
329 	return B_ERROR;
330 }
331 
332 
333 status_t
334 BSimpleGameSound::_Reserved_BSimpleGameSound_12(int32 arg, ...)
335 {
336 	return B_ERROR;
337 }
338 
339 
340 status_t
341 BSimpleGameSound::_Reserved_BSimpleGameSound_13(int32 arg, ...)
342 {
343 	return B_ERROR;
344 }
345 
346 
347 status_t
348 BSimpleGameSound::_Reserved_BSimpleGameSound_14(int32 arg, ...)
349 {
350 	return B_ERROR;
351 }
352 
353 
354 status_t
355 BSimpleGameSound::_Reserved_BSimpleGameSound_15(int32 arg, ...)
356 {
357 	return B_ERROR;
358 }
359 
360 
361 status_t
362 BSimpleGameSound::_Reserved_BSimpleGameSound_16(int32 arg, ...)
363 {
364 	return B_ERROR;
365 }
366 
367 
368 status_t
369 BSimpleGameSound::_Reserved_BSimpleGameSound_17(int32 arg, ...)
370 {
371 	return B_ERROR;
372 }
373 
374 
375 status_t
376 BSimpleGameSound::_Reserved_BSimpleGameSound_18(int32 arg, ...)
377 {
378 	return B_ERROR;
379 }
380 
381 
382 status_t
383 BSimpleGameSound::_Reserved_BSimpleGameSound_19(int32 arg, ...)
384 {
385 	return B_ERROR;
386 }
387 
388 
389 status_t
390 BSimpleGameSound::_Reserved_BSimpleGameSound_20(int32 arg, ...)
391 {
392 	return B_ERROR;
393 }
394 
395 
396 status_t
397 BSimpleGameSound::_Reserved_BSimpleGameSound_21(int32 arg, ...)
398 {
399 	return B_ERROR;
400 }
401 
402 
403 status_t
404 BSimpleGameSound::_Reserved_BSimpleGameSound_22(int32 arg, ...)
405 {
406 	return B_ERROR;
407 }
408 
409 
410 status_t
411 BSimpleGameSound::_Reserved_BSimpleGameSound_23(int32 arg, ...)
412 {
413 	return B_ERROR;
414 }
415 
416 
417