PcmFormat.cxx 12.8 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 19
 */

20
#include "config.h"
Max Kellermann's avatar
Max Kellermann committed
21 22
#include "PcmFormat.hxx"
#include "PcmDither.hxx"
23
#include "pcm_buffer.h"
24
#include "pcm_pack.h"
Max Kellermann's avatar
Max Kellermann committed
25
#include "PcmUtils.hxx"
26

27 28 29 30 31 32 33 34 35 36
#include <type_traits>

template<typename S>
struct DefaultSampleBits {
	typedef decltype(*S()) T;
	typedef typename std::remove_reference<T>::type U;

	static constexpr auto value = sizeof(U) * 8;
};

37
static void
38
pcm_convert_8_to_16(int16_t *out, const int8_t *in, const int8_t *in_end)
39
{
40
	while (in < in_end) {
41 42 43 44 45
		*out++ = *in++ << 8;
	}
}

static void
46
pcm_convert_24_to_16(PcmDither &dither,
47
		     int16_t *out, const int32_t *in, const int32_t *in_end)
48
{
49
	dither.Dither24To16(out, in, in_end);
50 51
}

52
static void
53
pcm_convert_32_to_16(PcmDither &dither,
54
		     int16_t *out, const int32_t *in, const int32_t *in_end)
55
{
56
	dither.Dither32To16(out, in, in_end);
57 58
}

59
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
60
static void
61
ConvertFromFloat(S dest, const float *src, const float *end)
62
{
63 64
	typedef decltype(*S()) T;
	typedef typename std::remove_reference<T>::type U;
65

66 67 68 69 70
	const float factor = 1 << (bits - 1);

	while (src != end) {
		int sample(*src++ * factor);
		*dest++ = PcmClamp<U, int, bits>(sample);
71 72 73
	}
}

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
static void
ConvertFromFloat(S dest, const float *src, size_t size)
{
	ConvertFromFloat<S, bits>(dest, src, pcm_end_pointer(src, size));
}

template<typename S, unsigned bits=sizeof(S)*8>
static S *
AllocateFromFloat(pcm_buffer &buffer, const float *src, size_t src_size,
		  size_t *dest_size_r)
{
	constexpr size_t src_sample_size = sizeof(*src);
	assert(src_size % src_sample_size == 0);

	const size_t num_samples = src_size / src_sample_size;
	*dest_size_r = num_samples * sizeof(S);
	S *dest = (S *)pcm_buffer_get(&buffer, *dest_size_r);
	ConvertFromFloat<S *, bits>(dest, src, src_size);
	return dest;
}

