QCC308X---ANC自适应通透

ANC自适应通透ANCAdaptive leakthrough 

 1. 关闭热敏检测功能:

2. 用MDE打开ADK_r784软件,打开ANC和自适应ANC的宏定义;

添加下列宏定义:ENABLE_ANC;

ENABLE_ENHANCED_ ANC;

ENABLE_ADAPTIVE_ANC;

ENABLE_ANC_AAH;

ENABLE_ANC_AAH_CC;

3. 在fw_cfg->subsys3_comfig2.htf文件中设置FF和FB Mic,本次案例FB是模拟MIC,在MIC1位置, instance0 channel A中;FF是数字MIC,放在instance2 channel A中;FF数字MIC的对应实际的PIO为PIO16/PIO17;

/*!
\copyright  Copyright (c) 2020-2023 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\version    
\file       kymera_adaptive_anc.c
\brief      Kymera Adaptive ANC code
*/
 
#include "kymera_adaptive_anc.h"
#include "kymera_dsp_clock.h"
#include "kymera_internal_msg_ids.h"
#include "kymera_lock.h"
#include "kymera_config.h"
#include "kymera_state.h"
#include "kymera_tones_prompts.h"
#include "anc_state_manager.h"
#include "microphones.h"
#include "kymera_aec.h"
#include "kymera_va.h"
#include "kymera_mic_if.h"
#include "kymera_output_if.h"
#include "kymera_data.h"
#include "kymera_setup.h"
#include <vmal.h>
#include <file.h>
#include <stdlib.h>
#include <cap_id_prim.h>
#include <opmsg_prim.h>
 
#include "kymera_fit_test.h"
#include "kymera_anc_common.h"
 
#ifdef ENABLE_ADAPTIVE_ANC
 
#define MAX_CHAIN (3)
#define CHAIN_MIC_REF_PATH_SPLITTER (MAX_CHAIN-1)
#define CHAIN_FBC (CHAIN_MIC_REF_PATH_SPLITTER-1)
#define CHAIN_AANC (CHAIN_FBC-1)
 
#define AANC_USB_AUDIO_MIC_CHANNELS     2   /* Number of mic and speaker channels in the audio data stream */
#define AANC_USB_AUDIO_SPKR_CHANNELS    1   /* Number of mic and speaker channels in the audio data stream */
 
#define AANC_SAMPLE_RATE 16000      /* Only 16KHz supported for anc tuning */
#define MAX_AANC_MICS (2)
 
#define kymeraAdaptiveAnc_IsAancActive() (kymeraAdaptiveAnc_GetChain(CHAIN_AANC) != NULL)
#define kymeraAdaptiveAnc_PanicIfNotActive()  if(!kymeraAdaptiveAnc_IsAancActive()) \
                                                                                    Panic()
#define kymeraAdaptiveAnc_IsSplitterInMicRefPathCreated() (kymeraAdaptiveAnc_GetChain(CHAIN_MIC_REF_PATH_SPLITTER) != NULL)
 
#define CONVERT_MSEC_TO_SEC(value) ((value)/1000)
 
#define IN_EAR  TRUE
#define OUT_OF_EAR !IN_EAR
#define ENABLE_ADAPTIVITY TRUE
#define DISABLE_ADAPTIVITY !ENABLE_ADAPTIVITY
 
#define NUM_STATUS_VAR              24
#define CUR_MODE_STATUS_OFFSET      0
#define FLAGS_STATUS_OFFSET          7
#define FF_GAIN_STATUS_OFFSET        8
#define FLAG_POS_QUIET_MODE         20
 
#define BIT_MASK(FLAG_POS)          (1 << FLAG_POS)
 
#define AANC_TUNNING_START_DELAY    (200U)
 
/*! Macro for creating messages */
#define MAKE_KYMERA_MESSAGE(TYPE) \
    TYPE##_T *message = PanicUnlessNew(TYPE##_T);
 
