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