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