自适应通透ANC调试

/*!
\copyright  Copyright (c) 2019 - 2023 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\version    
\file       kymera_a2dp_mirror.c
\brief      Kymera A2DP for TWM.
*/
 
#if defined(INCLUDE_MIRRORING) && !defined(ENABLE_TWM_SPEAKER)
#include "kymera_a2dp.h"
#include "kymera_a2dp_private.h"
#include "kymera_dsp_clock.h"
#include "kymera_buffer_utils.h"
#include "kymera_state.h"
#include "kymera_internal_msg_ids.h"
#include "kymera_source_sync.h"
#include "kymera_music_processing.h"
#include "kymera_config.h"
#include "kymera_latency_manager.h"
#include "kymera_output.h"
#include "kymera_leakthrough.h"
#include "kymera_data.h"
#include "kymera_setup.h"
#include "av.h"
#include "a2dp_profile_config.h"
#include "multidevice.h"
#include "mirror_profile_protected.h"
#include "kymera_anc_common.h"
#include "kymera_latency_manager.h"
#include "timestamp_event.h"
#include "kymera_output_if.h"
#include "handset_service.h"
#include "system_state.h"
#include <operators.h>
#include <rtime.h>
 
/*! Helper defines for RTP header format. These
    are used for hash transform configuration */
#define RTP_HEADER_LENGTH (12)
#define RTP_HEADER_SEQUENCE_NO_OFFSET (2)
 
/*! Enable toggling on PIO21 during key A2DP mirroring start events.
    This is useful for determining the time taken in the different
    parts of the start procedure.
 
    The PIOs need to be setup in pydbg as outputs controlled by P1:
    mask = 1<<21
    apps1.fw.call.PioSetMapPins32Bank(0, mask, mask)
    apps1.fw.call.PioSetDir32Bank(0, mask, mask)
*/
#ifdef KYMERA_PIO_TOGGLE
#include "pio.h"
#define KYMERA_PIO_MASK (1<<21)
#define KymeraPioSet() PioSet32Bank(0, KYMERA_PIO_MASK, KYMERA_PIO_MASK)
#define KymeraPioClr() PioSet32Bank(0, KYMERA_PIO_MASK, 0)
#else
#define KymeraPioSet()
#define KymeraPioClr()
#endif
 
static bool appKymeraA2dpGetPreferredChainOutput(kymera_output_chain_config *config);
static void appKymeraSendAudioSynchronisedMessage(rtime_t sync_time);
 
static const output_callbacks_t appKymeraA2dpMirrorCallbacks =
{
 
   .OutputGetPreferredChainConfig = appKymeraA2dpGetPreferredChainOutput,
};
 
static const output_registry_entry_t output_info =
{
 
    .user = output_user_a2dp,
    .connection = output_connection_mono,
    .callbacks = &appKymeraA2dpMirrorCallbacks,
};
 
static void appKymeraA2dpPopulateOutputChainConfig(a2dp_params_getter_t a2dp_params, kymera_output_chain_config *config)
{
 
    unsigned kick_period = KICK_PERIOD_FAST;
    unsigned block_size = DEFAULT_CODEC_BLOCK_SIZE;
    uint32   music_processing_kick_back_threshold = 256;
 
    DEBUG_LOG("appKymeraA2dpPopulateOutputChainConfig");
 
    switch (a2dp_params.seid)
    {
 
        case AV_SEID_SBC_SNK:
            kick_period = KICK_PERIOD_MASTER_SBC;
            block_size = SBC_CODEC_BLOCK_SIZE;
            break;
 
        case AV_SEID_AAC_SNK:
            kick_period = KICK_PERIOD_MASTER_AAC;
            block_size = AAC_CODEC_BLOCK_SIZE;
            music_processing_kick_back_threshold = block_size;
            break;
 
        case AV_SEID_APTX_SNK:
            kick_period = KICK_PERIOD_MASTER_APTX;
            block_size = APTX_CODEC_BLOCK_SIZE;
            break;
 
        case AV_SEID_APTX_ADAPTIVE_SNK:
            if (appKymeraIsAptxR22Enabled() == TRUE)
            { /* slow kick period, block size larger than the 2.1 mode */
                kick_period = KICK_PERIOD_MASTER_APTX;
                block_size = APTX_ADAPTIVE_CODEC_BLOCK_SIZE;
            }
            else
            { /* Fast kick period, block size the same as classic */
                kick_period = KICK_PERIOD_MASTER_APTX_ADAPTIVE;
                block_size = APTX_CODEC_BLOCK_SIZE;
            }
            break;
 
        default:
            kick_period = KICK_PERIOD_TONES;
            block_size = 0;
            break;
    }
    if (Kymera_FastKickPeriodInGamingMode() && Kymera_LatencyManagerIsGamingModeEnabled())
    {
 
        kick_period = KICK_PERIOD_FAST;
    }
    config->rate = a2dp_params.rate;
    config->kick_period = kick_period;
 
    if(Kymera_IsMusicProcessingPresent())
    {
 
        config->source_sync_kick_back_threshold = music_processing_kick_back_threshold;
    }
    else
    {
 
        config->source_sync_kick_back_threshold = block_size;
    }
 
    if (kick_period == KICK_PERIOD_SLOW)
    {
 
        config->source_sync_max_period = appKymeraGetSlowKickSourceSyncPeriod(TRUE);
        config->source_sync_min_period = appKymeraGetSlowKickSourceSyncPeriod(FALSE);
    }
    else if (kick_period == KICK_PERIOD_FAST)
    {
 
        config->source_sync_max_period = appKymeraGetFastKickSourceSyncPeriod(TRUE);
        config->source_sync_min_period = appKymeraGetFastKickSourceSyncPeriod(FALSE);
    }
    config->set_source_sync_min_period = TRUE;
    config->set_source_sync_max_period = TRUE;
    config->set_source_sync_kick_back_threshold = TRUE;
 
    /* Output buffer is 2.5*KP */
    appKymeraSetSourceSyncConfigOutputBufferSize(config, 5, 2);
    appKymeraSetSourceSyncConfigInputBufferSize(config, block_size);
    config->chain_type = output_chain_mono;
}
 