#define AANC_TUNING_SINK_USB        0
#define AANC_TUNING_SINK_UNUSED     1 /* Unused */
#define AANC_TUNING_SINK_INT_MIC    2 /* Internal Mic In */
#define AANC_TUNING_SINK_EXT_MIC    3 /* External Mic In */
 
#define AANC_TUNING_SOURCE_DAC      0
#define AANC_TUNING_SOURCE_UNUSED   1 /* Unused */
#define AANC_TUNING_SOURCE_INT_MIC  2 /* Forwards Int Mic */
#define AANC_TUNING_SOURCE_EXT_MIC  3 /* Forwards Ext Mic */
 
#ifdef DOWNLOAD_USB_AUDIO
#define EB_CAP_ID_USB_AUDIO_RX CAP_ID_DOWNLOAD_USB_AUDIO_RX
#define EB_CAP_ID_USB_AUDIO_TX CAP_ID_DOWNLOAD_USB_AUDIO_TX
#else
#define EB_CAP_ID_USB_AUDIO_RX CAP_ID_USB_AUDIO_RX
#define EB_CAP_ID_USB_AUDIO_TX CAP_ID_USB_AUDIO_TX
#endif
 
#ifdef __QCC517X__
/* By default AANC IIR filter sample rate set to 32kHz (in QCC517x devices) */
#define AANC_FILTER_SAMPLE_RATE (adaptive_anc_sample_rate_32khz)
#endif
/* AANC Capability ID*/
/* Hard coded to 0x409F to fix unity. Will be modified*/
#define CAP_ID_DOWNLOAD_AANC_TUNING 0x409F
 
static kymera_chain_handle_t adaptive_anc_chains[MAX_CHAIN] = {0};
 
static void kymeraAdaptiveAnc_UpdateAdaptivity(bool enable_adaptivity);
 
static kymera_chain_handle_t kymeraAdaptiveAnc_GetChain(uint8 index)
{
 
    return ((index < MAX_CHAIN) ? adaptive_anc_chains[index] : NULL);
}
 
static void kymeraAdaptiveAnc_SetChain(uint8 index, kymera_chain_handle_t chain)
{
 
    if(index < MAX_CHAIN)
        adaptive_anc_chains[index] = chain;
}
 
static Source kymeraAdaptiveAnc_GetOutput(uint8 index, chain_endpoint_role_t output_role)
{
 
    return ChainGetOutput(kymeraAdaptiveAnc_GetChain(index), output_role);
}
 
static Sink kymeraAdaptiveAnc_GetInput(uint8 index, chain_endpoint_role_t output_role)
{
 
    return ChainGetInput(kymeraAdaptiveAnc_GetChain(index), output_role);
}
 
static bool IsAancFbcActive;
static bool kymeraAdaptiveAnc_IsAancFbcActive(void)
{
 
	IsAancFbcActive = kymeraAdaptiveAnc_GetChain(CHAIN_FBC) != NULL;
	return IsAancFbcActive;
}
 
/* Mic interface callback functions */
static bool kymeraAdaptiveAnc_MicGetConnectionParameters(uint16 *mic_ids, Sink *mic_sinks, uint8 *num_of_mics, uint32 *sample_rate, Sink *aec_ref_sink);
static bool kymeraAdaptiveAnc_MicDisconnectIndication(const mic_change_info_t *info);
static void kymeraAdaptiveAnc_MicReconnectedIndication(void);
static mic_user_state_t kymeraAdaptiveAnc_GetUserState(void);
static bool kymeraAdaptiveAnc_GetAecRefUsage(void);
/* AANC support functions */
static void kymeraAdaptiveAnc_EnableConcurrency(bool transition);
static void kymeraAdaptiveAnc_CreateEchoCancellerChain(void);
static void kymeraAdaptiveAnc_ConnectConcurrency(void);
static void kymeraAdaptiveAnc_StartConcurrency(bool transition);
static void kymeraAdaptiveAnc_ConnectFbcChain(void);
static void kymeraAdaptiveAnc_ConnectSplitterFbcChain(void);
static void kymeraAdaptiveAnc_ActivateMicRefPathSplitterSecondOutput(void);
 
