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 18BSoundFile::BSoundFile() 19{ 20 _init_raw_stats(); 21} 22 23 24BSoundFile::BSoundFile(const entry_ref *ref, 25 uint32 open_mode) 26{ 27 _init_raw_stats(); 28 SetTo(ref,open_mode); 29} 30 31/* virtual */ 32BSoundFile::~BSoundFile() 33{ 34 delete fSoundFile; 35 delete fMediaFile; 36 // fMediaTrack will be deleted by the BMediaFile destructor 37} 38 39 40status_t 41BSoundFile::InitCheck() const 42{ 43 if (!fSoundFile) { 44 return B_NO_INIT; 45 } 46 return fSoundFile->InitCheck(); 47} 48 49 50status_t 51BSoundFile::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 78int32 79BSoundFile::FileFormat() const 80{ 81 return fFileFormat; 82} 83 84 85int32 86BSoundFile::SamplingRate() const 87{ 88 return fSamplingRate; 89} 90 91 92int32 93BSoundFile::CountChannels() const 94{ 95 return fChannelCount; 96} 97 98 99int32 100BSoundFile::SampleSize() const 101{ 102 return fSampleSize; 103} 104 105 106int32 107BSoundFile::ByteOrder() const 108{ 109 return fByteOrder; 110} 111 112 113int32 114BSoundFile::SampleFormat() const 115{ 116 return fSampleFormat; 117} 118 119 120int32 121BSoundFile::FrameSize() const 122{ 123 return fSampleSize * fChannelCount; 124} 125 126 127off_t 128BSoundFile::CountFrames() const 129{ 130 return fFrameCount; 131} 132 133 134bool 135BSoundFile::IsCompressed() const 136{ 137 return fIsCompressed; 138} 139 140 141int32 142BSoundFile::CompressionType() const 143{ 144 return fCompressionType; 145} 146 147 148char * 149BSoundFile::CompressionName() const 150{ 151 return fCompressionName; 152} 153 154 155/* virtual */ int32 156BSoundFile::SetFileFormat(int32 format) 157{ 158 fFileFormat = format; 159 return fFileFormat; 160} 161 162 163/* virtual */ int32 164BSoundFile::SetSamplingRate(int32 fps) 165{ 166 fSamplingRate = fps; 167 return fSamplingRate; 168} 169 170 171/* virtual */ int32 172BSoundFile::SetChannelCount(int32 spf) 173{ 174 fChannelCount = spf; 175 return fChannelCount; 176} 177 178 179/* virtual */ int32 180BSoundFile::SetSampleSize(int32 bps) 181{ 182 fSampleSize = bps; 183 return fSampleSize; 184} 185 186 187/* virtual */ int32 188BSoundFile::SetByteOrder(int32 bord) 189{ 190 fByteOrder = bord; 191 return fByteOrder; 192} 193 194 195/* virtual */ int32 196BSoundFile::SetSampleFormat(int32 fmt) 197{ 198 fSampleFormat = fmt; 199 return fSampleFormat; 200} 201 202 203/* virtual */ int32 204BSoundFile::SetCompressionType(int32 type) 205{ 206 return 0; 207} 208 209 210/* virtual */ char * 211BSoundFile::SetCompressionName(char *name) 212{ 213 return NULL; 214} 215 216 217/* virtual */ bool 218BSoundFile::SetIsCompressed(bool tf) 219{ 220 return false; 221} 222 223 224/* virtual */ off_t 225BSoundFile::SetDataLocation(off_t offset) 226{ 227 UNIMPLEMENTED(); 228 229 return 0; 230} 231 232 233/* virtual */ off_t 234BSoundFile::SetFrameCount(off_t count) 235{ 236 fFrameCount = count; 237 return fFrameCount; 238} 239 240 241size_t 242BSoundFile::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 263size_t 264BSoundFile::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 273BSoundFile::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 285off_t 286BSoundFile::FrameIndex() const 287{ 288 return fFrameIndex; 289} 290 291 292off_t 293BSoundFile::FramesRemaining() const 294{ 295 return fFrameCount - FrameIndex(); 296} 297 298/************************************************************* 299 * private BSoundFile 300 *************************************************************/ 301 302 303void BSoundFile::_ReservedSoundFile1() {} 304void BSoundFile::_ReservedSoundFile2() {} 305void BSoundFile::_ReservedSoundFile3() {} 306 307void 308BSoundFile::_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 327static 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 338status_t 339BSoundFile::_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