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