static void kymeraAdaptiveAnc_DisableConcurrency(bool transition);
static void kymeraAdaptiveAnc_StopConcurrency(void);
static void kymeraAdaptiveAnc_DisconnectConcurrency(void);
static void kymeraAdaptiveAnc_DestroyConcurrency(bool transition);
static void kymeraAdaptiveAnc_DeactivateMicRefPathSplitterSecondOutput(void);
static void kymeraAdaptiveAnc_DisconnectFbcOutputs(void);
static void kymeraAdaptiveAnc_DisconnectMicRefPathSplitterOutputs(void);
 
static void kymeraAdaptiveAnc_DisableStandalone(bool transition);
static void kymeraAdaptiveAnc_EnableStandalone(bool transition);
 
static void kymeraAdaptiveAnc_Stop(void);
static void kymeraAdaptiveAnc_Restart(void);
static void kymeraAdaptiveAnc_Disconnect(void);
static void kymeraAdaptiveAnc_Reconnect(void);
 
static void kymeraAdaptiveAnc_SetKymeraState(void);
static void kymeraAdaptiveAnc_ResetKymeraState(void);
 
/**************************************
 *** Kymera Mic interface callbacks ***
 **************************************/
static uint16 kymera_AdaptiveAncMics[MAX_AANC_MICS] =
{
 
    appConfigAncFeedForwardMic(),
    appConfigAncFeedBackMic()
};
 
static const mic_callbacks_t kymera_AdaptiveAncCallbacks =
{
 
    .MicGetConnectionParameters = kymeraAdaptiveAnc_MicGetConnectionParameters,
    .MicDisconnectIndication = kymeraAdaptiveAnc_MicDisconnectIndication,
    .MicReconnectedIndication = kymeraAdaptiveAnc_MicReconnectedIndication,
    .MicGetUserState = kymeraAdaptiveAnc_GetUserState,
    .MicGetAecRefUsage = kymeraAdaptiveAnc_GetAecRefUsage,
};
 
static const mic_registry_per_user_t kymera_AdaptiveAncRegistry =
{
 
    .user = mic_user_aanc,
    .callbacks = &kymera_AdaptiveAncCallbacks,
    .permanent.mandatory_mic_ids = &kymera_AdaptiveAncMics[0],
    .permanent.num_of_mandatory_mics = MAX_AANC_MICS,
};
 
/*! For a reconnection the mic parameters are sent to the mic interface.
 *  return TRUE to reconnect with the given parameters
 */
static bool kymeraAdaptiveAnc_MicGetConnectionParameters(uint16 *mic_ids, Sink *mic_sinks, uint8 *num_of_mics, uint32 *sample_rate, Sink *aec_ref_sink)
{
 
    *sample_rate = AANC_SAMPLE_RATE;
    *num_of_mics = MAX_AANC_MICS;
    mic_ids[0] = appConfigAncFeedForwardMic();
    mic_ids[1] = appConfigAncFeedBackMic();
 
    DEBUG_LOG("kymeraAdaptiveAnc_MicGetConnectionParameters");
 
    if (kymeraAdaptiveAnc_IsAancFbcActive())
    {
 
        DEBUG_LOG("AANC concurrency mic sinks");
        mic_sinks[0] = kymeraAdaptiveAnc_GetInput(CHAIN_FBC, EPR_AANC_FBC_FF_MIC_IN);
        mic_sinks[1] = kymeraAdaptiveAnc_GetInput(CHAIN_FBC, EPR_AANC_FBC_ERR_MIC_IN);
        aec_ref_sink[0] = kymeraAdaptiveAnc_GetInput(CHAIN_MIC_REF_PATH_SPLITTER, EPR_SPLT_MIC_REF_IN);
    }
    else
    {
 
        DEBUG_LOG("AANC standalone mic sinks");
        mic_sinks[0] = kymeraAdaptiveAnc_GetInput(CHAIN_AANC, EPR_AANC_FF_MIC_IN);
        mic_sinks[1] = kymeraAdaptiveAnc_GetInput(CHAIN_AANC, EPR_AANC_ERR_MIC_IN);
        aec_ref_sink[0] = NULL;
    }
 
    return TRUE;
}
 
