You need to sign in or sign up before continuing.
pcm_utils.c 11.9 KB
Newer Older
1
/* the Music Player Daemon (MPD)
2
 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * This project's homepage is: 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.
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

Warren Dukes's avatar
Warren Dukes committed
19 20 21 22
#include "pcm_utils.h"

#include "mpd_types.h"
#include "log.h"
23
#include "utils.h"
24
#include "conf.h"
25
#include "audio_format.h"
26
#include "os_compat.h"
Warren Dukes's avatar
Warren Dukes committed
27

28 29
void pcm_volumeChange(char *buffer, int bufferSize,
                      const struct audio_format *format,
J. Alexander Treuman's avatar
J. Alexander Treuman committed
30
                      int volume)
Warren Dukes's avatar
Warren Dukes committed
31 32
{
	mpd_sint32 temp32;
Avuton Olrich's avatar
Avuton Olrich committed
33 34 35 36 37
	mpd_sint8 *buffer8 = (mpd_sint8 *) buffer;
	mpd_sint16 *buffer16 = (mpd_sint16 *) buffer;

	if (volume >= 1000)
		return;
Warren Dukes's avatar
Warren Dukes committed
38

Avuton Olrich's avatar
Avuton Olrich committed
39 40
	if (volume <= 0) {
		memset(buffer, 0, bufferSize);
Warren Dukes's avatar
Warren Dukes committed
41 42 43
		return;
	}

Avuton Olrich's avatar
Avuton Olrich committed
44
	switch (format->bits) {
Warren Dukes's avatar
Warren Dukes committed
45
	case 16:
Avuton Olrich's avatar
Avuton Olrich committed
46
		while (bufferSize > 0) {
Warren Dukes's avatar
Warren Dukes committed
47
			temp32 = *buffer16;
Avuton Olrich's avatar
Avuton Olrich committed
48
			temp32 *= volume;
49 50 51
			temp32 += rand() & 511;
			temp32 -= rand() & 511;
			temp32 += 500;
Avuton Olrich's avatar
Avuton Olrich committed
52 53 54
			temp32 /= 1000;
			*buffer16 = temp32 > 32767 ? 32767 :
			    (temp32 < -32768 ? -32768 : temp32);
Warren Dukes's avatar
Warren Dukes committed
55
			buffer16++;
Avuton Olrich's avatar
Avuton Olrich committed
56
			bufferSize -= 2;
Warren Dukes's avatar
Warren Dukes committed
57 58 59
		}
		break;
	case 8:
Avuton Olrich's avatar
Avuton Olrich committed
60
		while (bufferSize > 0) {
Warren Dukes's avatar
Warren Dukes committed
61
			temp32 = *buffer8;
Avuton Olrich's avatar
Avuton Olrich committed
62
			temp32 *= volume;
63 64 65
			temp32 += rand() & 511;
			temp32 -= rand() & 511;
			temp32 += 500;
Avuton Olrich's avatar
Avuton Olrich committed
66 67 68
			temp32 /= 1000;
			*buffer8 = temp32 > 127 ? 127 :
			    (temp32 < -128 ? -128 : temp32);
Warren Dukes's avatar
Warren Dukes committed
69 70 71 72 73
			buffer8++;
			bufferSize--;
		}
		break;
	default:
74
		FATAL("%i bits not supported by pcm_volumeChange!\n",
Avuton Olrich's avatar
Avuton Olrich committed
75
		      format->bits);
Warren Dukes's avatar
Warren Dukes committed
76 77 78
	}
}

79
static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
J. Alexander Treuman's avatar
J. Alexander Treuman committed
80
                    size_t bufferSize2, int vol1, int vol2,
81
                    const struct audio_format *format)
Warren Dukes's avatar
Warren Dukes committed
82 83
{
	mpd_sint32 temp32;
Avuton Olrich's avatar
Avuton Olrich committed
84
	mpd_sint8 *buffer8_1 = (mpd_sint8 *) buffer1;
85
	const mpd_sint8 *buffer8_2 = (const mpd_sint8 *) buffer2;
Avuton Olrich's avatar
Avuton Olrich committed
86
	mpd_sint16 *buffer16_1 = (mpd_sint16 *) buffer1;
87
	const mpd_sint16 *buffer16_2 = (const mpd_sint16 *) buffer2;
Warren Dukes's avatar
Warren Dukes committed
88

Avuton Olrich's avatar
Avuton Olrich committed
89
	switch (format->bits) {
Warren Dukes's avatar
Warren Dukes committed
90
	case 16:
Avuton Olrich's avatar
Avuton Olrich committed
91 92 93
		while (bufferSize1 > 0 && bufferSize2 > 0) {
			temp32 =
			    (vol1 * (*buffer16_1) +
94 95 96 97 98
			     vol2 * (*buffer16_2));
			temp32 += rand() & 511;
			temp32 -= rand() & 511;
			temp32 += 500;
			temp32 /= 1000;
Avuton Olrich's avatar
Avuton Olrich committed
99 100 101
			*buffer16_1 =
			    temp32 > 32767 ? 32767 : (temp32 <
						      -32768 ? -32768 : temp32);
Warren Dukes's avatar
Warren Dukes committed
102 103
			buffer16_1++;
			buffer16_2++;
Avuton Olrich's avatar
Avuton Olrich committed
104 105
			bufferSize1 -= 2;
			bufferSize2 -= 2;
Warren Dukes's avatar
Warren Dukes committed
106
		}
Avuton Olrich's avatar
Avuton Olrich committed
107 108
		if (bufferSize2 > 0)
			memcpy(buffer16_1, buffer16_2, bufferSize2);
Warren Dukes's avatar
Warren Dukes committed
109 110
		break;
	case 8:
Avuton Olrich's avatar
Avuton Olrich committed
111 112
		while (bufferSize1 > 0 && bufferSize2 > 0) {
			temp32 =
113 114 115 116 117
			    (vol1 * (*buffer8_1) + vol2 * (*buffer8_2));
			temp32 += rand() & 511;
			temp32 -= rand() & 511;
			temp32 += 500;
			temp32 /= 1000;
Avuton Olrich's avatar
Avuton Olrich committed
118 119 120
			*buffer8_1 =
			    temp32 > 127 ? 127 : (temp32 <
						  -128 ? -128 : temp32);
Warren Dukes's avatar
Warren Dukes committed
121 122 123 124 125
			buffer8_1++;
			buffer8_2++;
			bufferSize1--;
			bufferSize2--;
		}
Avuton Olrich's avatar
Avuton Olrich committed
126 127
		if (bufferSize2 > 0)
			memcpy(buffer8_1, buffer8_2, bufferSize2);
Warren Dukes's avatar
Warren Dukes committed
128 129
		break;
	default:
130
		FATAL("%i bits not supported by pcm_add!\n", format->bits);
Warren Dukes's avatar
Warren Dukes committed
131 132 133
	}
}

134
void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1,
135 136
             size_t bufferSize2, const struct audio_format *format,
             float portion1)
Warren Dukes's avatar
Warren Dukes committed
137
{
Warren Dukes's avatar
Warren Dukes committed
138
	int vol1;
Avuton Olrich's avatar
Avuton Olrich committed
139 140
	float s = sin(M_PI_2 * portion1);
	s *= s;
Warren Dukes's avatar
Warren Dukes committed
141

Avuton Olrich's avatar
Avuton Olrich committed
142 143
	vol1 = s * 1000 + 0.5;
	vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1);
144

Avuton Olrich's avatar
Avuton Olrich committed
145 146 147
	pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1,
		format);
}
148

149
#ifdef HAVE_LIBSAMPLERATE
150
static int pcm_getSampleRateConverter(void)
J. Alexander Treuman's avatar
J. Alexander Treuman committed
151
{
152 153 154
	const char *conf = getConfigParamValue(CONF_SAMPLERATE_CONVERTER);
	long convalgo;
	char *test;
155
	const char *test2;
156
	size_t len;
157 158 159 160 161 162 163 164 165 166 167 168

	if (!conf) {
		convalgo = SRC_SINC_FASTEST;
		goto out;
	}

	convalgo = strtol(conf, &test, 10);
	if (*test == '\0' && src_get_name(convalgo))
		goto out;

	len = strlen(conf);
	for (convalgo = 0 ; ; convalgo++) {
169 170
		test2 = src_get_name(convalgo);
		if (!test2) {
171 172
			convalgo = SRC_SINC_FASTEST;
			break;
173
		}
174
		if (strncasecmp(test2, conf, len) == 0)
175
			goto out;
176
	}
177 178 179 180 181 182

	ERROR("unknown samplerate converter \"%s\"\n", conf);
out:
	DEBUG("selecting samplerate converter \"%s\"\n",
	      src_get_name(convalgo));

183 184 185 186
	return convalgo;
}
#endif

187
#ifdef HAVE_LIBSAMPLERATE
188
static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate,
Max Kellermann's avatar
Max Kellermann committed
189
                                    const char *inBuffer, size_t inSize,
190 191
                                    mpd_uint32 outSampleRate, char *outBuffer,
                                    size_t outSize, ConvState *convState)
192
{
193
	static int convalgo = -1;
194 195 196
	SRC_DATA *data = &convState->data;
	size_t dataInSize;
	size_t dataOutSize;
197 198
	int error;

199 200
	if (convalgo < 0)
		convalgo = pcm_getSampleRateConverter();
201

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
	/* (re)set the state/ratio if the in or out format changed */
	if ((channels != convState->lastChannels) ||
	    (inSampleRate != convState->lastInSampleRate) ||
	    (outSampleRate != convState->lastOutSampleRate)) {
		convState->error = 0;
		convState->lastChannels = channels;
		convState->lastInSampleRate = inSampleRate;
		convState->lastOutSampleRate = outSampleRate;

		if (convState->state)
			convState->state = src_delete(convState->state);

		convState->state = src_new(convalgo, channels, &error);
		if (!convState->state) {
			ERROR("cannot create new libsamplerate state: %s\n",
			      src_strerror(error));
			convState->error = 1;
			return 0;
		}
		
		data->src_ratio = (double)outSampleRate / (double)inSampleRate;
		DEBUG("setting samplerate conversion ratio to %.2lf\n",
		      data->src_ratio);
		src_set_ratio(convState->state, data->src_ratio);
	}

	/* there was an error previously, and nothing has changed */
	if (convState->error)
		return 0;
