1 /* 2 * Copyright 2009, Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marcus Overhagen 7 * Michael Lotz <mmlr@mlotz.ch> 8 */ 9 10 #include <Sound.h> 11 #include <File.h> 12 13 #include "TrackReader.h" 14 15 #include <debug.h> 16 #include <new> 17 #include <string.h> 18 19 20 BSound::BSound(void *data, size_t size, const media_raw_audio_format &format, 21 bool freeWhenDone) 22 : fData(data), 23 fDataSize(size), 24 fFile(NULL), 25 fRefCount(1), 26 fStatus(B_NO_INIT), 27 fFormat(format), 28 fFreeWhenDone(freeWhenDone), 29 fTrackReader(NULL) 30 { 31 if (fData == NULL) 32 return; 33 34 fStatus = B_OK; 35 } 36 37 38 BSound::BSound(const entry_ref *soundFile, bool loadIntoMemory) 39 : fData(NULL), 40 fDataSize(0), 41 fFile(new(std::nothrow) BFile(soundFile, B_READ_ONLY)), 42 fRefCount(1), 43 fStatus(B_NO_INIT), 44 fFreeWhenDone(false), 45 fTrackReader(NULL) 46 { 47 if (fFile == NULL) { 48 fStatus = B_NO_MEMORY; 49 return; 50 } 51 52 fStatus = fFile->InitCheck(); 53 if (fStatus != B_OK) 54 return; 55 56 memset(&fFormat, 0, sizeof(fFormat)); 57 fTrackReader = new(std::nothrow) BPrivate::BTrackReader(fFile, fFormat); 58 if (fTrackReader == NULL) { 59 fStatus = B_NO_MEMORY; 60 return; 61 } 62 63 fStatus = fTrackReader->InitCheck(); 64 if (fStatus != B_OK) 65 return; 66 67 fFormat = fTrackReader->Format(); 68 fStatus = B_OK; 69 } 70 71 72 BSound::BSound(const media_raw_audio_format &format) 73 : fData(NULL), 74 fDataSize(0), 75 fFile(NULL), 76 fRefCount(1), 77 fStatus(B_ERROR), 78 fFormat(format), 79 fFreeWhenDone(false), 80 fTrackReader(NULL) 81 { 82 // unimplemented protected constructor 83 UNIMPLEMENTED(); 84 } 85 86 87 BSound::~BSound() 88 { 89 delete fTrackReader; 90 delete fFile; 91 92 if (fFreeWhenDone) 93 free(fData); 94 } 95 96 97 status_t 98 BSound::InitCheck() 99 { 100 return fStatus; 101 } 102 103 104 BSound * 105 BSound::AcquireRef() 106 { 107 atomic_add(&fRefCount, 1); 108 return this; 109 } 110 111 bool 112 BSound::ReleaseRef() 113 { 114 if (atomic_add(&fRefCount, -1) == 1) { 115 delete this; 116 return false; 117 } 118 119 // TODO: verify those returns 120 return true; 121 } 122 123 124 int32 125 BSound::RefCount() const 126 { 127 return fRefCount; 128 } 129 130 131 bigtime_t 132 BSound::Duration() const 133 { 134 UNIMPLEMENTED(); 135 return 0; 136 } 137 138 139 const media_raw_audio_format & 140 BSound::Format() const 141 { 142 return fFormat; 143 } 144 145 146 const void * 147 BSound::Data() const 148 { 149 return fData; 150 } 151 152 153 off_t 154 BSound::Size() const 155 { 156 if (fFile != NULL) { 157 off_t result = 0; 158 fFile->GetSize(&result); 159 return result; 160 } 161 162 return fDataSize; 163 } 164 165 166 bool 167 BSound::GetDataAt(off_t offset, void *intoBuffer, size_t bufferSize, 168 size_t *outUsed) 169 { 170 if (intoBuffer == NULL) 171 return false; 172 173 if (fData != NULL) { 174 size_t copySize = MIN(bufferSize, fDataSize - offset); 175 memcpy(intoBuffer, (uint8 *)fData + offset, copySize); 176 if (outUsed != NULL) 177 *outUsed = copySize; 178 return true; 179 } 180 181 if (fTrackReader != NULL) { 182 int32 frameSize = fTrackReader->FrameSize(); 183 int64 frameCount = fTrackReader->CountFrames(); 184 int64 startFrame = offset / frameSize; 185 if (startFrame > frameCount) 186 return false; 187 188 if (fTrackReader->SeekToFrame(&startFrame) != B_OK) 189 return false; 190 191 off_t bufferOffset = offset - startFrame * frameSize; 192 int64 directStartFrame = (offset + frameSize - 1) / frameSize; 193 int64 directFrameCount = (offset + bufferSize - directStartFrame 194 * frameSize) / frameSize; 195 196 if (bufferOffset != 0) { 197 int64 indirectFrameCount = directStartFrame - startFrame; 198 size_t indirectSize = indirectFrameCount * frameSize; 199 void *buffer = malloc(indirectSize); 200 if (buffer == NULL) 201 return false; 202 203 if (fTrackReader->ReadFrames(buffer, indirectFrameCount) != B_OK) 204 return false; 205 206 memcpy(intoBuffer, (uint8 *)buffer + bufferOffset, 207 indirectSize - bufferOffset); 208 if (outUsed != NULL) 209 *outUsed = indirectSize - bufferOffset; 210 211 free(buffer); 212 } else if (outUsed != NULL) 213 *outUsed = 0; 214 215 if (fTrackReader->ReadFrames((uint8 *)intoBuffer + bufferOffset, 216 directFrameCount) != B_OK) 217 return false; 218 219 if (outUsed != NULL) 220 *outUsed += directFrameCount * frameSize; 221 222 return true; 223 } 224 225 return false; 226 } 227 228 229 status_t 230 BSound::BindTo(BSoundPlayer *player, const media_raw_audio_format &format) 231 { 232 UNIMPLEMENTED(); 233 return B_ERROR; 234 } 235 236 237 status_t 238 BSound::UnbindFrom(BSoundPlayer *player) 239 { 240 UNIMPLEMENTED(); 241 return B_ERROR; 242 } 243 244 245 status_t 246 BSound::Perform(int32 code, ...) 247 { 248 UNIMPLEMENTED(); 249 return B_ERROR; 250 } 251 252 253 status_t BSound::_Reserved_Sound_0(void *) { return B_ERROR; } 254 status_t BSound::_Reserved_Sound_1(void *) { return B_ERROR; } 255 status_t BSound::_Reserved_Sound_2(void *) { return B_ERROR; } 256 status_t BSound::_Reserved_Sound_3(void *) { return B_ERROR; } 257 status_t BSound::_Reserved_Sound_4(void *) { return B_ERROR; } 258 status_t BSound::_Reserved_Sound_5(void *) { return B_ERROR; } 259