88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER START
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The contents of this file are subject to the terms of the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common Development and Distribution License (the "License").
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You may not use this file except in compliance with the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the License for the specific language governing permissions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and limitations under the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER END
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Copyright (C) 4Front Technologies 1996-2008.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Purpose: Audio format conversion routines used by audio.c
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/types.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/ddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/sunddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/audio/g711.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include "audio_impl.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include "audio_grc3.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amoreextern uint_t audio_intrhz;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note: In the function below, the division by the number of channels is
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * probably fairly expensive. It turns out that we usually deal with stereo
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or mono data, so perhaps it would be useful to build custom versions of
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * this function that only dealt with stereo or mono.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoredo_src(audio_stream_t *sp, void *p1, void *p2, int len, int nchan)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int ch, size;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that we presume that we are doing sample rate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * conversions on AUDIO_FORMAT_S24_NE, which means that have 4
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * byte and 32-bit samples.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore size = sp->s_cnv_max / 4; /* sample size is 4 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore size /= nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (ch = 0; ch < nchan; ch++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_convert(sp->s_src_state[ch], sp->s_src_quality,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore p1, p2, len, size, nchan, ch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (((grc3state_t *)sp->s_src_state[0])->outsz);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoresetup_src(audio_stream_t *sp, int srate, int trate, int sch, int tch)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int ch, nch;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nch = min(sch, tch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(nch <= AUDIO_MAX_CHANNELS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_src_quality < 1)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_src_quality = 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_src_quality > 5)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_src_quality = 5;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (ch = 0; ch < nch; ch++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_reset(sp->s_src_state[ch]);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore grc3_setup(sp->s_src_state[ch], srate, trate);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_srconly(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *dst = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We must be using 24-bit native signed.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_s24oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Endian switch works in both directions. We do it in place.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *src = ddi_swap32(*src);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore src++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s8(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int8_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (*src++) << 16;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_u8(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (int8_t)((*src++) ^ 0x80) << 16;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_ulaw(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = _8ulaw2linear16[(*src++)] << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_alaw(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = _8alaw2linear16[(*src++)] << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s16ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int16_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (*src++) << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s16oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int16_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (int16_t)(ddi_swap16(*src++)) << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_u16ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (int16_t)((*src++) ^ 0x8000) << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_u16oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (int16_t)(ddi_swap16((*src++) ^ 0x8000)) << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s24p(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *s = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore void *d = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *src = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* NB: this is a little endian format */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = (*src++);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= (*src++) << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= (*src++) << 16;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = s;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s32ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* 32-bit conversions can be done in place */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *src = *src >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_from_s32oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* 32-bit conversions can be done in place */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *src = (int32_t)(ddi_swap32(*src)) >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NB: All the destination format conversions use the same or fewer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * bytes as the 24-bit unpacked (32-bits used per sample), so we can
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * convert all of them in place.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_u8(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (*src++ >> 16) ^ 0x80;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s8(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int8_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = *src++ >> 16;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_ulaw(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int idx = *src++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx >>= 10;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx += G711_ULAW_MIDPOINT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx &= 0x3fff; /* safety precaution */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = _14linear2ulaw8[idx];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_alaw(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int idx = *src++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx >>= 11;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx += G711_ALAW_MIDPOINT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idx &= 0x1fff; /* safety precaution */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = _13linear2alaw8[idx];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s16ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int16_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = *src++ >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s16oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int16_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = ddi_swap16(*src++ >> 8);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_u16ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (*src++ >> 8) ^ 0x8000;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_u16oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = ddi_swap16(*src++ >> 8) ^ 0x8000;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s24p(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *dst = (void *)src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t d;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* NB: this is a little endian format */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore d = *src++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = d & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (d >> 8) & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = (d >> 16) & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s32ne(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *src = *src << 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_to_s32oe(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *src = ddi_swap32(*src << 8);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorecnv_default(audio_stream_t *sp, int len)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that the formats were already preverified during
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * select_converter, to ensure that only supported formats are
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * used.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Convert samples to 24 bit (32 bit lsb aligned) if
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * necessary.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (sp->s_cnv_src_format) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U8:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_u8(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S8:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s8(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_ULAW:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_ulaw(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_ALAW:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_alaw(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S16_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s16ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S16_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s16oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U16_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_u16ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U16_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_u16oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S32_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s32ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S32_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s32oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S24_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_s24oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S24_PACKED:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_from_s24p(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If we aren't decreasing the number of channels, then do the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * SRC now. (We prefer to do SRC on the smaller number of channels.)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src_nchan <= sp->s_cnv_dst_nchan) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Convert between mono and stereo
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_src_nchan != sp->s_cnv_dst_nchan) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int tc = sp->s_cnv_dst_nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int sc = sp->s_cnv_src_nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int nc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sc == 1) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Mono expansion. We expand into the stereo
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * channel, and leave other channels silent.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = len; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = *src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = *src++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int j = tc - 2; j > 0; j--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (sc == 2 && tc == 1) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Stereo -> mono. We do stereo separately to make
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the division fast (div by const 2 is just shift).
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = len; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Take just the left channel sample,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * discard the right channel.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *dst++ = *src++; /* left */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore src++; /* right */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Multi channel conversions. We just copy the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * minimum number of channels.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Calculate number of frames */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nc = min(sc, tc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Clear destination */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bzero(dst, (len * tc * sizeof (int32_t)));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = len; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int c;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (c = 0; c < nc; c++)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dst[c] = src[c];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore src += sc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dst += tc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If we didn't do SRC pre-conversion, then do it now.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src_nchan > sp->s_cnv_dst_nchan) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *src = sp->s_cnv_src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int32_t *dst = sp->s_cnv_dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = do_src(sp, src, dst, len, sp->s_cnv_dst_nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_src = dst;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_dst = src;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Finally convert samples from internal 24 bit format to target format
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (sp->s_cnv_dst_format) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U8:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_u8(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S8:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s8(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S16_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s16ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S16_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s16oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U16_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_u16ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_U16_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_u16oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S24_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_s24oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S24_PACKED:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s24p(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S32_NE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s32ne(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_S32_OE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_s32oe(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_ULAW:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_ulaw(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUDIO_FORMAT_ALAW:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len = cnv_to_alaw(sp, len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (len);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic const struct audio_format_info {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned format;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int sampsize;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_cnv_func_t from;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_cnv_func_t to;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} audio_format_info[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S8, 1, cnv_from_s8, cnv_to_s8 },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_U8, 1, cnv_from_u8, cnv_to_u8 },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_ULAW, 1, cnv_from_ulaw, cnv_to_ulaw },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_ALAW, 1, cnv_from_alaw, cnv_to_alaw },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S16_NE, 2, cnv_from_s16ne, cnv_to_s16ne },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S16_OE, 2, cnv_from_s16oe, cnv_to_s16oe },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_U16_NE, 2, cnv_from_u16ne, cnv_to_u16ne },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_U16_OE, 2, cnv_from_u16oe, cnv_to_u16oe },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S32_NE, 4, cnv_from_s32ne, cnv_to_s32ne },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S32_OE, 4, cnv_from_s32oe, cnv_to_s32oe },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* 24-bit formats are "special" */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S24_NE, 4, NULL, NULL },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S24_OE, 4, cnv_s24oe, cnv_s24oe },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_S24_PACKED, 3, cnv_from_s24p, cnv_to_s24p },
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* sentinel */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { AUDIO_FORMAT_NONE, 0, NULL, NULL }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amoreauimpl_format_setup(audio_stream_t *sp, audio_parms_t *parms, uint_t mask)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore audio_parms_t source;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore audio_parms_t target;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore audio_parms_t *uparms;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_cnv_func_t converter = NULL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const struct audio_format_info *info;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int expand = AUDIO_UNIT_EXPAND;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned cnv_sampsz = sizeof (uint32_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned cnv_max;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore boolean_t needsrc = B_FALSE;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uint_t framesz;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uint_t fragfr;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uint_t fragbytes;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uint_t nfrags;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore ASSERT(mutex_owned(&sp->s_lock));
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore source = sp->s_cnv_src_parms;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore target = sp->s_cnv_dst_parms;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp == &sp->s_client->c_ostream) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_FMT)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore source.p_format = parms->p_format;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_RATE)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore source.p_rate = parms->p_rate;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_CHAN)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore source.p_nchan = parms->p_nchan;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uparms = &source;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_FMT)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore target.p_format = parms->p_format;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_RATE)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore target.p_rate = parms->p_rate;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (mask & FORMAT_MSK_CHAN)
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore target.p_nchan = parms->p_nchan;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore uparms = &target;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * At least one of the source or target are S24_NE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If we have a signed/native endian format, then pick an
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * optimized converter. While at it, ensure that a valid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * format is selected.
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore *
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * After this function executes, "info" will point to the
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * format information for the user parameters.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (source.p_format != AUDIO_FORMAT_S24_NE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (info = &audio_format_info[0]; info->sampsize; info++) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (source.p_format == info->format) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore converter = info->from;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore expand *= sizeof (int32_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore expand /= info->sampsize;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* save source frame size */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cnv_sampsz = info->sampsize;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore } else {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore /*
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * Target format. Note that this case is also taken
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * if we're operating on S24_NE data. In that case
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * the converter will be NULL and expand will not be
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * altered.
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (info = &audio_format_info[0]; info->sampsize; info++) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (target.p_format == info->format) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore converter = info->to;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore expand *= info->sampsize;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore expand /= sizeof (int32_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (info->format == AUDIO_FORMAT_NONE) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore audio_dev_warn(sp->s_client->c_dev, "invalid format selected");
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore return (EINVAL);
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore ASSERT(info->sampsize);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (source.p_nchan != target.p_nchan) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * if channels need conversion, then we must use the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * default.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore converter = cnv_default;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore expand *= target.p_nchan;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore expand /= source.p_nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (source.p_rate != target.p_rate) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore needsrc = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore converter = (converter == NULL) ? cnv_srconly : cnv_default;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore expand *= target.p_rate;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore expand /= source.p_rate;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Figure out the size of the conversion buffer we need. We
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * assume room for two full source fragments, which ought to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * be enough, even with rounding errors.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore cnv_max = 2 * (source.p_rate / audio_intrhz) *
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore cnv_sampsz * source.p_nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If the conversion will cause us to expand fragments, then
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we need to increase cnv_max. Scale by AUDIO_UNIT_EXPAND to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * avoid rouding errors or losing bits when doing reducing
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * conversions.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (expand > AUDIO_UNIT_EXPAND) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cnv_max *= expand;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cnv_max /= AUDIO_UNIT_EXPAND;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore framesz = info->sampsize * uparms->p_nchan;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore fragfr = (uparms->p_rate / audio_intrhz);
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore fragbytes = fragfr * framesz;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore /*
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * We need to "tune" the buffer and fragment counts for some
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * uses... OSS applications may like to configure a low
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * latency, and they rely upon write() to block to prevent too
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * much data from being queued up.
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (sp->s_hintsz) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore nfrags = sp->s_hintsz / fragbytes;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore } else if (sp->s_hintfrags) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore nfrags = sp->s_hintfrags;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore } else {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore nfrags = sp->s_allocsz / fragbytes;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore /*
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * Now make sure that the hint works -- we need at least 2 fragments,
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * and we need to fit within the room allocated to us.
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (nfrags < 2) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore nfrags = 2;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore while ((nfrags * fragbytes) > sp->s_allocsz) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore nfrags--;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore /* if the resulting configuration is invalid, note it */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (nfrags < 2) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore return (EINVAL);
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore }
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Now we need to allocate space.
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore *
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * NB: Once the allocation succeeds, we must not fail. We are
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * modifying the the stream settings and these changes must be
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore * made atomically.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_max < cnv_max) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t *buf0, *buf1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore buf0 = kmem_alloc(cnv_max, KM_NOSLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore buf1 = kmem_alloc(cnv_max, KM_NOSLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((buf0 == NULL) || (buf1 == NULL)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(sp->s_client->c_dev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "failed to allocate audio conversion buffer "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "(%u bytes)", cnv_max);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (buf0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(buf0, cnv_max);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (buf1)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(buf1, cnv_max);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (ENOMEM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_buf0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(sp->s_cnv_buf0, sp->s_cnv_max);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_cnv_buf1)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(sp->s_cnv_buf1, sp->s_cnv_max);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_buf0 = buf0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_buf1 = buf1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_max = cnv_max;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore /* Set up the SRC state if we will be using SRC. */
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore if (needsrc) {
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore setup_src(sp, source.p_rate, target.p_rate,
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore source.p_nchan, target.p_nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore
a702341c8e6cc834a456108a8bf5d22f031da3beGarrett D'Amore
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_framesz = framesz;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_fragfr = fragfr;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_fragbytes = fragbytes;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_nfrags = nfrags;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_nframes = nfrags * fragfr;
2c30fa4582c5d6c659e059e719c5f6163f7ef1e3Garrett D'Amore sp->s_nbytes = sp->s_nframes * framesz;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *sp->s_user_parms = *uparms;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_converter = converter;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Ensure that we toss any stale data -- probably wrong format.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that as a consequence of this, all of the offsets and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * counters get reset. Clients should not rely on these values
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * being preserved when changing formats.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Its critical that we reset the indices, in particular,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * because not only will the data be the wrong format, but the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * indices themselves are quite possibly going to be invalid.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_cnv_cnt = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_tail = sp->s_head = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_tidx = sp->s_hidx = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauimpl_format_alloc(audio_stream_t *sp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&sp->s_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_src_state[i] =
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_zalloc(sizeof (grc3state_t), KM_NOSLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_src_state[i] == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(sp->s_client->c_dev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "unable to allocate SRC state structures");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (ENOMEM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauimpl_format_free(audio_stream_t *sp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (sp->s_src_state[i] != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(sp->s_src_state[i], sizeof (grc3state_t));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore sp->s_src_state[i] = NULL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}