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
BSoundFile()18 BSoundFile::BSoundFile()
19 {
20 _init_raw_stats();
21 }
22
23
BSoundFile(const entry_ref * ref,uint32 open_mode)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 */
~BSoundFile()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
InitCheck() const41 BSoundFile::InitCheck() const
42 {
43 if (!fSoundFile) {
44 return B_NO_INIT;
45 }
46 return fSoundFile->InitCheck();
47 }
48
49
50 status_t
SetTo(const entry_ref * ref,uint32 open_mode)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
FileFormat() const79 BSoundFile::FileFormat() const
80 {
81 return fFileFormat;
82 }
83
84
85 int32
SamplingRate() const86 BSoundFile::SamplingRate() const
87 {
88 return fSamplingRate;
89 }
90
91
92 int32
CountChannels() const93 BSoundFile::CountChannels() const
94 {
95 return fChannelCount;
96 }
97
98
99 int32
SampleSize() const100 BSoundFile::SampleSize() const
101 {
102 return fSampleSize;
103 }
104
105
106 int32
ByteOrder() const107 BSoundFile::ByteOrder() const
108 {
109 return fByteOrder;
110 }
111
112
113 int32
SampleFormat() const114 BSoundFile::SampleFormat() const
115 {
116 return fSampleFormat;
117 }
118
119
120 int32
FrameSize() const121 BSoundFile::FrameSize() const
122 {
123 return fSampleSize * fChannelCount;
124 }
125
126
127 off_t
CountFrames() const128 BSoundFile::CountFrames() const
129 {
130 return fFrameCount;
131 }
132
133
134 bool
IsCompressed() const135 BSoundFile::IsCompressed() const
136 {
137 return fIsCompressed;
138 }
139
140
141 int32
CompressionType() const142 BSoundFile::CompressionType() const
143 {
144 return fCompressionType;
145 }
146
147
148 char *
CompressionName() const149 BSoundFile::CompressionName() const
150 {
151 return fCompressionName;
152 }
153
154
155 /* virtual */ int32
SetFileFormat(int32 format)156 BSoundFile::SetFileFormat(int32 format)
157 {
158 fFileFormat = format;
159 return fFileFormat;
160 }
161
162
163 /* virtual */ int32
SetSamplingRate(int32 fps)164 BSoundFile::SetSamplingRate(int32 fps)
165 {
166 fSamplingRate = fps;
167 return fSamplingRate;
168 }
169
170
171 /* virtual */ int32
SetChannelCount(int32 spf)172 BSoundFile::SetChannelCount(int32 spf)
173 {
174 fChannelCount = spf;
175 return fChannelCount;
176 }
177
178
179 /* virtual */ int32
SetSampleSize(int32 bps)180 BSoundFile::SetSampleSize(int32 bps)
181 {
182 fSampleSize = bps;
183 return fSampleSize;
184 }
185
186
187 /* virtual */ int32
SetByteOrder(int32 bord)188 BSoundFile::SetByteOrder(int32 bord)
189 {
190 fByteOrder = bord;
191 return fByteOrder;
192 }
193
194
195 /* virtual */ int32
SetSampleFormat(int32 fmt)196 BSoundFile::SetSampleFormat(int32 fmt)
197 {
198 fSampleFormat = fmt;
199 return fSampleFormat;
200 }
201
202
203 /* virtual */ int32
SetCompressionType(int32 type)204 BSoundFile::SetCompressionType(int32 type)
205 {
206 return 0;
207 }
208
209
210 /* virtual */ char *
SetCompressionName(char * name)211 BSoundFile::SetCompressionName(char *name)
212 {
213 return NULL;
214 }
215
216
217 /* virtual */ bool
SetIsCompressed(bool tf)218 BSoundFile::SetIsCompressed(bool tf)
219 {
220 return false;
221 }
222
223
224 /* virtual */ off_t
SetDataLocation(off_t offset)225 BSoundFile::SetDataLocation(off_t offset)
226 {
227 UNIMPLEMENTED();
228
229 return 0;
230 }
231
232
233 /* virtual */ off_t
SetFrameCount(off_t count)234 BSoundFile::SetFrameCount(off_t count)
235 {
236 fFrameCount = count;
237 return fFrameCount;
238 }
239
240
241 size_t
ReadFrames(char * buf,size_t count)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
WriteFrames(char * buf,size_t count)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
SeekToFrame(off_t n)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
FrameIndex() const286 BSoundFile::FrameIndex() const
287 {
288 return fFrameIndex;
289 }
290
291
292 off_t
FramesRemaining() const293 BSoundFile::FramesRemaining() const
294 {
295 return fFrameCount - FrameIndex();
296 }
297
298 /*************************************************************
299 * private BSoundFile
300 *************************************************************/
301
302
_ReservedSoundFile1()303 void BSoundFile::_ReservedSoundFile1() {}
_ReservedSoundFile2()304 void BSoundFile::_ReservedSoundFile2() {}
_ReservedSoundFile3()305 void BSoundFile::_ReservedSoundFile3() {}
306
307 void
_init_raw_stats()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
_ParseMimeType(char * mime_type)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
_ref_to_file(const entry_ref * ref)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