231

232 233 234 235 236
	data->input_frames = inSize / 2 / channels;
	dataInSize = data->input_frames * sizeof(float) * channels;
	if (dataInSize > convState->dataInSize) {
		convState->dataInSize = dataInSize;
		data->data_in = xrealloc(data->data_in, dataInSize);
237
	}
238

239 240 241 242 243
	data->output_frames = outSize / 2 / channels;
	dataOutSize = data->output_frames * sizeof(float) * channels;
	if (dataOutSize > convState->dataOutSize) {
		convState->dataOutSize = dataOutSize;
		data->data_out = xrealloc(data->data_out, dataOutSize);
244 245
	}

246
	src_short_to_float_array((const short *)inBuffer, data->data_in,
247
	                         data->input_frames * channels);
248

249
	error = src_process(convState->state, data);
250
	if (error) {
251 252
		ERROR("error processing samples with libsamplerate: %s\n",
		      src_strerror(error));
253
		convState->error = 1;
254 255 256
		return 0;
	}

257 258
	src_float_to_short_array(data->data_out, (short *)outBuffer,
	                         data->output_frames_gen * channels);
259

260
	return data->output_frames_gen * 2 * channels;
261 262 263
}
#else /* !HAVE_LIBSAMPLERATE */
/* resampling code blatantly ripped from ESD */
264
static size_t pcm_convertSampleRate(mpd_sint8 channels, mpd_uint32 inSampleRate,
265 266
                                    const char *inBuffer,
                                    mpd_unused size_t inSize,
267
                                    mpd_uint32 outSampleRate, char *outBuffer,
268 269
                                    size_t outSize,
                                    mpd_unused ConvState *convState)
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
{
	mpd_uint32 rd_dat = 0;
	mpd_uint32 wr_dat = 0;
	mpd_sint16 *in = (mpd_sint16 *)inBuffer;
	mpd_sint16 *out = (mpd_sint16 *)outBuffer;
	mpd_uint32 nlen = outSize / 2;
	mpd_sint16 lsample, rsample;

	switch (channels) {
	case 1:
		while (wr_dat < nlen) {
			rd_dat = wr_dat * inSampleRate / outSampleRate;

			lsample = in[rd_dat++];

			out[wr_dat++] = lsample;
286
		}
287 288 289 290 291 292 293 294
		break;
	case 2:
		while (wr_dat < nlen) {
			rd_dat = wr_dat * inSampleRate / outSampleRate;
			rd_dat &= ~1;

			lsample = in[rd_dat++];
			rsample = in[rd_dat++];
295

296 297
			out[wr_dat++] = lsample;
			out[wr_dat++] = rsample;
298
		}
299 300
		break;
	}
301

302
	return outSize;
303 304
}
#endif /* !HAVE_LIBSAMPLERATE */
305