96 97 98 99 100 101
static int16_t *
pcm_allocate_8_to_16(struct pcm_buffer *buffer,
		     const int8_t *src, size_t src_size, size_t *dest_size_r)
{
	int16_t *dest;
	*dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
Max Kellermann's avatar
Max Kellermann committed
102
	dest = (int16_t *)pcm_buffer_get(buffer, *dest_size_r);
103 104 105 106 107
	pcm_convert_8_to_16(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

static int16_t *
108
pcm_allocate_24p32_to_16(struct pcm_buffer *buffer, PcmDither &dither,
109 110 111 112 113 114
			 const int32_t *src, size_t src_size,
			 size_t *dest_size_r)
{
	int16_t *dest;
	*dest_size_r = src_size / 2;
	assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
Max Kellermann's avatar
Max Kellermann committed
115
	dest = (int16_t *)pcm_buffer_get(buffer, *dest_size_r);
116 117 118 119 120 121
	pcm_convert_24_to_16(dither, dest, src,
			     pcm_end_pointer(src, src_size));
	return dest;
}

static int16_t *
122
pcm_allocate_32_to_16(struct pcm_buffer *buffer, PcmDither &dither,
123 124 125 126 127 128
		      const int32_t *src, size_t src_size,
		      size_t *dest_size_r)
{
	int16_t *dest;
	*dest_size_r = src_size / 2;
	assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
Max Kellermann's avatar
Max Kellermann committed
129
	dest = (int16_t *)pcm_buffer_get(buffer, *dest_size_r);
130 131
	pcm_convert_32_to_16(dither, dest, src,
			     pcm_end_pointer(src, src_size));
132 133 134
	return dest;
}

135 136 137 138 139
static int16_t *
pcm_allocate_float_to_16(struct pcm_buffer *buffer,
			 const float *src, size_t src_size,
			 size_t *dest_size_r)
{
140
	return AllocateFromFloat<int16_t>(*buffer, src, src_size, dest_size_r);
141 142
}

143
const int16_t *
144
pcm_convert_to_16(struct pcm_buffer *buffer, PcmDither &dither,
145
		  enum sample_format src_format, const void *src,
146 147
		  size_t src_size, size_t *dest_size_r)
{
148 149
	assert(src_size % sample_format_size(src_format) == 0);

150 151
	switch (src_format) {
	case SAMPLE_FORMAT_UNDEFINED:
152
	case SAMPLE_FORMAT_DSD:
153 154 155
		break;

	case SAMPLE_FORMAT_S8:
156
		return pcm_allocate_8_to_16(buffer,
Max Kellermann's avatar
Max Kellermann committed
157 158
					    (const int8_t *)src, src_size,
					    dest_size_r);
159

160
	case SAMPLE_FORMAT_S16:
161
		*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
162
		return (const int16_t *)src;
163

164
	case SAMPLE_FORMAT_S24_P32:
Max Kellermann's avatar
Max Kellermann committed
165 166
		return pcm_allocate_24p32_to_16(buffer, dither,
						(const int32_t *)src, src_size,
167
						dest_size_r);
168

169
	case SAMPLE_FORMAT_S32:
Max Kellermann's avatar
Max Kellermann committed
170 171
		return pcm_allocate_32_to_16(buffer, dither,
					     (const int32_t *)src, src_size,
172
					     dest_size_r);
173 174

	case SAMPLE_FORMAT_FLOAT:
Max Kellermann's avatar
Max Kellermann committed
175 176
		return pcm_allocate_float_to_16(buffer,
						(const float *)src, src_size,
177
						dest_size_r);
178 179 180 181 182 183
	}

	return NULL;
}

static void
184
pcm_convert_8_to_24(int32_t *out, const int8_t *in, const int8_t *in_end)
185
{
186
	while (in < in_end)
187 188 189 190
		*out++ = *in++ << 16;
}

static void
191
pcm_convert_16_to_24(int32_t *out, const int16_t *in, const int16_t *in_end)
192
{
193
	while (in < in_end)
194 195 196
		*out++ = *in++ << 8;
}

197
static void
198 199 200
pcm_convert_32_to_24(int32_t *restrict out,
		     const int32_t *restrict in,
		     const int32_t *restrict in_end)
201
{
202
	while (in < in_end)
203 204 205
		*out++ = *in++ >> 8;
}

206 207 208 209 210 211
static int32_t *
pcm_allocate_8_to_24(struct pcm_buffer *buffer,
		     const int8_t *src, size_t src_size, size_t *dest_size_r)
{
	int32_t *dest;
	*dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
Max Kellermann's avatar
Max Kellermann committed
212
	dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
213 214 215 216 217 218 219 220 221 222 223
	pcm_convert_8_to_24(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

static int32_t *
pcm_allocate_16_to_24(struct pcm_buffer *buffer,
		      const int16_t *src, size_t src_size, size_t *dest_size_r)
{
	int32_t *dest;
	*dest_size_r = src_size * 2;
	assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
Max Kellermann's avatar
Max Kellermann committed
224
	dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
225 226 227 228 229 230 231 232 233
	pcm_convert_16_to_24(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

static int32_t *
pcm_allocate_32_to_24(struct pcm_buffer *buffer,
		      const int32_t *src, size_t src_size, size_t *dest_size_r)
{
	*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
234
	int32_t *dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
235 236 237 238
	pcm_convert_32_to_24(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

239 240 241 242 243
static int32_t *
pcm_allocate_float_to_24(struct pcm_buffer *buffer,
			 const float *src, size_t src_size,
			 size_t *dest_size_r)
{
244 245
	return AllocateFromFloat<int32_t, 24>(*buffer, src, src_size,
					      dest_size_r);
246 247
}

248
const int32_t *
249
pcm_convert_to_24(struct pcm_buffer *buffer,
250
		  enum sample_format src_format, const void *src,
251 252
		  size_t src_size, size_t *dest_size_r)
{
253 254
	assert(src_size % sample_format_size(src_format) == 0);

255 256
	switch (src_format) {
	case SAMPLE_FORMAT_UNDEFINED:
257
	case SAMPLE_FORMAT_DSD:
258 259 260
		break;

	case SAMPLE_FORMAT_S8:
261
		return pcm_allocate_8_to_24(buffer,
Max Kellermann's avatar
Max Kellermann committed
262 263
					    (const int8_t *)src, src_size,
					    dest_size_r);
264

265
	case SAMPLE_FORMAT_S16:
266
		return pcm_allocate_16_to_24(buffer,
Max Kellermann's avatar
Max Kellermann committed
267 268
					     (const int16_t *)src, src_size,
					     dest_size_r);
269

270
	case SAMPLE_FORMAT_S24_P32:
271
		*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
272
		return (const int32_t *)src;
273

274
	case SAMPLE_FORMAT_S32:
Max Kellermann's avatar
Max Kellermann committed
275 276
		return pcm_allocate_32_to_24(buffer,
					     (const int32_t *)src, src_size,
277
					     dest_size_r);
278 279

	case SAMPLE_FORMAT_FLOAT:
Max Kellermann's avatar
Max Kellermann committed
280 281
		return pcm_allocate_float_to_24(buffer,
						(const float *)src, src_size,
282
						dest_size_r);
283 284 285 286
	}

	return NULL;
}
287 288

static void
289
pcm_convert_8_to_32(int32_t *out, const int8_t *in, const int8_t *in_end)
290
{
291
	while (in < in_end)
292 293 294 295
		*out++ = *in++ << 24;
}

static void
296
pcm_convert_16_to_32(int32_t *out, const int16_t *in, const int16_t *in_end)
297
{
298
	while (in < in_end)
299 300 301 302
		*out++ = *in++ << 16;
}

static void
303 304 305
pcm_convert_24_to_32(int32_t *restrict out,
		     const int32_t *restrict in,
		     const int32_t *restrict in_end)
306
{
307
	while (in < in_end)
308 309 310
		*out++ = *in++ << 8;
}

311 312 313 314 315 316
static int32_t *
pcm_allocate_8_to_32(struct pcm_buffer *buffer,
		     const int8_t *src, size_t src_size, size_t *dest_size_r)
{
	int32_t *dest;
	*dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
Max Kellermann's avatar
Max Kellermann committed
317
	dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
318 319 320 321 322 323 324 325 326 327 328
	pcm_convert_8_to_32(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

static int32_t *
pcm_allocate_16_to_32(struct pcm_buffer *buffer,
		      const int16_t *src, size_t src_size, size_t *dest_size_r)
{
	int32_t *dest;
	*dest_size_r = src_size * 2;
	assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
Max Kellermann's avatar
Max Kellermann committed
329
	dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
330 331 332 333 334 335 336 337 338 339
	pcm_convert_16_to_32(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

static int32_t *
pcm_allocate_24p32_to_32(struct pcm_buffer *buffer,
			 const int32_t *src, size_t src_size,
			 size_t *dest_size_r)
{
	*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
340
	int32_t *dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
341 342 343 344
	pcm_convert_24_to_32(dest, src, pcm_end_pointer(src, src_size));
	return dest;
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358
static int32_t *
pcm_allocate_float_to_32(struct pcm_buffer *buffer,
			 const float *src, size_t src_size,
			 size_t *dest_size_r)
{
	/* convert to S24_P32 first */
	int32_t *dest = pcm_allocate_float_to_24(buffer, src, src_size,
						 dest_size_r);

	/* convert to 32 bit in-place */
	pcm_convert_24_to_32(dest, dest, pcm_end_pointer(dest, *dest_size_r));
	return dest;
}

359 360
const int32_t *
pcm_convert_to_32(struct pcm_buffer *buffer,
361
		  enum sample_format src_format, const void *src,
362 363
		  size_t src_size, size_t *dest_size_r)
{
364 365
	assert(src_size % sample_format_size(src_format) == 0);

366 367
	switch (src_format) {
	case SAMPLE_FORMAT_UNDEFINED:
368
	case SAMPLE_FORMAT_DSD:
369 370 371
		break;

	case SAMPLE_FORMAT_S8:
Max Kellermann's avatar
Max Kellermann committed
372 373
		return pcm_allocate_8_to_32(buffer,
					    (const int8_t *)src, src_size,
374
					    dest_size_r);
375

376
	case SAMPLE_FORMAT_S16:
Max Kellermann's avatar
Max Kellermann committed
377 378
		return pcm_allocate_16_to_32(buffer,
					     (const int16_t *)src, src_size,
379
					     dest_size_r);
380

381
	case SAMPLE_FORMAT_S24_P32:
Max Kellermann's avatar
Max Kellermann committed
382 383
		return pcm_allocate_24p32_to_32(buffer,
						(const int32_t *)src, src_size,
384
						dest_size_r);
385

386
	case SAMPLE_FORMAT_S32:
387
		*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
388
		return (const int32_t *)src;
389 390

	case SAMPLE_FORMAT_FLOAT:
Max Kellermann's avatar
Max Kellermann committed
391 392
		return pcm_allocate_float_to_32(buffer,
						(const float *)src, src_size,
393
						dest_size_r);
394 395 396 397
	}

	return NULL;
}
398

399
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
400
static void
401
ConvertToFloat(float *dest, S src, S end)
402
{
403 404 405
	constexpr float factor = 0.5 / (1 << (bits - 2));
	while (src != end)
		*dest++ = float(*src++) * factor;
406 407 408

}

409
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
410
static void
411
ConvertToFloat(float *dest, S src, size_t size)
412
{
413
	ConvertToFloat<S, bits>(dest, src, pcm_end_pointer(src, size));
414 415
}

416 417 418 419
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
static float *
AllocateToFloat(pcm_buffer &buffer, S src, size_t src_size,
		size_t *dest_size_r)
420
{
421 422 423 424 425 426 427 428
	constexpr size_t src_sample_size = sizeof(*S());
	assert(src_size % src_sample_size == 0);

	const size_t num_samples = src_size / src_sample_size;
	*dest_size_r = num_samples * sizeof(float);
	float *dest = (float *)pcm_buffer_get(&buffer, *dest_size_r);
	ConvertToFloat<S, bits>(dest, src, src_size);
	return dest;
429 430 431 432 433 434 435
}

static float *
pcm_allocate_8_to_float(struct pcm_buffer *buffer,
			const int8_t *src, size_t src_size,
			size_t *dest_size_r)
{
436
	return AllocateToFloat(*buffer, src, src_size, dest_size_r);
437 438 439 440 441 442 443
}

static float *
pcm_allocate_16_to_float(struct pcm_buffer *buffer,
			 const int16_t *src, size_t src_size,
			 size_t *dest_size_r)
{
444
	return AllocateToFloat(*buffer, src, src_size, dest_size_r);
445 446 447 448
}

static float *
pcm_allocate_24p32_to_float(struct pcm_buffer *buffer,
449 450
			    const int32_t *src, size_t src_size,
			    size_t *dest_size_r)
451
{
452 453
	return AllocateToFloat<decltype(src), 24>
		(*buffer, src, src_size, dest_size_r);
454 455 456 457 458 459 460
}

static float *
pcm_allocate_32_to_float(struct pcm_buffer *buffer,
			 const int32_t *src, size_t src_size,
			 size_t *dest_size_r)
{
461
	return AllocateToFloat(*buffer, src, src_size, dest_size_r);
462 463 464 465 466 467 468 469 470
}

const float *
pcm_convert_to_float(struct pcm_buffer *buffer,
		     enum sample_format src_format, const void *src,
		     size_t src_size, size_t *dest_size_r)
{
	switch (src_format) {
	case SAMPLE_FORMAT_UNDEFINED:
471
	case SAMPLE_FORMAT_DSD:
472 473 474 475
		break;

	case SAMPLE_FORMAT_S8:
		return pcm_allocate_8_to_float(buffer,
Max Kellermann's avatar
Max Kellermann committed
476 477
					       (const int8_t *)src, src_size,
					       dest_size_r);
478 479 480

	case SAMPLE_FORMAT_S16:
		return pcm_allocate_16_to_float(buffer,
Max Kellermann's avatar
Max Kellermann committed
481 482
						(const int16_t *)src, src_size,
						dest_size_r);
483 484 485

	case SAMPLE_FORMAT_S24_P32:
		return pcm_allocate_24p32_to_float(buffer,
Max Kellermann's avatar
Max Kellermann committed
486 487
						   (const int32_t *)src, src_size,
						   dest_size_r);
488 489 490

	case SAMPLE_FORMAT_S32:
		return pcm_allocate_32_to_float(buffer,
Max Kellermann's avatar
Max Kellermann committed
491 492
						(const int32_t *)src, src_size,
						dest_size_r);
493 494 495

	case SAMPLE_FORMAT_FLOAT:
		*dest_size_r = src_size;
Max Kellermann's avatar
Max Kellermann committed
496
		return (const float *)src;
497 498 499 500
	}

	return NULL;
}