static bool appKymeraA2dpGetA2dpParametersPrediction(uint32 *rate, uint8 *seid)
{
 
    const kymera_callback_configs_t *config = Kymera_GetCallbackConfigs();
    DEBUG_LOG("appKymeraA2dpGetA2dpParametersPrediction");
    if ((config) && (config->GetA2dpParametersPrediction))
 
    {
 
        return config->GetA2dpParametersPrediction(rate, seid);
    }
    return FALSE;
}
 
static bool appKymeraA2dpGetPreferredChainOutput(kymera_output_chain_config *config)
{
 
    uint32 rate;
    uint8 seid;
    bool a2dp_params_are_valid = appKymeraA2dpGetA2dpParametersPrediction(&rate, &seid);
    if (a2dp_params_are_valid)
    {
 
        a2dp_params_getter_t a2dp_params;
        a2dp_params.rate = rate;
        a2dp_params.seid = seid;
 
        appKymeraA2dpPopulateOutputChainConfig(a2dp_params, config);
    }
    return a2dp_params_are_valid;
}
 
static void appKymeraSetAudioSyncCompleted(void)
{
 
    kymeraTaskData *theKymera = KymeraGetTaskData();
    theKymera->sync_info.state = KYMERA_AUDIO_SYNC_STATE_COMPLETE;
}
 
static void appKymeraCreateInputChain(kymeraTaskData *theKymera, uint8 seid, bool is_left)
{
 
    const chain_config_t *config = NULL;
    /* Create input chain */
    switch (seid)
    {
 
        case AV_SEID_SBC_SNK:
            DEBUG_LOG("appKymeraCreateInputChain, create TWM SBC input chain");
            config = Kymera_GetChainConfigs()->chain_input_sbc_stereo_mix_config;
        break;
 
        case AV_SEID_AAC_SNK:
            DEBUG_LOG("appKymeraCreateInputChain, create TWM AAC input chain");
            config = Kymera_GetChainConfigs()->chain_input_aac_stereo_mix_config;
        break;
 
        case AV_SEID_APTX_SNK:
            DEBUG_LOG("appKymeraCreateInputChain, create TWM aptX input chain");
            if (appConfigEnableAptxStereoMix())
            {
 
                config = Kymera_GetChainConfigs()->chain_input_aptx_stereo_mix_config;
            }
            else
            {
 
                config = is_left ? Kymera_GetChainConfigs()->chain_forwarding_input_aptx_left_config :
                                   Kymera_GetChainConfigs()->chain_forwarding_input_aptx_right_config;
            }
        break;
#ifdef INCLUDE_APTX_ADAPTIVE
    case AV_SEID_APTX_ADAPTIVE_SNK:
        DEBUG_LOG("appKymeraCreateInputChain, create TWM aptX adaptive input chain, Q2Q %u, R22 Mode %u", theKymera->q2q_mode, theKymera->aptx_adaptive_r22_dec);
        if (appConfigEnableAptxAdaptiveStereoMix())
        {
 
#ifdef INCLUDE_APTX_ADAPTIVE_22
            if (theKymera->aptx_adaptive_r22_dec)
            {
 
                if (appConfigEnableAptxAdaptiveStereoMixLossless())
                {
 
                    if (theKymera->q2q_mode)
                        config = Kymera_GetChainConfigs()->chain_input_aptx_adaptive_r3_stereo_mix_q2q_config;
                    else
                        Panic();
                }
                else
                {
 
                    if (theKymera->q2q_mode)
                        config = Kymera_GetChainConfigs()->chain_input_aptx_adaptive_r3_mono_q2q_config;
                    else
                        config = Kymera_GetChainConfigs()->chain_input_aptx_adaptive_r3_mono_config;
                }
            }
            else
#endif
            {
 
                if (theKymera->q2q_mode)
                    config =  Kymera_GetChainConfigs()->chain_input_aptx_adaptive_stereo_mix_q2q_config;
                else
                    config =  Kymera_GetChainConfigs()->chain_input_aptx_adaptive_stereo_mix_config;
            }
 
        }
        else
        {/* We do not support forwarding for aptX adaptive */
            Panic();
        }
    break;
 
#endif
        default:
            Panic();
        break;
    }
    theKymera->chain_input_handle = PanicNull(ChainCreate(config));
}
 
