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