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