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