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