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