Max Kellermann's avatar
Max Kellermann committed
306
static char *pcm_convertChannels(mpd_sint8 channels, const char *inBuffer,
307 308 309 310
                                 size_t inSize, size_t *outSize)
{
	static char *buf;
	static size_t len;
311
	char *outBuffer = NULL;
312
	const mpd_sint16 *in;
313 314 315
	mpd_sint16 *out;
	int inSamples, i;

316
	switch (channels) {
317 318 319 320 321 322
	/* convert from 1 -> 2 channels */
	case 1:
		*outSize = (inSize >> 1) << 2;
		if (*outSize > len) {
			len = *outSize;
			buf = xrealloc(buf, len);
323
		}
324 325 326
		outBuffer = buf;

		inSamples = inSize >> 1;
327
		in = (const mpd_sint16 *)inBuffer;
328 329 330 331
		out = (mpd_sint16 *)outBuffer;
		for (i = 0; i < inSamples; i++) {
			*out++ = *in;
			*out++ = *in++;
332
		}
333

334 335 336 337 338 339 340 341 342 343 344
		break;
	/* convert from 2 -> 1 channels */
	case 2:
		*outSize = inSize >> 1;
		if (*outSize > len) {
			len = *outSize;
			buf = xrealloc(buf, len);
		}
		outBuffer = buf;

		inSamples = inSize >> 2;
345
		in = (const mpd_sint16 *)inBuffer;
346 347 348 349
		out = (mpd_sint16 *)outBuffer;
		for (i = 0; i < inSamples; i++) {
			*out = (*in++) / 2;
			*out++ += (*in++) / 2;
350 351
		}

352 353 354 355
		break;
	default:
		ERROR("only 1 or 2 channels are supported for conversion!\n");
	}
356

357 358
	return outBuffer;
}
359

