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