xref: /haiku/src/apps/mediaplayer/media_node_framework/audio/AudioFormatConverter.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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 #	include <stdio.h>
17 #	define TRACE(x...)	printf(x)
18 #else
19 #	define TRACE(x...)
20 #endif
21 
22 
23 struct ReadFloat {
24 	inline int operator()(const void* buffer) const {
25 		// 0 == mid, -1.0 == bottom, 1.0 == top
26 		float b = *(float*)buffer;
27 		if (b < -1.0f)
28 			b = -1.0f;
29 		else if (b > 1.0f)
30 			b = 1.0f;
31 		return (int)((double)b * (double)0x7fffffff);
32 	}
33 };
34 
35 struct ReadInt {
36 	inline int operator()(const void* buffer) const {
37 		// 0 == mid, 0x80000001 == bottom, 0x7fffffff == top
38 		int b = *(int*)buffer;
39 		if (b == INT_MIN)
40 			b++;
41 		return b;
42 	}
43 };
44 
45 struct ReadShort {
46 	inline int operator()(const void* buffer) const {
47 		// 0 == mid, -32767 == bottom, +32767
48 		short b = *(short*)buffer;
49 		if (b == -32768)
50 			b++;
51 		return int(int64(b) * 0x7fffffff / 32767);
52 	}
53 };
54 
55 struct ReadUChar {
56 	inline int operator()(const void* buffer) const {
57 		// 128 == mid, 1 == bottom, 255 == top
58 		uchar b = *(uchar*)buffer;
59 		if (b == 0)
60 			b++;
61 		return int((int64(b) - 0x80) * 0x7fffffff / 127);
62 	}
63 };
64 
65 struct ReadChar {
66 	inline int operator()(const void* buffer) const {
67 		// 0 == mid, -127 == bottom, +127 == top
68 		char b = *(char*)buffer;
69 		if (b == 0)
70 			b++;
71 		return int(int64(b) * 0x7fffffff / 127);
72 	}
73 };
74 
75 struct WriteFloat {
76 	inline void operator()(void* buffer, int value) const {
77 		*(float*)buffer = (double)value / (double)0x7fffffff;
78 	}
79 
80 };
81 
82 struct WriteInt {
83 	inline void operator()(void* buffer, int value) const {
84 		*(int*)buffer = value;
85 	}
86 };
87 
88 struct WriteShort {
89 	inline void operator()(void* buffer, int value) const {
90 		*(short*)buffer = (short)(value / (int)0x10000);
91 	}
92 };
93 
94 struct WriteUChar {
95 	inline void operator()(void* buffer, int value) const {
96 		*(uchar*)buffer = (uchar)(value / (int)0x1000000 + 128);
97 	}
98 };
99 
100 struct WriteChar {
101 	inline void operator()(void* buffer, int value) const {
102 		*(char*)buffer = (char)(value / (int)0x1000000);
103 	}
104 };
105 
106 
107 template<typename ReadT, typename WriteT>
108 static void
109 convert(const ReadT& read, const WriteT& write,
110 		const char* inBuffer, char* outBuffer, int32 frames,
111 		int32 inSampleSize, int32 outSampleSize, int32 channelCount)
112 {
113 	for (int32 i = 0; i < frames; i++) {
114 		for (int32 c = 0; c < channelCount; c++) {
115 			write(outBuffer, read(inBuffer));
116 			inBuffer += inSampleSize;
117 			outBuffer += outSampleSize;
118 		}
119 	}
120 }
121 
122 
123 static void
124 swap_sample_byte_order(void* buffer, uint32 format, size_t length)
125 {
126 	type_code type = B_ANY_TYPE;
127 	switch (format) {
128 		case media_raw_audio_format::B_AUDIO_FLOAT:
129 			type = B_FLOAT_TYPE;
130 			break;
131 		case media_raw_audio_format::B_AUDIO_INT:
132 			type = B_INT32_TYPE;
133 			break;
134 		case media_raw_audio_format::B_AUDIO_SHORT:
135 			type = B_INT16_TYPE;
136 			break;
137 		case media_raw_audio_format::B_AUDIO_UCHAR:
138 			break;
139 		case media_raw_audio_format::B_AUDIO_CHAR:
140 			break;
141 	}
142 	if (type != B_ANY_TYPE)
143 		swap_data(type, buffer, length, B_SWAP_ALWAYS);
144 }
145 
146 
147 // #pragma mark -
148 
149 
150 AudioFormatConverter::AudioFormatConverter(AudioReader* source, uint32 format,
151 		uint32 byteOrder)
152 	:
153 	AudioReader(),
154 	fSource(NULL)
155 {
156 	uint32 hostByteOrder
157 		= (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
158 	if (source && source->Format().type == B_MEDIA_RAW_AUDIO
159 		&& source->Format().u.raw_audio.byte_order == hostByteOrder) {
160 		fFormat = source->Format();
161 		fFormat.u.raw_audio.format = format;
162 		fFormat.u.raw_audio.byte_order = byteOrder;
163 		int32 inSampleSize = source->Format().u.raw_audio.format
164 			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
165 		int32 outSampleSize = fFormat.u.raw_audio.format
166 			& media_raw_audio_format::B_AUDIO_SIZE_MASK;
167 		if (inSampleSize != outSampleSize) {
168 			fFormat.u.raw_audio.buffer_size
169 				= source->Format().u.raw_audio.buffer_size * outSampleSize
170 				  / inSampleSize;
171 		}
172 	} else
173 		source = NULL;
174 	fSource = source;
175 }
176 
177 
178 AudioFormatConverter::~AudioFormatConverter()
179 {
180 }
181 
182 
183 bigtime_t
184 AudioFormatConverter::InitialLatency() const
185 {
186 	return fSource->InitialLatency();
187 }
188 
189 status_t
190 AudioFormatConverter::Read(void* buffer, int64 pos, int64 frames)
191 {
192 	TRACE("AudioFormatConverter::Read(%p, %lld, %lld)\n", buffer, pos, frames);
193 	status_t error = InitCheck();
194 	if (error != B_OK) {
195 		TRACE("AudioFormatConverter::Read() done 1\n");
196 		return error;
197 	}
198 	pos += fOutOffset;
199 
200 	if (fFormat.u.raw_audio.format == fSource->Format().u.raw_audio.format
201 		&& fFormat.u.raw_audio.byte_order
202 		   == fSource->Format().u.raw_audio.byte_order) {
203 		TRACE("AudioFormatConverter::Read() done 2\n");
204 		return fSource->Read(buffer, pos, frames);
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