xref: /haiku/src/kits/media/SoundFile.cpp (revision 57ab322d674a58ddfa2c04fc8aa45b8171b2bf08)
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