1/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6/* For now just use speex, can add more resamplers later. */
7#include <speex/speex_resampler.h>
8#include <sys/param.h>
9#include <syslog.h>
10
11#include "cras_fmt_conv.h"
12#include "cras_audio_format.h"
13#include "cras_util.h"
14#include "linear_resampler.h"
15
16/* The quality level is a value between 0 and 10. This is a tradeoff between
17 * performance, latency, and quality. */
18#define SPEEX_QUALITY_LEVEL 4
19/* Max number of converters, src, down/up mix, 2xformat, and linear resample. */
20#define MAX_NUM_CONVERTERS 5
21/* Channel index for stereo. */
22#define STEREO_L 0
23#define STEREO_R 1
24
25typedef void (*sample_format_converter_t)(const uint8_t *in,
26					  size_t in_samples,
27					  uint8_t *out);
28typedef size_t (*channel_converter_t)(struct cras_fmt_conv *conv,
29				      const int16_t *in,
30				      size_t in_frames,
31				      int16_t *out);
32
33/* Member data for the resampler. */
34struct cras_fmt_conv {
35	SpeexResamplerState *speex_state;
36	channel_converter_t channel_converter;
37	float **ch_conv_mtx; /* Coefficient matrix for mixing channels. */
38	sample_format_converter_t in_format_converter;
39	sample_format_converter_t out_format_converter;
40	struct linear_resampler *resampler;
41	struct cras_audio_format in_fmt;
42	struct cras_audio_format out_fmt;
43	uint8_t *tmp_bufs[MAX_NUM_CONVERTERS - 1];
44	size_t tmp_buf_frames;
45	size_t pre_linear_resample;
46	size_t num_converters; /* Incremented once for SRC, channel, format. */
47};
48
49/* Add and clip two s16 samples. */
50static int16_t s16_add_and_clip(int16_t a, int16_t b)
51{
52	int32_t sum;
53
54	sum = a + b;
55	sum = MAX(sum, -0x8000);
56	sum = MIN(sum, 0x7fff);
57	return (int16_t)sum;
58}
59
60/*
61 * Convert between different sample formats.
62 */
63
64/* Converts from U8 to S16. */
65static void convert_u8_to_s16le(const uint8_t *in, size_t in_samples,
66				uint8_t *out)
67{
68	size_t i;
69	uint16_t *_out = (uint16_t *)out;
70
71	for (i = 0; i < in_samples; i++, in++, _out++)
72		*_out = ((int16_t)*in - 0x80) << 8;
73}
74
75/* Converts from S24 to S16. */
76static void convert_s24le_to_s16le(const uint8_t *in, size_t in_samples,
77				   uint8_t *out)
78{
79	size_t i;
80	int32_t *_in = (int32_t *)in;
81	uint16_t *_out = (uint16_t *)out;
82
83	for (i = 0; i < in_samples; i++, _in++, _out++)
84		*_out = (int16_t)((*_in & 0x00ffffff) >> 8);
85}
86
87/* Converts from S32 to S16. */
88static void convert_s32le_to_s16le(const uint8_t *in, size_t in_samples,
89				   uint8_t *out)
90{
91	size_t i;
92	int32_t *_in = (int32_t *)in;
93	uint16_t *_out = (uint16_t *)out;
94
95	for (i = 0; i < in_samples; i++, _in++, _out++)
96		*_out = (int16_t)(*_in >> 16);
97}
98
99/* Converts from S24_3LE to S16. */
100static void convert_s243le_to_s16le(const uint8_t *in, size_t in_samples,
101				   uint8_t *out)
102{
103	/* find how to calculate in and out size, implement the conversion
104	 * between S24_3LE and S16 */
105
106	size_t i;
107	int8_t *_in = (int8_t *)in;
108	uint16_t *_out = (uint16_t *)out;
109
110	for (i = 0; i < in_samples; i++, _in += 3, _out++)
111		memcpy(_out, _in + 1, 2);
112}
113
114/* Converts from S16 to U8. */
115static void convert_s16le_to_u8(const uint8_t *in, size_t in_samples,
116				uint8_t *out)
117{
118	size_t i;
119	int16_t *_in = (int16_t *)in;
120
121	for (i = 0; i < in_samples; i++, _in++, out++)
122		*out = (uint8_t)(*_in >> 8) + 128;
123}
124
125/* Converts from S16 to S24. */
126static void convert_s16le_to_s24le(const uint8_t *in, size_t in_samples,
127				   uint8_t *out)
128{
129	size_t i;
130	int16_t *_in = (int16_t *)in;
131	uint32_t *_out = (uint32_t *)out;
132
133	for (i = 0; i < in_samples; i++, _in++, _out++)
134		*_out = ((int32_t)*_in << 8);
135}
136
137/* Converts from S16 to S32. */
138static void convert_s16le_to_s32le(const uint8_t *in, size_t in_samples,
139				   uint8_t *out)
140{
141	size_t i;
142	int16_t *_in = (int16_t *)in;
143	uint32_t *_out = (uint32_t *)out;
144
145	for (i = 0; i < in_samples; i++, _in++, _out++)
146		*_out = ((int32_t)*_in << 16);
147}
148
149/* Converts from S16 to S24_3LE. */
150static void convert_s16le_to_s243le(const uint8_t *in, size_t in_samples,
151				   uint8_t *out)
152{
153	size_t i;
154	int16_t *_in = (int16_t *)in;
155	uint8_t *_out = (uint8_t *)out;
156
157	for (i = 0; i < in_samples; i++, _in++, _out += 3) {
158		*_out = 0;
159		memcpy(_out + 1, _in, 2);
160	}
161}
162
163/*
164 * Convert between different channel numbers.
165 */
166
167/* Converts S16 mono to S16 stereo. The out buffer must be double the size of
168 * the input buffer. */
169static size_t s16_mono_to_stereo(struct cras_fmt_conv *conv,
170				const int16_t *in, size_t in_frames,
171				int16_t *out)
172{
173	size_t i;
174
175	for (i = 0; i < in_frames; i++) {
176		out[2 * i] = in[i];
177		out[2 * i + 1] = in[i];
178	}
179	return in_frames;
180}
181
182/* Converts S16 Stereo to S16 mono.  The output buffer only need be big enough
183 * for mono samples. */
184static size_t s16_stereo_to_mono(struct cras_fmt_conv *conv,
185				const int16_t *in, size_t in_frames,
186				int16_t *out)
187{
188	size_t i;
189
190	for (i = 0; i < in_frames; i++)
191		out[i] = s16_add_and_clip(in[2 * i], in[2 * i + 1]);
192	return in_frames;
193}
194
195/* Converts S16 mono to 5.1 surround. Fit mono to front center of the
196 * output, or split to front left/right if front center is missing
197 * from the output channel layout.
198 */
199static size_t s16_mono_to_51(struct cras_fmt_conv *conv,
200			     const int16_t *in, size_t in_frames,
201			     int16_t *out)
202{
203	size_t i, left, right, center;
204
205	memset(out, 0, sizeof(*out) * 6 * in_frames);
206	left = conv->out_fmt.channel_layout[CRAS_CH_FL];
207	right = conv->out_fmt.channel_layout[CRAS_CH_FR];
208	center = conv->out_fmt.channel_layout[CRAS_CH_FC];
209
210	if (center != -1)
211		for (i = 0; i < in_frames; i++)
212			out[6 * i + center] = in[i];
213	else if (left != -1 && right != -1)
214		for (i = 0; i < in_frames; i++) {
215			out[6 * i + right] = in[i] / 2;
216			out[6 * 1 + left] = in[i] / 2;
217		}
218	else
219		/* Select the first channel to convert to as the
220		 * default behavior.
221		 */
222		for (i = 0; i < in_frames; i++)
223			out[6 * i] = in[i];
224
225	return in_frames;
226}
227
228/* Converts S16 stereo to 5.1 surround. Fit the left/right of input
229 * to the front left/right of output respectively and fill others
230 * with zero. If any of the front left/right is missed from the output
231 * channel layout, mix to front center.
232 */
233static size_t s16_stereo_to_51(struct cras_fmt_conv *conv,
234			       const int16_t *in, size_t in_frames,
235			       int16_t *out)
236{
237	size_t i, left, right, center;
238
239	memset(out, 0, sizeof(*out) * 6 * in_frames);
240	left = conv->out_fmt.channel_layout[CRAS_CH_FL];
241	right = conv->out_fmt.channel_layout[CRAS_CH_FR];
242	center = conv->out_fmt.channel_layout[CRAS_CH_FC];
243
244	if (left != -1 && right != -1)
245		for (i = 0; i < in_frames; i++) {
246			out[6 * i + left] = in[2 * i];
247			out[6 * i + right] = in[2 * i + 1];
248		}
249	else if (center != -1)
250		for (i = 0; i < in_frames; i++)
251			out[6 * i + center] = s16_add_and_clip(
252					in[2 * i], in[2 * i + 1]);
253	else
254		/* Select the first two channels to convert to as the
255		 * default behavior.
256		 */
257		for (i = 0; i < in_frames; i++) {
258			out[6 * i] = in[2 * i];
259			out[6 * i + 1] = in[2 * i + 1];
260		}
261
262	return in_frames;
263}
264
265/* Converts S16 5.1 to S16 stereo. The out buffer can have room for just
266 * stereo samples. This convert function is used as the default behavior
267 * when channel layout is not set from the client side. */
268static size_t s16_51_to_stereo(struct cras_fmt_conv *conv,
269			       const int16_t *in, size_t in_frames,
270			       int16_t *out)
271{
272	static const unsigned int left_idx = 0;
273	static const unsigned int right_idx = 1;
274	/* static const unsigned int left_surround_idx = 2; */
275	/* static const unsigned int right_surround_idx = 3; */
276	static const unsigned int center_idx = 4;
277	/* static const unsigned int lfe_idx = 5; */
278	size_t i;
279
280	for (i = 0; i < in_frames; i++) {
281		unsigned int half_center;
282
283		half_center = in[6 * i + center_idx] / 2;
284		out[2 * i + left_idx] = s16_add_and_clip(in[6 * i + left_idx],
285							 half_center);
286		out[2 * i + right_idx] = s16_add_and_clip(in[6 * i + right_idx],
287							  half_center);
288	}
289	return in_frames;
290}
291
292/* Converts S16 N channels to S16 M channels.  The out buffer must have room for
293 * M channel. This convert function is used as the default behavior when channel
294 * layout is not set from the client side. */
295static size_t s16_default_all_to_all(struct cras_fmt_conv *conv,
296				     const int16_t *in, size_t in_frames,
297				     int16_t *out)
298{
299	unsigned int num_in_ch = conv->in_fmt.num_channels;
300	unsigned int num_out_ch = conv->out_fmt.num_channels;
301	unsigned int in_ch, out_ch, i;
302
303	memset(out, 0, num_out_ch * in_frames *
304				cras_get_format_bytes(&conv->out_fmt));
305	for (out_ch = 0; out_ch < num_out_ch; out_ch++) {
306		for (in_ch = 0; in_ch < num_in_ch; in_ch++) {
307			for (i = 0; i < in_frames; i++) {
308				out[out_ch + i * num_out_ch] +=
309					in[in_ch + i * num_in_ch] / num_in_ch;
310			}
311		}
312	}
313	return in_frames;
314}
315
316static int is_channel_layout_equal(const struct cras_audio_format *a,
317				   const struct cras_audio_format *b)
318{
319	int ch;
320	for (ch = 0; ch < CRAS_CH_MAX; ch++)
321		if (a->channel_layout[ch] != b->channel_layout[ch])
322			return 0;
323
324	return 1;
325}
326
327/* Multiplies buffer vector with coefficient vector. */
328static int16_t multiply_buf_with_coef(float *coef,
329				      const int16_t *buf,
330				      size_t size)
331{
332	int32_t sum = 0;
333	int i;
334
335	for (i = 0; i < size; i++)
336		sum += coef[i] * buf[i];
337	sum = MAX(sum, -0x8000);
338	sum = MIN(sum, 0x7fff);
339	return (int16_t)sum;
340}
341
342static void normalize_buf(float *buf, size_t size)
343{
344	int i;
345	float squre_sum = 0.0;
346	for (i = 0; i < size; i++)
347		squre_sum += buf[i] * buf[i];
348	for (i = 0; i < size; i ++)
349		buf[i] /= squre_sum;
350}
351
352/* Converts channels based on the channel conversion
353 * coefficient matrix.
354 */
355static size_t convert_channels(struct cras_fmt_conv *conv,
356			       const int16_t *in,
357			       size_t in_frames,
358			       int16_t *out)
359{
360	unsigned i, fr;
361	unsigned in_idx = 0;
362	unsigned out_idx = 0;
363
364	for (fr = 0; fr < in_frames; fr++) {
365		for (i = 0; i < conv->out_fmt.num_channels; i++)
366			out[out_idx + i] = multiply_buf_with_coef(
367					conv->ch_conv_mtx[i],
368					&in[in_idx],
369					conv->in_fmt.num_channels);
370		in_idx += conv->in_fmt.num_channels;
371		out_idx += conv->out_fmt.num_channels;
372	}
373
374	return in_frames;
375}
376
377/* Populates the down mix matrix by rules:
378 * 1. Front/side left(right) channel will mix to left(right) of
379 *    full scale.
380 * 2. Center and LFE will be split equally to left and right.
381 *    Rear
382 * 3. Rear left/right will split 1/4 of the power to opposite
383 *    channel.
384 */
385static void surround51_to_stereo_downmix_mtx(float **mtx,
386					     int8_t layout[CRAS_CH_MAX])
387{
388	if (layout[CRAS_CH_FC] != -1) {
389		mtx[STEREO_L][layout[CRAS_CH_FC]] = 0.707;
390		mtx[STEREO_R][layout[CRAS_CH_FC]] = 0.707;
391	}
392	if (layout[CRAS_CH_FL] != -1 && layout[CRAS_CH_FR] != -1) {
393		mtx[STEREO_L][layout[CRAS_CH_FL]] = 1.0;
394		mtx[STEREO_R][layout[CRAS_CH_FR]] = 1.0;
395	}
396	if (layout[CRAS_CH_SL] != -1 && layout[CRAS_CH_SR] != -1) {
397		mtx[STEREO_L][layout[CRAS_CH_SL]] = 1.0;
398		mtx[STEREO_R][layout[CRAS_CH_SR]] = 1.0;
399	}
400	if (layout[CRAS_CH_RL] != -1 && layout[CRAS_CH_RR] != -1) {
401		/* Split 1/4 power to the other side */
402		mtx[STEREO_L][layout[CRAS_CH_RL]] = 0.866;
403		mtx[STEREO_R][layout[CRAS_CH_RL]] = 0.5;
404		mtx[STEREO_R][layout[CRAS_CH_RR]] = 0.866;
405		mtx[STEREO_L][layout[CRAS_CH_RR]] = 0.5;
406	}
407	if (layout[CRAS_CH_LFE] != -1) {
408		mtx[STEREO_L][layout[CRAS_CH_LFE]] = 0.707;
409		mtx[STEREO_R][layout[CRAS_CH_LFE]] = 0.707;
410	}
411
412	normalize_buf(mtx[STEREO_L], 6);
413	normalize_buf(mtx[STEREO_R], 6);
414}
415
416/*
417 * Exported interface
418 */
419
420struct cras_fmt_conv *cras_fmt_conv_create(const struct cras_audio_format *in,
421					   const struct cras_audio_format *out,
422					   size_t max_frames,
423					   size_t pre_linear_resample)
424{
425	struct cras_fmt_conv *conv;
426	int rc;
427	unsigned i;
428
429	conv = calloc(1, sizeof(*conv));
430	if (conv == NULL)
431		return NULL;
432	conv->in_fmt = *in;
433	conv->out_fmt = *out;
434	conv->tmp_buf_frames = max_frames;
435	conv->pre_linear_resample = pre_linear_resample;
436
437	/* Set up sample format conversion. */
438	/* TODO(dgreid) - modify channel and sample rate conversion so
439	 * converting to s16 isnt necessary. */
440	if (in->format != SND_PCM_FORMAT_S16_LE) {
441		conv->num_converters++;
442		syslog(LOG_DEBUG, "Convert from format %d to %d.",
443		       in->format, out->format);
444		switch(in->format) {
445		case SND_PCM_FORMAT_U8:
446			conv->in_format_converter = convert_u8_to_s16le;
447			break;
448		case SND_PCM_FORMAT_S24_LE:
449			conv->in_format_converter = convert_s24le_to_s16le;
450			break;
451		case SND_PCM_FORMAT_S32_LE:
452			conv->in_format_converter = convert_s32le_to_s16le;
453			break;
454		case SND_PCM_FORMAT_S24_3LE:
455			conv->in_format_converter = convert_s243le_to_s16le;
456			break;
457		default:
458			syslog(LOG_WARNING, "Invalid format %d", in->format);
459			cras_fmt_conv_destroy(conv);
460			return NULL;
461		}
462	}
463	if (out->format != SND_PCM_FORMAT_S16_LE) {
464		conv->num_converters++;
465		syslog(LOG_DEBUG, "Convert from format %d to %d.",
466		       in->format, out->format);
467		switch (out->format) {
468		case SND_PCM_FORMAT_U8:
469			conv->out_format_converter = convert_s16le_to_u8;
470			break;
471		case SND_PCM_FORMAT_S24_LE:
472			conv->out_format_converter = convert_s16le_to_s24le;
473			break;
474		case SND_PCM_FORMAT_S32_LE:
475			conv->out_format_converter = convert_s16le_to_s32le;
476			break;
477		case SND_PCM_FORMAT_S24_3LE:
478			conv->out_format_converter = convert_s16le_to_s243le;
479			break;
480		default:
481			syslog(LOG_WARNING, "Invalid format %d", out->format);
482			cras_fmt_conv_destroy(conv);
483			return NULL;
484		}
485	}
486
487	/* Set up channel number conversion. */
488	if (in->num_channels != out->num_channels) {
489		conv->num_converters++;
490		syslog(LOG_DEBUG, "Convert from %zu to %zu channels.",
491		       in->num_channels, out->num_channels);
492
493		/* Populate the conversion matrix base on in/out channel count
494		 * and layout. */
495		if (in->num_channels == 1 && out->num_channels == 2) {
496			conv->channel_converter = s16_mono_to_stereo;
497		} else if (in->num_channels == 1 && out->num_channels == 6) {
498			conv->channel_converter = s16_mono_to_51;
499		} else if (in->num_channels == 2 && out->num_channels == 1) {
500			conv->channel_converter = s16_stereo_to_mono;
501		} else if (in->num_channels == 2 && out->num_channels == 6) {
502			conv->channel_converter = s16_stereo_to_51;
503		} else if (in->num_channels == 6 && out->num_channels == 2) {
504			int in_channel_layout_set = 0;
505
506			/* Checks if channel_layout is set in the incoming format */
507			for (i = 0; i < CRAS_CH_MAX; i++)
508				if (in->channel_layout[i] != -1)
509					in_channel_layout_set = 1;
510
511			/* Use the conversion matrix based converter when a
512			 * channel layout is set, or default to use existing
513			 * converter to downmix to stereo */
514			if (in_channel_layout_set) {
515				conv->ch_conv_mtx = cras_channel_conv_matrix_alloc(
516						in->num_channels,
517						out->num_channels);
518				if (conv->ch_conv_mtx == NULL) {
519					cras_fmt_conv_destroy(conv);
520					return NULL;
521				}
522				conv->channel_converter = convert_channels;
523				surround51_to_stereo_downmix_mtx(
524						conv->ch_conv_mtx,
525						conv->in_fmt.channel_layout);
526			} else {
527				conv->channel_converter = s16_51_to_stereo;
528			}
529		} else {
530			syslog(LOG_WARNING,
531			       "Using default channel map for %zu to %zu",
532			       in->num_channels, out->num_channels);
533			conv->channel_converter = s16_default_all_to_all;
534		}
535	} else if (in->num_channels > 2 &&
536		   !is_channel_layout_equal(in, out)){
537		conv->num_converters++;
538		conv->ch_conv_mtx = cras_channel_conv_matrix_create(in, out);
539		if (conv->ch_conv_mtx == NULL) {
540			syslog(LOG_ERR, "Failed to create channel conversion matrix");
541			cras_fmt_conv_destroy(conv);
542			return NULL;
543		}
544		conv->channel_converter = convert_channels;
545	}
546	/* Set up sample rate conversion. */
547	if (in->frame_rate != out->frame_rate) {
548		conv->num_converters++;
549		syslog(LOG_DEBUG, "Convert from %zu to %zu Hz.",
550		       in->frame_rate, out->frame_rate);
551		conv->speex_state = speex_resampler_init(out->num_channels,
552							 in->frame_rate,
553							 out->frame_rate,
554							 SPEEX_QUALITY_LEVEL,
555							 &rc);
556		if (conv->speex_state == NULL) {
557			syslog(LOG_ERR, "Fail to create speex:%zu %zu %zu %d",
558			       out->num_channels,
559			       in->frame_rate,
560			       out->frame_rate,
561			       rc);
562			cras_fmt_conv_destroy(conv);
563			return NULL;
564		}
565	}
566
567	/* Set up linear resampler. */
568	conv->num_converters++;
569	conv->resampler = linear_resampler_create(
570			out->num_channels,
571			cras_get_format_bytes(out),
572			out->frame_rate,
573			out->frame_rate);
574	if (conv->resampler == NULL) {
575		syslog(LOG_ERR, "Fail to create linear resampler");
576		cras_fmt_conv_destroy(conv);
577		return NULL;
578	}
579
580	/* Need num_converters-1 temp buffers, the final converter renders
581	 * directly into the output. */
582	for (i = 0; i < conv->num_converters - 1; i++) {
583		conv->tmp_bufs[i] = malloc(
584			max_frames *
585			4 * /* width in bytes largest format. */
586			MAX(in->num_channels, out->num_channels));
587		if (conv->tmp_bufs[i] == NULL) {
588			cras_fmt_conv_destroy(conv);
589			return NULL;
590		}
591	}
592
593	assert(conv->num_converters <= MAX_NUM_CONVERTERS);
594
595	return conv;
596}
597
598void cras_fmt_conv_destroy(struct cras_fmt_conv *conv)
599{
600	unsigned i;
601	if (conv->ch_conv_mtx)
602		cras_channel_conv_matrix_destroy(conv->ch_conv_mtx,
603						 conv->out_fmt.num_channels);
604	if (conv->speex_state)
605		speex_resampler_destroy(conv->speex_state);
606	if (conv->resampler)
607		linear_resampler_destroy(conv->resampler);
608	for (i = 0; i < MAX_NUM_CONVERTERS - 1; i++)
609		free(conv->tmp_bufs[i]);
610	free(conv);
611}
612
613struct cras_fmt_conv *cras_channel_remix_conv_create(
614		unsigned int num_channels,
615		const float *coefficient)
616{
617	struct cras_fmt_conv *conv;
618	unsigned out_ch, in_ch;
619
620	conv = calloc(1, sizeof(*conv));
621	if (conv == NULL)
622		return NULL;
623	conv->in_fmt.num_channels = num_channels;
624	conv->out_fmt.num_channels = num_channels;
625
626	conv->ch_conv_mtx = cras_channel_conv_matrix_alloc(num_channels,
627							   num_channels);
628	/* Convert the coeffiencnt array to conversion matrix. */
629	for (out_ch = 0; out_ch < num_channels; out_ch++)
630		for (in_ch = 0; in_ch < num_channels; in_ch++)
631			conv->ch_conv_mtx[out_ch][in_ch] =
632				coefficient[in_ch + out_ch * num_channels];
633
634	conv->num_converters = 1;
635	conv->tmp_bufs[0] = malloc(4 * /* width in bytes largest format. */
636				   num_channels);
637	return conv;
638}
639
640void cras_channel_remix_convert(struct cras_fmt_conv *conv,
641				const struct cras_audio_format *fmt,
642				uint8_t *in_buf,
643				size_t nframes)
644{
645	unsigned ch, fr;
646	int16_t *tmp = (int16_t *)conv->tmp_bufs[0];
647	int16_t *buf = (int16_t *)in_buf;
648
649	/* Do remix only when input buffer has the same number of channels. */
650	if (fmt->num_channels != conv->in_fmt.num_channels)
651		return;
652
653	for (fr = 0; fr < nframes; fr++) {
654		for (ch = 0; ch < conv->in_fmt.num_channels; ch++)
655			tmp[ch] = multiply_buf_with_coef(
656				conv->ch_conv_mtx[ch],
657				buf,
658				conv->in_fmt.num_channels);
659		for (ch = 0; ch < conv->in_fmt.num_channels; ch++)
660			buf[ch] = tmp[ch];
661		buf += conv->in_fmt.num_channels;
662	}
663}
664
665const struct cras_audio_format *cras_fmt_conv_in_format(
666		const struct cras_fmt_conv *conv)
667{
668	return &conv->in_fmt;
669}
670
671const struct cras_audio_format *cras_fmt_conv_out_format(
672		const struct cras_fmt_conv *conv)
673{
674	return &conv->out_fmt;
675}
676
677size_t cras_fmt_conv_in_frames_to_out(struct cras_fmt_conv *conv,
678				      size_t in_frames)
679{
680	if (!conv)
681		return in_frames;
682
683	if (conv->pre_linear_resample)
684		in_frames = linear_resampler_in_frames_to_out(
685				conv->resampler,
686				in_frames);
687	in_frames = cras_frames_at_rate(conv->in_fmt.frame_rate,
688				   in_frames,
689				   conv->out_fmt.frame_rate);
690	if (!conv->pre_linear_resample)
691		in_frames = linear_resampler_in_frames_to_out(
692				conv->resampler,
693				in_frames);
694	return in_frames;
695}
696
697size_t cras_fmt_conv_out_frames_to_in(struct cras_fmt_conv *conv,
698				      size_t out_frames)
699{
700	if (!conv)
701		return out_frames;
702	if (!conv->pre_linear_resample)
703		out_frames = linear_resampler_out_frames_to_in(
704				conv->resampler,
705				out_frames);
706	out_frames = cras_frames_at_rate(conv->out_fmt.frame_rate,
707				   out_frames,
708				   conv->in_fmt.frame_rate);
709	if (conv->pre_linear_resample)
710		out_frames = linear_resampler_out_frames_to_in(
711				conv->resampler,
712				out_frames);
713	return out_frames;
714}
715
716void cras_fmt_conv_set_linear_resample_rates(struct cras_fmt_conv *conv,
717					     float from,
718					     float to)
719{
720	linear_resampler_set_rates(conv->resampler, from, to);
721}
722
723size_t cras_fmt_conv_convert_frames(struct cras_fmt_conv *conv,
724				    const uint8_t *in_buf,
725				    uint8_t *out_buf,
726				    unsigned int *in_frames,
727				    size_t out_frames)
728{
729	uint32_t fr_in, fr_out;
730	uint8_t *buffers[MAX_NUM_CONVERTERS + 1]; /* converters + out buffer. */
731	size_t buf_idx = 0;
732	static int logged_frames_dont_fit;
733	unsigned int used_converters = conv->num_converters;
734	unsigned int post_linear_resample = 0;
735	unsigned int pre_linear_resample = 0;
736	unsigned int linear_resample_fr = 0;
737
738	assert(conv);
739
740	if (linear_resampler_needed(conv->resampler)) {
741		post_linear_resample = !conv->pre_linear_resample;
742		pre_linear_resample = conv->pre_linear_resample;
743	}
744
745	/* If no SRC, then in_frames should = out_frames. */
746	if (conv->speex_state == NULL) {
747		fr_in = MIN(*in_frames, out_frames);
748		if (out_frames < *in_frames && !logged_frames_dont_fit) {
749			syslog(LOG_INFO,
750			       "fmt_conv: %u to %zu no SRC.",
751			       *in_frames,
752			       out_frames);
753			logged_frames_dont_fit = 1;
754		}
755	} else {
756		fr_in = *in_frames;
757	}
758	fr_out = fr_in;
759
760	/* Set up a chain of buffers.  The output buffer of the first conversion
761	 * is used as input to the second and so forth, ending in the output
762	 * buffer. */
763	if (!linear_resampler_needed(conv->resampler))
764		used_converters--;
765
766	buffers[4] = (uint8_t *)conv->tmp_bufs[3];
767	buffers[3] = (uint8_t *)conv->tmp_bufs[2];
768	buffers[2] = (uint8_t *)conv->tmp_bufs[1];
769	buffers[1] = (uint8_t *)conv->tmp_bufs[0];
770	buffers[0] = (uint8_t *)in_buf;
771	buffers[used_converters] = out_buf;
772
773	if (pre_linear_resample) {
774		linear_resample_fr = fr_in;
775		unsigned resample_limit = out_frames;
776
777		/* If there is a 2nd fmt conversion we should convert the
778		 * resample limit and round it to the lower bound in order
779		 * not to convert too many frames in the pre linear resampler.
780		 */
781		if (conv->speex_state != NULL)
782			resample_limit = resample_limit * conv->in_fmt.frame_rate /
783					conv->out_fmt.frame_rate;
784
785		resample_limit = MIN(resample_limit, conv->tmp_buf_frames);
786		fr_in = linear_resampler_resample(
787				conv->resampler,
788				buffers[buf_idx],
789				&linear_resample_fr,
790				buffers[buf_idx + 1],
791				resample_limit);
792		buf_idx++;
793	}
794
795	/* If the input format isn't S16_LE convert to it. */
796	if (conv->in_fmt.format != SND_PCM_FORMAT_S16_LE) {
797		conv->in_format_converter(buffers[buf_idx],
798					  fr_in * conv->in_fmt.num_channels,
799					  (uint8_t *)buffers[buf_idx + 1]);
800		buf_idx++;
801	}
802
803	/* Then channel conversion. */
804	if (conv->channel_converter != NULL) {
805		conv->channel_converter(conv,
806					(int16_t *)buffers[buf_idx],
807					fr_in,
808					(int16_t *)buffers[buf_idx + 1]);
809		buf_idx++;
810	}
811
812	/* Then SRC. */
813	if (conv->speex_state != NULL) {
814		unsigned int out_limit = out_frames;
815
816		if (post_linear_resample)
817			out_limit = linear_resampler_out_frames_to_in(
818					conv->resampler, out_limit);
819		fr_out = cras_frames_at_rate(conv->in_fmt.frame_rate,
820					     fr_in,
821					     conv->out_fmt.frame_rate);
822		if (fr_out > out_frames + 1 && !logged_frames_dont_fit) {
823			syslog(LOG_INFO,
824			       "fmt_conv: put %u frames in %zu sized buffer",
825			       fr_out,
826			       out_frames);
827			logged_frames_dont_fit = 1;
828		}
829		/* limit frames to the output size. */
830		fr_out = MIN(fr_out, out_limit);
831		speex_resampler_process_interleaved_int(
832				conv->speex_state,
833				(int16_t *)buffers[buf_idx],
834				&fr_in,
835				(int16_t *)buffers[buf_idx + 1],
836				&fr_out);
837		buf_idx++;
838	}
839
840	if (post_linear_resample) {
841		linear_resample_fr = fr_out;
842		unsigned resample_limit = MIN(conv->tmp_buf_frames, out_frames);
843		fr_out = linear_resampler_resample(
844				conv->resampler,
845				buffers[buf_idx],
846				&linear_resample_fr,
847				buffers[buf_idx + 1],
848				resample_limit);
849		buf_idx++;
850	}
851
852	/* If the output format isn't S16_LE convert to it. */
853	if (conv->out_fmt.format != SND_PCM_FORMAT_S16_LE) {
854		conv->out_format_converter(buffers[buf_idx],
855					   fr_out * conv->out_fmt.num_channels,
856					   (uint8_t *)buffers[buf_idx + 1]);
857		buf_idx++;
858	}
859
860	if (pre_linear_resample)
861		*in_frames = linear_resample_fr;
862	else
863		*in_frames = fr_in;
864	return fr_out;
865}
866
867int cras_fmt_conversion_needed(const struct cras_fmt_conv *conv)
868{
869	return linear_resampler_needed(conv->resampler) ||
870	       (conv->num_converters > 1);
871}
872
873/* If the server cannot provide the requested format, configures an audio format
874 * converter that handles transforming the input format to the format used by
875 * the server. */
876int config_format_converter(struct cras_fmt_conv **conv,
877			    enum CRAS_STREAM_DIRECTION dir,
878			    const struct cras_audio_format *from,
879			    const struct cras_audio_format *to,
880			    unsigned int frames)
881{
882	struct cras_audio_format target;
883
884	/* For input, preserve the channel count and layout of
885	 * from format */
886	if (dir == CRAS_STREAM_INPUT) {
887		target = *from;
888		target.format = to->format;
889		target.frame_rate = to->frame_rate;
890	} else {
891		target = *to;
892	}
893
894	syslog(LOG_DEBUG,
895	       "format convert: from:%d %zu %zu target: %d %zu %zu "
896	       "frames = %u",
897	       from->format, from->frame_rate, from->num_channels,
898	       target.format, target.frame_rate, target.num_channels,
899	       frames);
900	*conv = cras_fmt_conv_create(from, &target, frames,
901				     (dir == CRAS_STREAM_INPUT));
902	if (!*conv) {
903		syslog(LOG_ERR, "Failed to create format converter");
904		return -ENOMEM;
905	}
906
907	return 0;
908}
909