Home | History | Annotate | Download | only in server
      1 /* Copyright (c) 2014 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 #include <stdlib.h>
      7 #include <sys/param.h>
      8 
      9 #include "cras_audio_area.h"
     10 #include "cras_audio_format.h"
     11 #include "cras_mix.h"
     12 
     13 struct cras_audio_area *cras_audio_area_create(int num_channels)
     14 {
     15 	struct cras_audio_area *area;
     16 	size_t sz;
     17 
     18 	sz = sizeof(*area) + num_channels * sizeof(struct cras_channel_area);
     19 	area = calloc(1, sz);
     20 	area->num_channels = num_channels;
     21 
     22 	return area;
     23 }
     24 
     25 unsigned int cras_audio_area_copy(const struct cras_audio_area *dst,
     26 				  unsigned int dst_offset,
     27 				  const struct cras_audio_format *dst_fmt,
     28 				  const struct cras_audio_area *src,
     29 				  unsigned int src_offset,
     30 				  float software_gain_scaler)
     31 {
     32 	unsigned int src_idx, dst_idx;
     33 	unsigned int ncopy;
     34 	uint8_t *schan, *dchan;
     35 
     36 	ncopy = MIN(src->frames - src_offset, dst->frames - dst_offset);
     37 
     38 	/* TODO(dgreid) - this replaces a memcpy, it needs to be way faster. */
     39 	for (src_idx = 0; src_idx < src->num_channels; src_idx++) {
     40 
     41 		for (dst_idx = 0; dst_idx < dst->num_channels; dst_idx++) {
     42 			if (!(src->channels[src_idx].ch_set &
     43 			      dst->channels[dst_idx].ch_set))
     44 				continue;
     45 
     46 			schan = src->channels[src_idx].buf +
     47 				src_offset * src->channels[src_idx].step_bytes;
     48 			dchan = dst->channels[dst_idx].buf +
     49 				dst_offset * dst->channels[dst_idx].step_bytes;
     50 
     51 			cras_mix_add_scale_stride(dst_fmt->format, dchan, schan,
     52 					    ncopy,
     53 					    dst->channels[dst_idx].step_bytes,
     54 					    src->channels[src_idx].step_bytes,
     55 					    software_gain_scaler);
     56 		}
     57 	}
     58 
     59 	return ncopy;
     60 }
     61 
     62 void cras_audio_area_destroy(struct cras_audio_area *area)
     63 {
     64 	free(area);
     65 }
     66 
     67 void cras_audio_area_config_channels(struct cras_audio_area *area,
     68 				     const struct cras_audio_format *fmt)
     69 {
     70 	unsigned int i, ch;
     71 
     72 	/* For mono, config the channel type to match both front
     73 	 * left and front right.
     74 	 * TODO(hychao): add more mapping when we have like {FL, FC}
     75 	 * for mono + kb mic.
     76 	 */
     77 	if ((fmt->num_channels == 1) &&
     78 	    ((fmt->channel_layout[CRAS_CH_FC] == 0) ||
     79 	     (fmt->channel_layout[CRAS_CH_FL] == 0))) {
     80 		channel_area_set_channel(area->channels, CRAS_CH_FL);
     81 		channel_area_set_channel(area->channels, CRAS_CH_FR);
     82 		return;
     83 	}
     84 
     85 	for (i = 0; i < fmt->num_channels; i++) {
     86 		area->channels[i].ch_set = 0;
     87 		for (ch = 0; ch < CRAS_CH_MAX; ch++)
     88 			if (fmt->channel_layout[ch] == i)
     89 				channel_area_set_channel(&area->channels[i], ch);
     90 	}
     91 
     92 }
     93 
     94 void cras_audio_area_config_buf_pointers(struct cras_audio_area *area,
     95 					 const struct cras_audio_format *fmt,
     96 					 uint8_t *base_buffer)
     97 {
     98 	int i;
     99 	const int sample_size = snd_pcm_format_physical_width(fmt->format) / 8;
    100 
    101 	/* TODO(dgreid) - assuming interleaved audio here for now. */
    102 	for (i = 0 ; i < area->num_channels; i++) {
    103 		area->channels[i].step_bytes = cras_get_format_bytes(fmt);
    104 		area->channels[i].buf = base_buffer + i * sample_size;
    105 	}
    106 }
    107