187ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao * Use of this source code is governed by a BSD-style license that can be 387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao * found in the LICENSE file. 487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao */ 587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao#include <stdlib.h> 7c677a0b94719d82e9fab2bb7559e9818ef60d648Dylan Reid#include <sys/param.h> 887ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 987ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao#include "cras_audio_area.h" 1087ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao#include "cras_audio_format.h" 11501ff6948b4a88694c705964dc6fde86cb7340b2Dylan Reid#include "cras_mix.h" 1287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 1387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chaostruct cras_audio_area *cras_audio_area_create(int num_channels) 1487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao{ 1587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao struct cras_audio_area *area; 1687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao size_t sz; 1787ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 1887ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao sz = sizeof(*area) + num_channels * sizeof(struct cras_channel_area); 1987ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao area = calloc(1, sz); 2087ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao area->num_channels = num_channels; 2187ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 2287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao return area; 2387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao} 2487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 25bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reidunsigned int cras_audio_area_copy(const struct cras_audio_area *dst, 26bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid unsigned int dst_offset, 278cd4a917e6cef477799245a4e81fe3709ceff6c9Dylan Reid const struct cras_audio_format *dst_fmt, 28bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid const struct cras_audio_area *src, 29bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid unsigned int src_offset, 30a7031f6452138ef6edd64f5ef75002299e2dd32aCheng-Yi Chiang float software_gain_scaler) 311c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao{ 321c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao unsigned int src_idx, dst_idx; 33c677a0b94719d82e9fab2bb7559e9818ef60d648Dylan Reid unsigned int ncopy; 341c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao uint8_t *schan, *dchan; 351c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao 36bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid ncopy = MIN(src->frames - src_offset, dst->frames - dst_offset); 37c677a0b94719d82e9fab2bb7559e9818ef60d648Dylan Reid 381c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao /* TODO(dgreid) - this replaces a memcpy, it needs to be way faster. */ 391c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao for (src_idx = 0; src_idx < src->num_channels; src_idx++) { 401c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao 411c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao for (dst_idx = 0; dst_idx < dst->num_channels; dst_idx++) { 421c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao if (!(src->channels[src_idx].ch_set & 431c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao dst->channels[dst_idx].ch_set)) 441c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao continue; 451c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao 46bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid schan = src->channels[src_idx].buf + 477c1e82fbb2b8f139a096e7d4103bfa501b106c71Dylan Reid src_offset * src->channels[src_idx].step_bytes; 481c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao dchan = dst->channels[dst_idx].buf + 491c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao dst_offset * dst->channels[dst_idx].step_bytes; 501c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao 51dcbdb01f1bdafd5a60e23432744cc40fff4eef44Cheng-Yi Chiang cras_mix_add_scale_stride(dst_fmt->format, dchan, schan, 52501ff6948b4a88694c705964dc6fde86cb7340b2Dylan Reid ncopy, 53501ff6948b4a88694c705964dc6fde86cb7340b2Dylan Reid dst->channels[dst_idx].step_bytes, 54dcbdb01f1bdafd5a60e23432744cc40fff4eef44Cheng-Yi Chiang src->channels[src_idx].step_bytes, 55a7031f6452138ef6edd64f5ef75002299e2dd32aCheng-Yi Chiang software_gain_scaler); 561c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao } 571c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao } 58bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid 59bc0496defda90cdc6d4427d43bcbb04338400a0eDylan Reid return ncopy; 601c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao} 611c84d884fdfcd82c85cc6ab07a4b208b2d34d887Hsin-Yu Chao 6287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chaovoid cras_audio_area_destroy(struct cras_audio_area *area) 6387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao{ 6487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao free(area); 6587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao} 6687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 6787ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chaovoid cras_audio_area_config_channels(struct cras_audio_area *area, 6887ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao const struct cras_audio_format *fmt) 6987ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao{ 7087ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao unsigned int i, ch; 7187ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 7287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao /* For mono, config the channel type to match both front 7387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao * left and front right. 7487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao * TODO(hychao): add more mapping when we have like {FL, FC} 7587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao * for mono + kb mic. 7687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao */ 7787ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao if ((fmt->num_channels == 1) && 78b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao ((fmt->channel_layout[CRAS_CH_FC] == 0) || 79b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao (fmt->channel_layout[CRAS_CH_FL] == 0))) { 80b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao channel_area_set_channel(area->channels, CRAS_CH_FL); 8187ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao channel_area_set_channel(area->channels, CRAS_CH_FR); 82b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao return; 83b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao } 84b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao 85b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao for (i = 0; i < fmt->num_channels; i++) { 86b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao area->channels[i].ch_set = 0; 87b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao for (ch = 0; ch < CRAS_CH_MAX; ch++) 88b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao if (fmt->channel_layout[ch] == i) 89b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao channel_area_set_channel(&area->channels[i], ch); 90b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao } 91b2540cbe5809a7714c3fafc88fe41dafe1b6135aHsin-Yu Chao 9287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao} 9387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 9487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chaovoid cras_audio_area_config_buf_pointers(struct cras_audio_area *area, 9587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao const struct cras_audio_format *fmt, 9687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao uint8_t *base_buffer) 9787ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao{ 9887ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao int i; 9987ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao const int sample_size = snd_pcm_format_physical_width(fmt->format) / 8; 10087ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao 10187ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao /* TODO(dgreid) - assuming interleaved audio here for now. */ 10287ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao for (i = 0 ; i < area->num_channels; i++) { 10387ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao area->channels[i].step_bytes = cras_get_format_bytes(fmt); 10487ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao area->channels[i].buf = base_buffer + i * sample_size; 10587ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao } 10687ee399d94dc527c4ebe3e4da0febe1490f1f5fbHsin-Yu Chao} 107