Max Kellermann's avatar
Max Kellermann committed
360 361
static const char *pcm_convertTo16bit(mpd_sint8 bits, const char *inBuffer,
				      size_t inSize, size_t *outSize)
362 363 364 365
{
	static char *buf;
	static size_t len;
	char *outBuffer = NULL;
366
	const mpd_sint8 *in;
367
	mpd_sint16 *out;
Max Kellermann's avatar
Max Kellermann committed
368
	size_t i;
369

370
	switch (bits) {
371 372 373 374 375 376 377
	case 8:
		*outSize = inSize << 1;
		if (*outSize > len) {
			len = *outSize;
			buf = xrealloc(buf, len);
		}
		outBuffer = buf;
378

379
		in = (const mpd_sint8 *)inBuffer;
380 381 382
		out = (mpd_sint16 *)outBuffer;
		for (i = 0; i < inSize; i++)
			*out++ = (*in++) << 8;
383

384 385 386
		break;
	case 16:
		*outSize = inSize;
387
		return inBuffer;
388 389 390 391
	case 24:
		/* put dithering code from mp3_decode here */
	default:
		ERROR("only 8 or 16 bits are supported for conversion!\n");
392
	}
393

394 395 396 397
	return outBuffer;
}

/* outFormat bits must be 16 and channels must be 1 or 2! */
398
size_t pcm_convertAudioFormat(const struct audio_format *inFormat,
399
			      const char *inBuffer, size_t inSize,
400
			      const struct audio_format *outFormat,
401
                              char *outBuffer, ConvState *convState)