static uint32 appKymeraGetCodecMaxBitrate(uint8 seid)
{
 
    switch (seid)
    {
 
        // Use the same max bitrate, could be optimized if needed
        case AV_SEID_SBC_SNK:
        case AV_SEID_AAC_SNK:
        case AV_SEID_APTX_SNK:
            return APTX_STEREO_CODEC_RATE_KBPS * 1000;
        case AV_SEID_APTX_ADAPTIVE_SNK:
            return APTX_AD_CODEC_RATE_KBPS * 1000;
        default:
            Panic();
            return 0;
    }
}
 
static void appKymeraConfigureInputChain(kymeraTaskData *theKymera,
                                         uint8 seid, uint32 rate, uint32 max_bitrate,
                                         bool cp_header_enabled, bool is_left,
                                         aptx_adaptive_ttp_latencies_t nq2q_ttp)
{
 
    UNUSED(nq2q_ttp);
    kymera_chain_handle_t chain_handle = theKymera->chain_input_handle;
    rtp_codec_type_t rtp_codec = -1;
    Operator op;
    unsigned rtp_buffer_size = 0;
    Operator op_rtp_decoder = ChainGetOperatorByRole(chain_handle, OPR_RTP_DECODER);
 
    max_bitrate = (max_bitrate) ? max_bitrate : appKymeraGetCodecMaxBitrate(seid);
    rtp_buffer_size = Kymera_GetAudioBufferSize(max_bitrate, TWS_STANDARD_LATENCY_MAX_MS);
 
#if !defined(INCLUDE_APTX_ADAPTIVE)
    UNUSED(nq2q_ttp);
#endif
 
    switch (seid)
    {
 
        case AV_SEID_SBC_SNK:
            DEBUG_LOG("appKymeraConfigureAndConnectInputChain, configure TWM SBC input chain");
            rtp_codec = rtp_codec_type_sbc;
        break;
 
        case AV_SEID_AAC_SNK:
            DEBUG_LOG("appKymeraConfigureAndConnectInputChain, configure TWM AAC input chain");
            rtp_codec = rtp_codec_type_aac;
        break;
 
        case AV_SEID_APTX_SNK:
            DEBUG_LOG("appKymeraConfigureAndConnectInputChain, configure TWM aptX input chain");
            rtp_codec = rtp_codec_type_aptx;
 
            op = PanicZero(ChainGetOperatorByRole(chain_handle, OPR_APTX_DEMUX));
            OperatorsStandardSetSampleRate(op, rate);
            op = PanicZero(ChainGetOperatorByRole(chain_handle, OPR_SWITCHED_PASSTHROUGH_CONSUMER));
            OperatorsSetSwitchedPassthruEncoding(op, spc_op_format_encoded);
 
            if (appConfigEnableAptxStereoMix())
            {
 
                spc_mode_t sync_mode = spc_op_mode_tagsync_dual;
                OperatorsSetSwitchedPassthruMode(op, sync_mode);
            }
 
 
        break;
#ifdef INCLUDE_APTX_ADAPTIVE
    case AV_SEID_APTX_ADAPTIVE_SNK:
        DEBUG_LOG("appKymeraConfigureAndConnectInputChain, configure TWM aptX adaptive input chain");
 
        aptx_adaptive_ttp_in_ms_t aptx_ad_ttp;
 
        if (theKymera->q2q_mode)
        {
 
            op = PanicZero(ChainGetOperatorByRole(chain_handle, OPR_SWITCHED_PASSTHROUGH_CONSUMER));
            OperatorsSetSwitchedPassthruEncoding(op, spc_op_format_encoded);
            OperatorsStandardSetBufferSizeWithFormat(op, rtp_buffer_size, operator_data_format_encoded);
            OperatorsSetSwitchedPassthruMode(op, spc_op_mode_passthrough);
        }
        else
        {
 
            convertAptxAdaptiveTtpToOperatorsFormat(nq2q_ttp, &aptx_ad_ttp);
            getAdjustedAptxAdaptiveTtpLatencies(&aptx_ad_ttp);
 
            OperatorsRtpSetAptxAdaptiveTTPLatency(op_rtp_decoder, aptx_ad_ttp);
            rtp_codec = rtp_codec_type_aptx_ad;
        }
 
        /* Need a separate operator f
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值