/*! Before the microphones are disconnected, all users get informed with a DisconnectIndication.
 * return FALSE: accept disconnection
 * return TRUE: Try to reconnect the microphones. This will trigger a kymeraAdaptiveAnc_MicGetConnectionParameters
 */
static bool kymeraAdaptiveAnc_MicDisconnectIndication(const mic_change_info_t *info)
{
 
    DEBUG_LOG("kymeraAdaptiveAnc_MicDisconnectIndication user %d, event %d", info->user, info->event);
    /* Stop & disconnect Adaptive ANC audio graph - due to client disconnection request */
    kymeraAdaptiveAnc_Stop();
    kymeraAdaptiveAnc_Disconnect();
    return TRUE;
}
 
 
/*! This indication is sent if the microphones have been reconnected after a DisconnectIndication.
 * Also used in cases where ANC is enabled and SCO is started, then a kymeraAdaptiveAnc_MicDisconnectIndication
 * and a kymeraAdaptiveAnc_MicReconnectedIndication is called, which will configure the new mic sinks through
 * kymeraAdaptiveAnc_MicGetConnectionParameters callback from mic framework
 */
static void kymeraAdaptiveAnc_MicReconnectedIndication(void)
{
 
    DEBUG_LOG("kymeraAdaptiveAnc_MicReconnectedIndication");
    /* Reconnect & Restart Adaptive ANC audio graph - after new client added */
    kymeraAdaptiveAnc_Reconnect();
    kymeraAdaptiveAnc_Restart();
}
 
static mic_user_state_t kymeraAdaptiveAnc_GetUserState(void)
{
 
    return mic_user_state_interruptible;
}
 
static bool kymeraAdaptiveAnc_GetAecRefUsage(void)
{
 
    return IsAancFbcActive;
}
 
/***************************************
 *** Kymera Output Manager callbacks ***
 ***************************************/
/*! Notifies registered user that another user is about to connect to the output chain. */
static void kymera_AdaptiveAncOutputConnectingIndication(output_users_t connecting_user, output_connection_t connection_type)
{
 
    UNUSED(connection_type);
    UNUSED(connecting_user);
    DEBUG_LOG_INFO("kymera_AdaptiveAncOutputConnectingIndication connecting user: enum:output_users_t:%d",connecting_user);
 
    if(kymeraAdaptiveAnc_IsAancActive())
    {
 
        if(KymeraAdaptiveAnc_IsConcurrencyActive())
        {
 
            /* do nothing */
        }
        else
        {
 
            kymeraAdaptiveAnc_DisableStandalone(TRUE);
            kymeraAdaptiveAnc_EnableConcurrency(TRUE);
        }
    }
}
 
/*! Notifies registered user that a user has disconnected from the output chain */
static void kymera_AdaptiveAncOutputDisconnectedIndication(output_users_t disconnected_user, output_connection_t connection_type)
{
 
    UNUSED(connection_type);
    UNUSED(disconnected_user);
    DEBUG_LOG_INFO("kymera_AdaptiveAncOutputDisconnectingIndication disconnected user: enum:output_users_t:%d",disconnected_user);
    DEBUG_LOG_INFO("kymera_AdaptiveAncOutputDisconnectingIndication Kymera_OutputIsChainInUse():%d",Kymera_OutputIsChainInUse());
 
    if(!Kymera_OutputIsChainInUse())
    {
 
        if(kymeraAdaptiveAnc_IsAancActive())
        {
 
            if(KymeraAdaptiveAnc_IsConcurrencyActive())
            {
 
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值