mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 09:01:40 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/******************************************************************************
 | 
						|
 *
 | 
						|
 *  Copyright (C) 2014 The Android Open Source Project
 | 
						|
 *  Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
 | 
						|
 *
 | 
						|
 *  Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 *  you may not use this file except in compliance with the License.
 | 
						|
 *  You may obtain a copy of the License at:
 | 
						|
 *
 | 
						|
 *  http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 *  Unless required by applicable law or agreed to in writing, software
 | 
						|
 *  distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 *  See the License for the specific language governing permissions and
 | 
						|
 *  limitations under the License.
 | 
						|
 *
 | 
						|
 ******************************************************************************/
 | 
						|
 | 
						|
/**********************************************************************************
 | 
						|
  $Revision: #1 $
 | 
						|
***********************************************************************************/
 | 
						|
 | 
						|
/** @file
 | 
						|
@ingroup codec_internal
 | 
						|
*/
 | 
						|
 | 
						|
/**@addgroup codec_internal*/
 | 
						|
/**@{*/
 | 
						|
#include "common/bt_target.h"
 | 
						|
#include <oi_codec_sbc_private.h>
 | 
						|
 | 
						|
#if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE)
 | 
						|
 | 
						|
static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
 | 
						|
{
 | 
						|
    OI_UINT bitcountL;
 | 
						|
    OI_UINT bitcountR;
 | 
						|
    OI_UINT bitpoolPreferenceL = 0;
 | 
						|
    OI_UINT bitpoolPreferenceR = 0;
 | 
						|
    BITNEED_UNION1 bitneedsL;
 | 
						|
    BITNEED_UNION1 bitneedsR;
 | 
						|
 | 
						|
    bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
 | 
						|
    bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
 | 
						|
 | 
						|
    oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
 | 
						|
    oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
 | 
						|
}
 | 
						|
 | 
						|
static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
 | 
						|
{
 | 
						|
    const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
 | 
						|
    BITNEED_UNION2 bitneeds;
 | 
						|
    OI_UINT excess;
 | 
						|
    OI_INT bitadjust;
 | 
						|
    OI_UINT bitcount;
 | 
						|
    OI_UINT sbL;
 | 
						|
    OI_UINT sbR;
 | 
						|
    OI_UINT bitpoolPreference = 0;
 | 
						|
 | 
						|
    bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
 | 
						|
    bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
 | 
						|
 | 
						|
    {
 | 
						|
        OI_UINT ex;
 | 
						|
        bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
 | 
						|
        /* We want the compiler to put excess into a register */
 | 
						|
        excess = ex;
 | 
						|
    }
 | 
						|
    sbL = 0;
 | 
						|
    sbR = nrof_subbands;
 | 
						|
    while (sbL < nrof_subbands) {
 | 
						|
        excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
 | 
						|
        ++sbL;
 | 
						|
        excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
 | 
						|
        ++sbR;
 | 
						|
    }
 | 
						|
    sbL = 0;
 | 
						|
    sbR = nrof_subbands;
 | 
						|
    while (excess) {
 | 
						|
        excess = allocExcessBits(&common->bits.uint8[sbL], excess);
 | 
						|
        ++sbL;
 | 
						|
        if (!excess) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        excess = allocExcessBits(&common->bits.uint8[sbR], excess);
 | 
						|
        ++sbR;
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static const BIT_ALLOC balloc[] = {
 | 
						|
    monoBitAllocation,    /* SBC_MONO */
 | 
						|
    dualBitAllocation,    /* SBC_DUAL_CHANNEL */
 | 
						|
    stereoBitAllocation,  /* SBC_STEREO */
 | 
						|
    stereoBitAllocation   /* SBC_JOINT_STEREO */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
 | 
						|
{
 | 
						|
    OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
 | 
						|
    OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
 | 
						|
 | 
						|
    /*
 | 
						|
     * Using an array of function pointers prevents the compiler from creating a suboptimal
 | 
						|
     * monolithic inlined bit allocation function.
 | 
						|
     */
 | 
						|
    balloc[common->frameInfo.mode](common);
 | 
						|
}
 | 
						|
 | 
						|
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
 | 
						|
{
 | 
						|
    return internal_CalculateBitrate(frame);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Return the current maximum bitneed and clear it.
 | 
						|
 */
 | 
						|
OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
 | 
						|
{
 | 
						|
    OI_UINT8 max = common->maxBitneed;
 | 
						|
 | 
						|
    common->maxBitneed = 0;
 | 
						|
    return max;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Calculates the bitpool size for a given frame length
 | 
						|
 */
 | 
						|
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
 | 
						|
                                        OI_UINT16 frameLen)
 | 
						|
{
 | 
						|
    OI_UINT16 nrof_subbands = frame->nrof_subbands;
 | 
						|
    OI_UINT16 nrof_blocks = frame->nrof_blocks;
 | 
						|
    OI_UINT16 hdr;
 | 
						|
    OI_UINT16 bits;
 | 
						|
 | 
						|
    if (frame->mode == SBC_JOINT_STEREO) {
 | 
						|
        hdr = 9 * nrof_subbands;
 | 
						|
    } else {
 | 
						|
        if (frame->mode == SBC_MONO) {
 | 
						|
            hdr = 4 * nrof_subbands;
 | 
						|
        } else {
 | 
						|
            hdr = 8 * nrof_subbands;
 | 
						|
        }
 | 
						|
        if (frame->mode == SBC_DUAL_CHANNEL) {
 | 
						|
            nrof_blocks *= 2;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    bits = 8 * (frameLen - SBC_HEADER_LEN) - hdr;
 | 
						|
    return DIVIDE(bits, nrof_blocks);
 | 
						|
}
 | 
						|
 | 
						|
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
 | 
						|
{
 | 
						|
    return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
 | 
						|
{
 | 
						|
    return internal_CalculateFramelen(frame);
 | 
						|
}
 | 
						|
 | 
						|
/**@}*/
 | 
						|
#endif /* #if (defined(SBC_DEC_INCLUDED) && SBC_DEC_INCLUDED == TRUE) */
 |