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