402
{
Max Kellermann's avatar
Max Kellermann committed
403
	const char *buf;
404
	size_t len = 0;
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
	size_t outSize = pcm_sizeOfConvBuffer(inFormat, inSize, outFormat);

	assert(outFormat->bits == 16);
	assert(outFormat->channels == 2 || outFormat->channels == 1);

	/* everything else supports 16 bit only, so convert to that first */
	buf = pcm_convertTo16bit(inFormat->bits, inBuffer, inSize, &len);
	if (!buf)
		exit(EXIT_FAILURE);

	if (inFormat->channels != outFormat->channels) {
		buf = pcm_convertChannels(inFormat->channels, buf, len, &len);
		if (!buf)
			exit(EXIT_FAILURE);
	}

	if (inFormat->sampleRate == outFormat->sampleRate) {
		assert(outSize >= len);
		memcpy(outBuffer, buf, len);
	} else {
425 426 427 428 429
		len = pcm_convertSampleRate(outFormat->channels,
		                            inFormat->sampleRate, buf, len,
		                            outFormat->sampleRate, outBuffer,
		                            outSize, convState);
		if (len == 0)
430 431
			exit(EXIT_FAILURE);
	}
432 433

	return len;
434 435
}

436 437
size_t pcm_sizeOfConvBuffer(const struct audio_format *inFormat, size_t inSize,
                            const struct audio_format *outFormat)
438
{
439 440 441
	const double ratio = (double)outFormat->sampleRate /
	                     (double)inFormat->sampleRate;
	const int shift = 2 * outFormat->channels;
442
	size_t outSize = inSize;
443

Avuton Olrich's avatar
Avuton Olrich committed
444
	switch (inFormat->bits) {
445
	case 8:
446
		outSize <<= 1;
447 448 449 450
		break;
	case 16:
		break;
	default:
451
		FATAL("only 8 or 16 bits are supported for conversion!\n");
452
	}
453

Avuton Olrich's avatar
Avuton Olrich committed
454 455
	if (inFormat->channels != outFormat->channels) {
		switch (inFormat->channels) {
456 457 458 459
		case 1:
			outSize = (outSize >> 1) << 2;
			break;
		case 2:
460
			outSize >>= 1;
461
			break;
462
		default:
463
			FATAL("only 1 or 2 channels are supported "
464
			      "for conversion!\n");
465
		}
466
	}
Avuton Olrich's avatar
Avuton Olrich committed
467

J. Alexander Treuman's avatar
J. Alexander Treuman committed
468
	outSize /= shift;
469
	outSize = floor(0.5 + (double)outSize * ratio);
470
	outSize *= shift;
471

472
	return outSize;
473
}