1 /*********************************************************************** 2 * AUTHOR: Marcus Overhagen 3 * FILE: SoundFile.cpp 4 * DESCR: 5 ***********************************************************************/ 6 #include <MediaFile.h> 7 #include <MediaTrack.h> 8 #include <SoundFile.h> 9 10 #include <string.h> 11 12 #include "MediaDebug.h" 13 14 /************************************************************* 15 * public BSoundFile 16 *************************************************************/ 17 18 BSoundFile::BSoundFile() 19 { 20 _init_raw_stats(); 21 } 22 23 24 BSoundFile::BSoundFile(const entry_ref *ref, 25 uint32 open_mode) 26 { 27 _init_raw_stats(); 28 SetTo(ref,open_mode); 29 } 30 31 /* virtual */ 32 BSoundFile::~BSoundFile() 33 { 34 delete fSoundFile; 35 delete fMediaFile; 36 // fMediaTrack will be deleted by the BMediaFile destructor 37 } 38 39 40 status_t 41 BSoundFile::InitCheck() const 42 { 43 if (!fSoundFile) { 44 return B_NO_INIT; 45 } 46 return fSoundFile->InitCheck(); 47 } 48 49 50 status_t 51 BSoundFile::SetTo(const entry_ref *ref, 52 uint32 open_mode) 53 { 54 if (fMediaTrack) { 55 BMediaTrack * track = fMediaTrack; 56 fMediaTrack = 0; 57 fMediaFile->ReleaseTrack(track); 58 } 59 if (fMediaFile) { 60 BMediaFile * file = fMediaFile; 61 fMediaFile = 0; 62 delete file; 63 } 64 if (fSoundFile) { 65 BFile * file = fSoundFile; 66 fSoundFile = 0; 67 delete file; 68 } 69 if (open_mode == B_READ_ONLY) { 70 return _ref_to_file(ref); 71 } else { 72 UNIMPLEMENTED(); 73 return B_ERROR; 74 } 75 } 76 77 78 int32 79 BSoundFile::FileFormat() const 80 { 81 return fFileFormat; 82 } 83 84 85 int32 86 BSoundFile::SamplingRate() const 87 { 88 return fSamplingRate; 89 } 90 91 92 int32 93 BSoundFile::CountChannels() const 94 { 95 return fChannelCount; 96 } 97 98 99 int32 100 BSoundFile::SampleSize() const 101 { 102 return fSampleSize; 103 } 104 105 106 int32 107 BSoundFile::ByteOrder() const 108 { 109 return fByteOrder; 110 } 111 112 113 int32 114 BSoundFile::SampleFormat() const 115 { 116 return fSampleFormat; 117 } 118 119 120 int32 121 BSoundFile::FrameSize() const 122 { 123 return fSampleSize * fChannelCount; 124 } 125 126 127 off_t 128 BSoundFile::CountFrames() const 129 { 130 return fFrameCount; 131 } 132 133 134 bool 135 BSoundFile::IsCompressed() const 136 { 137 return fIsCompressed; 138 } 139 140 141 int32 142 BSoundFile::CompressionType() const 143 { 144 return fCompressionType; 145 } 146 147 148 char * 149 BSoundFile::CompressionName() const 150 { 151 return fCompressionName; 152 } 153 154 155 /* virtual */ int32 156 BSoundFile::SetFileFormat(int32 format) 157 { 158 fFileFormat = format; 159 return fFileFormat; 160 } 161 162 163 /* virtual */ int32 164 BSoundFile::SetSamplingRate(int32 fps) 165 { 166 fSamplingRate = fps; 167 return fSamplingRate; 168 } 169 170 171 /* virtual */ int32 172 BSoundFile::SetChannelCount(int32 spf) 173 { 174 fChannelCount = spf; 175 return fChannelCount; 176 } 177 178 179 /* virtual */ int32 180 BSoundFile::SetSampleSize(int32 bps) 181 { 182 fSampleSize = bps; 183 return fSampleSize; 184 } 185 186 187 /* virtual */ int32 188 BSoundFile::SetByteOrder(int32 bord) 189 { 190 fByteOrder = bord; 191 return fByteOrder; 192 } 193 194 195 /* virtual */ int32 196 BSoundFile::SetSampleFormat(int32 fmt) 197 { 198 fSampleFormat = fmt; 199 return fSampleFormat; 200 } 201 202 203 /* virtual */ int32 204 BSoundFile::SetCompressionType(int32 type) 205 { 206 return 0; 207 } 208 209 210 /* virtual */ char * 211 BSoundFile::SetCompressionName(char *name) 212 { 213 return NULL; 214 } 215 216 217 /* virtual */ bool 218 BSoundFile::SetIsCompressed(bool tf) 219 { 220 return false; 221 } 222 223 224 /* virtual */ off_t 225 BSoundFile::SetDataLocation(off_t offset) 226 { 227 UNIMPLEMENTED(); 228 229 return 0; 230 } 231 232 233 /* virtual */ off_t 234 BSoundFile::SetFrameCount(off_t count) 235 { 236 fFrameCount = count; 237 return fFrameCount; 238 } 239 240 241 size_t 242 BSoundFile::ReadFrames(char *buf, 243 size_t count) 244 { 245 size_t frameRead = 0; 246 int64 frames = count; 247 while (count > 0) { 248 status_t status = fMediaTrack->ReadFrames( 249 reinterpret_cast<void *>(buf), &frames); 250 count -= frames; 251 frameRead += frames; 252 buf += fSampleSize * fChannelCount * frames; 253 if (status != B_OK) { 254 if (frameRead > 0) 255 break; 256 return status; 257 } 258 } 259 return frameRead; 260 } 261 262 263 size_t 264 BSoundFile::WriteFrames(char *buf, 265 size_t count) 266 { 267 return fMediaTrack->WriteFrames( 268 reinterpret_cast<void *>(buf), count); 269 } 270 271 272 /* virtual */ off_t 273 BSoundFile::SeekToFrame(off_t n) 274 { 275 int64 frames = n; 276 status_t status = fMediaTrack->SeekToFrame(&frames); 277 278 if (status != B_OK) 279 return status; 280 281 return frames; 282 } 283 284 285 off_t 286 BSoundFile::FrameIndex() const 287 { 288 return fFrameIndex; 289 } 290 291 292 off_t 293 BSoundFile::FramesRemaining() const 294 { 295 return fFrameCount - FrameIndex(); 296 } 297 298 /************************************************************* 299 * private BSoundFile 300 *************************************************************/ 301 302 303 void BSoundFile::_ReservedSoundFile1() {} 304 void BSoundFile::_ReservedSoundFile2() {} 305 void BSoundFile::_ReservedSoundFile3() {} 306 307 void 308 BSoundFile::_init_raw_stats() 309 { 310 fSoundFile = 0; 311 fMediaFile = 0; 312 fMediaTrack = 0; 313 fFileFormat = B_UNKNOWN_FILE; 314 fSamplingRate = 44100; 315 fChannelCount = 2; 316 fSampleSize = 2; 317 fByteOrder = B_BIG_ENDIAN; 318 fSampleFormat = B_LINEAR_SAMPLES; 319 fFrameCount = 0; 320 fFrameIndex = 0; 321 fIsCompressed = false; 322 fCompressionType = -1; 323 fCompressionName = NULL; 324 } 325 326 327 static int32 328 _ParseMimeType(char *mime_type) 329 { 330 if (strcmp(mime_type, "audio/x-aiff") == 0) 331 return B_AIFF_FILE; 332 if (strcmp(mime_type, "audio/x-wav") == 0) 333 return B_WAVE_FILE; 334 return B_UNKNOWN_FILE; 335 } 336 337 338 status_t 339 BSoundFile::_ref_to_file(const entry_ref *ref) 340 { 341 status_t status; 342 BFile * file = new BFile(ref, B_READ_ONLY); 343 status = file->InitCheck(); 344 if (status != B_OK) { 345 fSoundFile = file; 346 return status; 347 } 348 BMediaFile * media = new BMediaFile(file); 349 status = media->InitCheck(); 350 if (status != B_OK) { 351 delete media; 352 delete file; 353 return status; 354 } 355 media_file_format mfi; 356 media->GetFileFormatInfo(&mfi); 357 switch (mfi.family) { 358 case B_AIFF_FORMAT_FAMILY: fFileFormat = B_AIFF_FILE; break; 359 case B_WAV_FORMAT_FAMILY: fFileFormat = B_WAVE_FILE; break; 360 default: fFileFormat = _ParseMimeType(mfi.mime_type); break; 361 } 362 int trackNum = 0; 363 BMediaTrack * track = 0; 364 media_format mf; 365 while (trackNum < media->CountTracks()) { 366 track = media->TrackAt(trackNum); 367 status = track->DecodedFormat(&mf); 368 if (status != B_OK) { 369 media->ReleaseTrack(track); 370 delete media; 371 delete file; 372 return status; 373 } 374 if (mf.IsAudio()) { 375 break; 376 } 377 media->ReleaseTrack(track); 378 track = 0; 379 } 380 if (track == 0) { 381 delete media; 382 delete file; 383 return B_ERROR; 384 } 385 media_raw_audio_format * raw = 0; 386 if (mf.type == B_MEDIA_ENCODED_AUDIO) { 387 raw = &mf.u.encoded_audio.output; 388 } 389 if (mf.type == B_MEDIA_RAW_AUDIO) { 390 raw = &mf.u.raw_audio; 391 } 392 393 if (raw == NULL) { 394 delete media; 395 delete file; 396 return B_ERROR; 397 } 398 399 fSamplingRate = (int)raw->frame_rate; 400 fChannelCount = raw->channel_count; 401 fSampleSize = raw->format & 0xf; 402 fByteOrder = raw->byte_order; 403 switch (raw->format) { 404 case media_raw_audio_format::B_AUDIO_FLOAT: 405 fSampleFormat = B_FLOAT_SAMPLES; 406 break; 407 case media_raw_audio_format::B_AUDIO_INT: 408 case media_raw_audio_format::B_AUDIO_SHORT: 409 case media_raw_audio_format::B_AUDIO_UCHAR: 410 case media_raw_audio_format::B_AUDIO_CHAR: 411 fSampleFormat = B_LINEAR_SAMPLES; 412 break; 413 default: 414 fSampleFormat = B_UNDEFINED_SAMPLES; 415 } 416 fByteOffset = 0; 417 fFrameCount = track->CountFrames(); 418 fFrameIndex = 0; 419 if (mf.type == B_MEDIA_ENCODED_AUDIO) { 420 fIsCompressed = true; 421 fCompressionType = mf.u.encoded_audio.encoding; 422 } 423 fMediaFile = media; 424 fMediaTrack = track; 425 fSoundFile = file; 426 return B_OK; 427 } 428 429 430