xref: /haiku/src/apps/mediaplayer/media_node_framework/audio/AudioFormatConverter.cpp (revision 37c7d5d83a2372a6971e383411d5bacbeef0ebdc)
1 /*
2  * Copyright 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
3  * Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
4  * All rights reserved. Distributed under the terms of the MIT licensce.
5  */
6 
7 
8 #include "AudioFormatConverter.h"
9 
10 #include <ByteOrder.h>
11 #include <MediaDefs.h>
12 
13 
14 //#define TRACE_AUDIO_CONVERTER
15 #ifdef TRACE_AUDIO_CONVERTER
16 #	define TRACE(x...)	printf(x)
17 #else
18 #	define TRACE(x...)
19 #endif
20 
21 
22 struct ReadFloat {
23 	inline int operator()(const void* buffer) const {
24 		// 0 == mid, -1.0 == bottom, 1.0 == top
25 		float b = *(float*)buffer;
26 		if (b < -1.0f)
27 			b = -1.0f;
28 		else if (b > 1.0f)
29 			b = 1.0f;
30 		return (int)((double)b * (double)0x7fffffff);
31 	}
32 };
33 
34 struct ReadInt {
35 	inline int operator()(const void* buffer) const {
36 		// 0 == mid, 0x80000001 == bottom, 0x7fffffff == top
37 		short b = *(int*)buffer;
38 		if (b == 0x80000000)
39 			b++;
40 		return b;
41 	}
42 };
43 
44 struct ReadShort {
45 	inline int operator()(const void* buffer) const {
46 		// 0 == mid, -32767 == bottom, +32767
47 		short b = *(short*)buffer;
48 		if (b == -32768)
49 			b++;
50 		return int(int64(b) * 0x7fffffff / 32767);
51 	}
52 };
53 
54 struct ReadUChar {
55 	inline int operator()(const void* buffer) const {
56 		// 128 == mid, 1 == bottom, 255 == top
57 		uchar b = *(uchar*)buffer;
58 		if (b == 0)
59 			b++;
60 		return int((int64(b) - 0x80) * 0x7fffffff / 127);
61 	}
62 };
63 
64 struct ReadChar {
65 	inline int operator()(const void* buffer) const {
66 		// 0 == mid, -127 == bottom, +127 == top
67 		char b = *(char*)buffer;
68 		if (b == 0)
69 			b++;
70 		return int(int64(b) * 0x7fffffff / 127);
71 	}
72 };
73 
74 struct WriteFloat {
75 	inline void operator()(void* buffer, int value) const {
76 		*(float*)buffer = (double)value / (double)0x7fffffff;
77 	}
78 
79 };
80 
81 struct WriteInt {
82 	inline void operator()(void* buffer, int value) const {
83 		*(int*)buffer = value;
84 	}
85 };
86 
87 struct WriteShort {
88 	inline void operator()(void* buffer, int value) const {
89 		*(short*)buffer = (short)(value / (int)0x10000);
90 	}
91 };
92 
93 struct WriteUChar {
94 	inline void operator()(void* buffer, int value) const {
95 		*(uchar*)buffer = (uchar)(value / (int)0x1000000 + 128);
96 	}
97 };
98 
99 struct WriteChar {
100 	inline void operator()(void* buffer, int value) const {
101 		*(char*)buffer = (char)(value / (int)0x1000000);
102 	}
103 };
104 
105 
106 template<typename ReadT, typename WriteT>
107 static void
108 convert(const ReadT& read, const WriteT& write,
109 		const char* inBuffer, char* outBuffer, int32 frames,
110 		int32 inSampleSize, int32 outSampleSize, int32 channelCount)
111 {
112 	for (int32 i = 0; i < frames; i++) {
113 		for (int32 c = 0; c < channelCount; c++) {
114 			write(outBuffer, read(inBuffer));
115 			inBuffer += inSampleSize;
116 			outBuffer += outSampleSize;
117 		}
118 	}
119 }
120 
121 
122 static void
123 swap_sample_byte_order(void* buffer, uint32 format, size_t length)
124 {
125 	type_code type = B_ANY_TYPE;
126 	switch (format) {
127 		case media_raw_audio_format::B_AUDIO_FLOAT:
128 			type = B_FLOAT_TYPE;
129 			break;
130 		case media_raw_audio_format::B_AUDIO_INT:
131 			type = B_INT32_TYPE;
132 			break;
133 		case media_raw_audio_format::B_AUDIO_SHORT:
134 			type = B_INT16_TYPE;
135 			break;
136 		case media_raw_audio_format::B_AUDIO_UCHAR:
137 			break;
138 		case media_raw_audio_format::B_AUDIO_CHAR:
139 			break;
140 	}
141 	if (type != B_ANY_TYPE)
142 		swap_data(type, buffer, length, B_SWAP_ALWAYS);
143 }
144 
145 
146 // #pragma mark -
147 
148 
149 AudioFormatConverter::AudioFormatConverter(AudioReader* source, uint32 format,
150 		uint32 byte_order)
151 	:
152 	AudioReader(),
153 	fSource(NULL)
154 {
155 	uint32 hostByteOrder
156 		= (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
157 	if (source && source->Format().type == B_MEDIA_RAW_AUDIO
158 		&& source->Format().u.raw_audio.byte_order == hostByteOrder) {
159 		fFormat = source->Format();
160 		fFormat.u.raw_audio.format = format;
161 		fFormat.u.raw_audio.byte_order = byte_order;
162 		int32 inSampleSize = source->Format().u.raw_audio.format
163 			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
164 		int32 outSampleSize = fFormat.u.raw_audio.format
165 			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
166 		if (inSampleSize != outSampleSize) {
167 			fFormat.u.raw_audio.buffer_size
168 				= source->Format().u.raw_audio.buffer_size * outSampleSize
169 				  / inSampleSize;
170 		}
171 	} else
172 		source = NULL;
173 	fSource = source;
174 }
175 
176 
177 AudioFormatConverter::~AudioFormatConverter()
178 {
179 }
180 
181 
182 bigtime_t
183 AudioFormatConverter::InitialLatency() const
184 {
185 	fSource->InitialLatency();
186 }
187 
188 status_t
189 AudioFormatConverter::Read(void* buffer, int64 pos, int64 frames)
190 {
191 	TRACE("AudioFormatConverter::Read(%p, %Ld, %Ld)\n", buffer, pos, frames);
192 	status_t error = InitCheck();
193 	if (error != B_OK) {
194 		TRACE("AudioFormatConverter::Read() done 1\n");
195 		return error;
196 	}
197 	pos += fOutOffset;
198 
199 	if (fFormat.u.raw_audio.format == fSource->Format().u.raw_audio.format
200 		&& fFormat.u.raw_audio.byte_order
201 		   == fSource->Format().u.raw_audio.byte_order) {
202 		TRACE("AudioFormatConverter::Read() done 2\n");
203 		return fSource->Read(buffer, pos, frames);
204 	}
205 
206 
207 	int32 inSampleSize = fSource->Format().u.raw_audio.format
208 		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
209 	int32 outSampleSize = fFormat.u.raw_audio.format
210 		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
211 	int32 channelCount = fFormat.u.raw_audio.channel_count;
212 	int32 inFrameSize = inSampleSize * channelCount;
213 	int32 outFrameSize = outSampleSize * channelCount;
214 	char* reformatBuffer = NULL;
215 	char* inBuffer = (char*)buffer;
216 
217 	#ifdef TRACE_AUDIO_CONVERTER
218 		char formatString[256];
219 		string_for_format(fSource->Format(), formatString, 256);
220 		TRACE("  source format: %s\n", formatString);
221 		TRACE("  in format : format: %lx, sample size: %ld, channels: %ld, "
222 			"byte order: %lu\n", fSource->Format().u.raw_audio.format,
223 			inSampleSize, channelCount,
224 			fSource->Format().u.raw_audio.byte_order);
225 		TRACE("  out format: format: %lx, sample size: %ld, channels: %ld, "
226 			"byte order: %lu\n", fFormat.u.raw_audio.format, outSampleSize,
227 			channelCount, fFormat.u.raw_audio.byte_order);
228 	#endif // TRACE_AUDIO_CONVERTER
229 
230 	if (inSampleSize != outSampleSize) {
231 		reformatBuffer = new char[frames * inFrameSize];
232 		inBuffer = reformatBuffer;
233 	}
234 	error = fSource->Read(inBuffer, pos, frames);
235 	// convert samples to host endianess
236 	uint32 hostByteOrder
237 		= (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
238 	if (fSource->Format().u.raw_audio.byte_order != hostByteOrder) {
239 		swap_sample_byte_order(inBuffer, fSource->Format().u.raw_audio.format,
240 							   frames * inFrameSize);
241 	}
242 	// convert the sample type
243 	switch (fSource->Format().u.raw_audio.format) {
244 		// float
245 		case media_raw_audio_format::B_AUDIO_FLOAT:
246 			switch (fFormat.u.raw_audio.format) {
247 				case media_raw_audio_format::B_AUDIO_FLOAT:
248 					break;
249 				case media_raw_audio_format::B_AUDIO_INT:
250 					convert(ReadFloat(), WriteInt(), inBuffer, (char*)buffer,
251 							frames, inSampleSize, outSampleSize, channelCount);
252 					break;
253 				case media_raw_audio_format::B_AUDIO_SHORT:
254 					convert(ReadFloat(), WriteShort(), inBuffer, (char*)buffer,
255 							frames, inSampleSize, outSampleSize, channelCount);
256 					break;
257 				case media_raw_audio_format::B_AUDIO_UCHAR:
258 					convert(ReadFloat(), WriteUChar(), inBuffer, (char*)buffer,
259 							frames, inSampleSize, outSampleSize, channelCount);
260 					break;
261 				case media_raw_audio_format::B_AUDIO_CHAR:
262 					convert(ReadFloat(), WriteChar(), inBuffer, (char*)buffer,
263 							frames, inSampleSize, outSampleSize, channelCount);
264 					break;
265 			}
266 			break;
267 		// int
268 		case media_raw_audio_format::B_AUDIO_INT:
269 			switch (fFormat.u.raw_audio.format) {
270 				case media_raw_audio_format::B_AUDIO_FLOAT:
271 					convert(ReadInt(), WriteFloat(), inBuffer, (char*)buffer,
272 							frames, inSampleSize, outSampleSize, channelCount);
273 					break;
274 				case media_raw_audio_format::B_AUDIO_INT:
275 					break;
276 				case media_raw_audio_format::B_AUDIO_SHORT:
277 					convert(ReadInt(), WriteShort(), inBuffer, (char*)buffer,
278 							frames, inSampleSize, outSampleSize, channelCount);
279 					break;
280 				case media_raw_audio_format::B_AUDIO_UCHAR:
281 					convert(ReadInt(), WriteUChar(), inBuffer, (char*)buffer,
282 							frames, inSampleSize, outSampleSize, channelCount);
283 					break;
284 				case media_raw_audio_format::B_AUDIO_CHAR:
285 					convert(ReadInt(), WriteChar(), inBuffer, (char*)buffer,
286 							frames, inSampleSize, outSampleSize, channelCount);
287 					break;
288 			}
289 			break;
290 		// short
291 		case media_raw_audio_format::B_AUDIO_SHORT:
292 			switch (fFormat.u.raw_audio.format) {
293 				case media_raw_audio_format::B_AUDIO_FLOAT:
294 					convert(ReadShort(), WriteFloat(), inBuffer, (char*)buffer,
295 							frames, inSampleSize, outSampleSize, channelCount);
296 					break;
297 				case media_raw_audio_format::B_AUDIO_INT:
298 					convert(ReadShort(), WriteInt(), inBuffer, (char*)buffer,
299 							frames, inSampleSize, outSampleSize, channelCount);
300 					break;
301 				case media_raw_audio_format::B_AUDIO_SHORT:
302 					break;
303 				case media_raw_audio_format::B_AUDIO_UCHAR:
304 					convert(ReadShort(), WriteUChar(), inBuffer, (char*)buffer,
305 							frames, inSampleSize, outSampleSize, channelCount);
306 					break;
307 				case media_raw_audio_format::B_AUDIO_CHAR:
308 					convert(ReadShort(), WriteChar(), inBuffer, (char*)buffer,
309 							frames, inSampleSize, outSampleSize, channelCount);
310 					break;
311 			}
312 			break;
313 		// uchar
314 		case media_raw_audio_format::B_AUDIO_UCHAR:
315 			switch (fFormat.u.raw_audio.format) {
316 				case media_raw_audio_format::B_AUDIO_FLOAT:
317 					convert(ReadUChar(), WriteFloat(), inBuffer, (char*)buffer,
318 							frames, inSampleSize, outSampleSize, channelCount);
319 					break;
320 				case media_raw_audio_format::B_AUDIO_INT:
321 					convert(ReadUChar(), WriteInt(), inBuffer, (char*)buffer,
322 							frames, inSampleSize, outSampleSize, channelCount);
323 					break;
324 				case media_raw_audio_format::B_AUDIO_SHORT:
325 					convert(ReadUChar(), WriteShort(), inBuffer, (char*)buffer,
326 							frames, inSampleSize, outSampleSize, channelCount);
327 					break;
328 				case media_raw_audio_format::B_AUDIO_UCHAR:
329 					break;
330 				case media_raw_audio_format::B_AUDIO_CHAR:
331 					convert(ReadUChar(), WriteChar(), inBuffer, (char*)buffer,
332 							frames, inSampleSize, outSampleSize, channelCount);
333 					break;
334 			}
335 			break;
336 		// char
337 		case media_raw_audio_format::B_AUDIO_CHAR:
338 			switch (fFormat.u.raw_audio.format) {
339 				case media_raw_audio_format::B_AUDIO_FLOAT:
340 					convert(ReadChar(), WriteFloat(), inBuffer, (char*)buffer,
341 							frames, inSampleSize, outSampleSize, channelCount);
342 					break;
343 				case media_raw_audio_format::B_AUDIO_INT:
344 					convert(ReadChar(), WriteInt(), inBuffer, (char*)buffer,
345 							frames, inSampleSize, outSampleSize, channelCount);
346 					break;
347 				case media_raw_audio_format::B_AUDIO_SHORT:
348 					convert(ReadChar(), WriteShort(), inBuffer, (char*)buffer,
349 							frames, inSampleSize, outSampleSize, channelCount);
350 					break;
351 				case media_raw_audio_format::B_AUDIO_UCHAR:
352 					convert(ReadChar(), WriteUChar(), inBuffer, (char*)buffer,
353 							frames, inSampleSize, outSampleSize, channelCount);
354 					break;
355 				case media_raw_audio_format::B_AUDIO_CHAR:
356 					break;
357 			}
358 			break;
359 	}
360 	// convert samples to output endianess
361 	if (fFormat.u.raw_audio.byte_order != hostByteOrder) {
362 		swap_sample_byte_order(buffer, fFormat.u.raw_audio.format,
363 							   frames * outFrameSize);
364 	}
365 
366 	delete[] reformatBuffer;
367 	TRACE("AudioFormatConverter::Read() done\n");
368 	return B_OK;
369 }
370 
371 
372 status_t
373 AudioFormatConverter::InitCheck() const
374 {
375 	status_t error = AudioReader::InitCheck();
376 	if (error == B_OK && !fSource)
377 		error = B_NO_INIT;
378 	if (error == B_OK)
379 		error = fSource->InitCheck();
380 	return error;
381 }
382 
383 
384 AudioReader*
385 AudioFormatConverter::Source() const
386 {
387 	return fSource;
388 }
389 
390