8202 lines
281 KiB
C++
8202 lines
281 KiB
C++
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2019 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
//#include "mbed.h"
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#include "cmsis_os.h"
|
|
#include "app_bt_trace.h"
|
|
#include "tgt_hardware.h"
|
|
#include "hal_uart.h"
|
|
#include "hal_timer.h"
|
|
#include "audioflinger.h"
|
|
#include "lockcqueue.h"
|
|
#include "hal_cmu.h"
|
|
#include "hal_overlay.h"
|
|
#include "analog.h"
|
|
#include "avdtp_i.h"
|
|
#include "app_bt_stream.h"
|
|
#include "app_overlay.h"
|
|
#include "app_audio.h"
|
|
#include "app_utils.h"
|
|
#ifdef ANC_APP
|
|
#include "app_anc.h"
|
|
#endif
|
|
#include "anc_wnr.h"
|
|
#include "bluetooth.h"
|
|
#include "nvrecord.h"
|
|
#include "nvrecord_env.h"
|
|
#include "nvrecord_dev.h"
|
|
#include "resample_coef.h"
|
|
#include "hal_codec.h"
|
|
#include "hal_i2s.h"
|
|
#include "hal_bootmode.h"
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
#include "resources.h"
|
|
#include "app_media_player.h"
|
|
#endif
|
|
#ifdef __FACTORY_MODE_SUPPORT__
|
|
#include "app_factory_audio.h"
|
|
#endif
|
|
#ifdef TX_RX_PCM_MASK
|
|
#include "hal_chipid.h"
|
|
#endif
|
|
|
|
#ifdef __IAG_BLE_INCLUDE__
|
|
#include "app_ble_mode_switch.h"
|
|
#endif
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
#include "app_voicepath.h"
|
|
#endif
|
|
|
|
#if defined(__AI_VOICE__)||defined(BISTO_ENABLED)
|
|
#include "app_ai_voice.h"
|
|
#include "app_ai_if.h"
|
|
#endif
|
|
|
|
#ifdef AI_AEC_CP_ACCEL
|
|
#include "app_ai_algorithm.h"
|
|
#endif
|
|
|
|
#include "app_ring_merge.h"
|
|
#include "bt_drv.h"
|
|
#include "bt_xtal_sync.h"
|
|
#include "bt_drv_reg_op.h"
|
|
#include "besbt.h"
|
|
#include "hal_chipid.h"
|
|
#include "cqueue.h"
|
|
#include "btapp.h"
|
|
#include "app_hfp.h"
|
|
#include "app_bt.h"
|
|
#include "os_api.h"
|
|
#include "audio_process.h"
|
|
#include "app_a2dp.h"
|
|
#include "audio_dump.h"
|
|
#include "math.h"
|
|
|
|
#ifdef WL_DET
|
|
#include "app_mic_alg.h"
|
|
#endif
|
|
|
|
#if (A2DP_DECODER_VER == 2)
|
|
#include "a2dp_decoder.h"
|
|
#endif
|
|
#if defined(__AUDIO_SPECTRUM__)
|
|
#include "audio_spectrum.h"
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
#include "speech_utils.h"
|
|
#include "lis25ba.h"
|
|
#include "tdm_stream.h"
|
|
#endif
|
|
|
|
#if defined(ANC_NOISE_TRACKER)
|
|
#include "noise_tracker.h"
|
|
#include "noise_tracker_callback.h"
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
#include "app_ibrt_if.h"
|
|
#include "app_tws_ctrl_thread.h"
|
|
#include "app_tws_ibrt_audio_analysis.h"
|
|
#include "app_tws_ibrt_audio_sync.h"
|
|
#include "app_ibrt_a2dp.h"
|
|
#include "app_ibrt_rssi.h"
|
|
#undef MUSIC_DELAY_CONTROL
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_ADJ_MC)
|
|
#include "adj_mc.h"
|
|
#include "fftfilt2.h"
|
|
#endif
|
|
|
|
|
|
// NOTE: Modify parameters for your project.
|
|
// #define A2DP_STREAM_AUDIO_DUMP
|
|
|
|
#if defined(__SW_IIR_EQ_PROCESS__)
|
|
static uint8_t audio_eq_sw_iir_index = 0;
|
|
extern const IIR_CFG_T * const audio_eq_sw_iir_cfg_list[];
|
|
#endif
|
|
|
|
#if defined(__HW_FIR_EQ_PROCESS__)
|
|
static uint8_t audio_eq_hw_fir_index = 0;
|
|
extern const FIR_CFG_T * const audio_eq_hw_fir_cfg_list[];
|
|
#endif
|
|
|
|
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
|
|
static uint8_t audio_eq_hw_dac_iir_index = 0;
|
|
extern const IIR_CFG_T * const audio_eq_hw_dac_iir_cfg_list[];
|
|
#endif
|
|
|
|
#include "audio_prompt_sbc.h"
|
|
|
|
#if defined(__HW_IIR_EQ_PROCESS__)
|
|
static uint8_t audio_eq_hw_iir_index = 0;
|
|
extern const IIR_CFG_T * const audio_eq_hw_iir_cfg_list[];
|
|
#endif
|
|
|
|
#if defined(HW_DC_FILTER_WITH_IIR)
|
|
#include "hw_filter_codec_iir.h"
|
|
#include "hw_codec_iir_process.h"
|
|
|
|
hw_filter_codec_iir_cfg POSSIBLY_UNUSED adc_iir_cfg = {
|
|
.bypass = 0,
|
|
.iir_device = HW_CODEC_IIR_ADC,
|
|
#if 1
|
|
.iir_cfg = {
|
|
.iir_filtes_l = {
|
|
.iir_bypass_flag = 0,
|
|
.iir_counter = 2,
|
|
.iir_coef = {
|
|
{{0.994406, -1.988812, 0.994406}, {1.000000, -1.988781, 0.988843}}, // iir_designer('highpass', 0, 20, 0.7, 16000);
|
|
{{4.0, 0.0, 0.0}, {1.0, 0.0, 0.0}},
|
|
}
|
|
},
|
|
.iir_filtes_r = {
|
|
.iir_bypass_flag = 0,
|
|
.iir_counter = 2,
|
|
.iir_coef = {
|
|
{{0.994406, -1.988812, 0.994406}, {1.000000, -1.988781, 0.988843}},
|
|
{{4.0, 0.0, 0.0}, {1.0, 0.0, 0.0}},
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
.iir_cfg = {
|
|
.gain0 = 0,
|
|
.gain1 = 0,
|
|
.num = 1,
|
|
.param = {
|
|
{IIR_TYPE_HIGH_PASS, 0, 20.0, 0.7},
|
|
}
|
|
}
|
|
#endif
|
|
};
|
|
|
|
hw_filter_codec_iir_state *hw_filter_codec_iir_st;
|
|
#endif
|
|
|
|
#if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST3003)|| \
|
|
defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST1000) || \
|
|
defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST2001) \
|
|
|
|
#undef AUDIO_RESAMPLE_ANTI_DITHER
|
|
|
|
#else
|
|
#define AUDIO_RESAMPLE_ANTI_DITHER
|
|
#endif
|
|
|
|
#include "audio_cfg.h"
|
|
|
|
//#define SCO_DMA_SNAPSHOT_DEBUG
|
|
|
|
extern uint8_t bt_audio_get_eq_index(AUDIO_EQ_TYPE_T audio_eq_type,uint8_t anc_status);
|
|
extern uint32_t bt_audio_set_eq(AUDIO_EQ_TYPE_T audio_eq_type,uint8_t index);
|
|
extern uint8_t bt_audio_updata_eq_for_anc(uint8_t anc_status);
|
|
|
|
#include "app_bt_media_manager.h"
|
|
|
|
#include "string.h"
|
|
#include "hal_location.h"
|
|
|
|
#include "bt_drv_interface.h"
|
|
|
|
#include "audio_resample_ex.h"
|
|
|
|
#if defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2001)
|
|
#define BT_INIT_XTAL_SYNC_FCAP_RANGE (0x1FF)
|
|
#else
|
|
#define BT_INIT_XTAL_SYNC_FCAP_RANGE (0xFF)
|
|
#endif
|
|
#define BT_INIT_XTAL_SYNC_MIN (20)
|
|
#define BT_INIT_XTAL_SYNC_MAX (BT_INIT_XTAL_SYNC_FCAP_RANGE - BT_INIT_XTAL_SYNC_MIN)
|
|
|
|
#ifdef __THIRDPARTY
|
|
#include "app_thirdparty.h"
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
#include"anc_process.h"
|
|
|
|
#ifdef ANC_FB_MC_96KHZ
|
|
#define DELAY_SAMPLE_MC (29*2) // 2:ch
|
|
#define SAMPLERATE_RATIO_THRESHOLD (4) //384 = 96*4
|
|
#else
|
|
#define DELAY_SAMPLE_MC (31*2) // 2:ch
|
|
#define SAMPLERATE_RATIO_THRESHOLD (8) //384 = 48*8
|
|
#endif
|
|
|
|
static int32_t delay_buf_bt[DELAY_SAMPLE_MC];
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
static uint8_t anc_status_record = 0xff;
|
|
#endif
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
|
|
#ifdef PCM_FAST_MODE
|
|
#define MASTER_MOBILE_BTCLK_OFFSET (4)
|
|
#elif TX_RX_PCM_MASK
|
|
#define MASTER_MOBILE_BTCLK_OFFSET (8)
|
|
#else
|
|
#define MASTER_MOBILE_BTCLK_OFFSET (4)
|
|
#endif
|
|
#define MASTER_MOBILE_BTCNT_OFFSET (MASTER_MOBILE_BTCLK_OFFSET*625)
|
|
|
|
#if defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) || defined(CHIP_BEST2001)
|
|
#define MUTE_PATTERN (0x55)
|
|
#else
|
|
#define MUTE_PATTERN (0x00)
|
|
#endif
|
|
|
|
extern void app_tws_ibrt_audio_mobile_clkcnt_get(uint32_t btclk, uint16_t btcnt,
|
|
uint32_t *mobile_master_clk, uint16_t *mobile_master_cnt);
|
|
|
|
static uint8_t *playback_buf_codecpcm;
|
|
static uint32_t playback_size_codecpcm;
|
|
static uint8_t *capture_buf_codecpcm;
|
|
static uint32_t capture_size_codecpcm;
|
|
|
|
static uint8_t *playback_buf_btpcm;
|
|
static uint32_t playback_size_btpcm;
|
|
static uint8_t *capture_buf_btpcm;
|
|
static uint32_t capture_size_btpcm;
|
|
|
|
#ifdef TX_RX_PCM_MASK
|
|
static uint8_t *playback_buf_btpcm_copy=NULL;
|
|
static uint32_t playback_size_btpcm_copy=0;
|
|
static uint8_t *capture_buf_btpcm_copy=NULL;
|
|
static uint32_t capture_size_btpcm_copy=0;
|
|
#endif
|
|
|
|
volatile int sco_btpcm_mute_flag=0;
|
|
volatile int sco_disconnect_mute_flag=0;
|
|
|
|
static uint8_t *playback_buf_btpcm_cache=NULL;
|
|
|
|
static enum AUD_SAMPRATE_T playback_samplerate_codecpcm;
|
|
static int32_t mobile_master_clk_offset_init;
|
|
#endif
|
|
|
|
enum PLAYER_OPER_T
|
|
{
|
|
PLAYER_OPER_START,
|
|
PLAYER_OPER_STOP,
|
|
PLAYER_OPER_RESTART,
|
|
};
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
extern "C" void hal_codec_capture_enable(void);
|
|
extern "C" void hal_codec_capture_enable_delay(void);
|
|
|
|
static uint32_t codec_capture_cnt = 0;
|
|
static uint32_t codec_playback_cnt = 0;
|
|
#endif
|
|
|
|
#if (AUDIO_OUTPUT_VOLUME_DEFAULT < 1) || (AUDIO_OUTPUT_VOLUME_DEFAULT > 17)
|
|
#error "AUDIO_OUTPUT_VOLUME_DEFAULT out of range"
|
|
#endif
|
|
int8_t stream_local_volume = (AUDIO_OUTPUT_VOLUME_DEFAULT);
|
|
#ifdef AUDIO_LINEIN
|
|
int8_t stream_linein_volume = (AUDIO_OUTPUT_VOLUME_DEFAULT);
|
|
#endif
|
|
|
|
struct btdevice_volume *btdevice_volume_p;
|
|
struct btdevice_volume current_btdevice_volume;
|
|
|
|
#ifdef __BT_ANC__
|
|
uint8_t bt_sco_samplerate_ratio = 0;
|
|
static uint8_t *bt_anc_sco_dec_buf;
|
|
extern void us_fir_init(void);
|
|
extern uint32_t voicebtpcm_pcm_resample (short* src_samp_buf, uint32_t src_smpl_cnt, short* dst_samp_buf);
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
static enum AUD_BITS_T sample_size_play_bt;
|
|
static enum AUD_SAMPRATE_T sample_rate_play_bt;
|
|
static uint32_t data_size_play_bt;
|
|
|
|
static uint8_t *playback_buf_bt;
|
|
static uint32_t playback_size_bt;
|
|
static int32_t playback_samplerate_ratio_bt;
|
|
|
|
static uint8_t *playback_buf_mc;
|
|
static uint32_t playback_size_mc;
|
|
static enum AUD_CHANNEL_NUM_T playback_ch_num_bt;
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
uint32_t adj_mc_capture_sample_rate;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
static enum AUD_BITS_T lowdelay_sample_size_play_bt;
|
|
static enum AUD_SAMPRATE_T lowdelay_sample_rate_play_bt;
|
|
static uint32_t lowdelay_data_size_play_bt;
|
|
static enum AUD_CHANNEL_NUM_T lowdelay_playback_ch_num_bt;
|
|
#endif
|
|
|
|
extern uint8_t current_a2dp_non_type;
|
|
|
|
|
|
extern void bt_media_clear_media_type(uint16_t media_type,enum BT_DEVICE_ID_T device_id);
|
|
|
|
extern "C" uint8_t is_sbc_mode (void);
|
|
uint8_t bt_sbc_mode;
|
|
extern "C" uint8_t __attribute__((section(".fast_text_sram"))) is_sbc_mode(void)
|
|
{
|
|
return bt_sbc_mode;
|
|
}
|
|
|
|
extern "C" uint8_t is_sco_mode (void);
|
|
|
|
uint8_t bt_sco_mode;
|
|
extern "C" uint8_t __attribute__((section(".fast_text_sram"))) is_sco_mode(void)
|
|
{
|
|
return bt_sco_mode;
|
|
}
|
|
|
|
#define APP_BT_STREAM_TRIGGER_TIMEROUT (2000)
|
|
|
|
#define TRIGGER_CHECKER_A2DP_PLAYERBLACK (1<<0)
|
|
#define TRIGGER_CHECKER_A2DP_DONE (TRIGGER_CHECKER_A2DP_PLAYERBLACK)
|
|
|
|
#define TRIGGER_CHECKER_HFP_BTPCM_PLAYERBLACK (1<<1)
|
|
#define TRIGGER_CHECKER_HFP_BTPCM_CAPTURE (1<<2)
|
|
#define TRIGGER_CHECKER_HFP_AUDPCM_PLAYERBLACK (1<<3)
|
|
#define TRIGGER_CHECKER_HFP_AUDPCM_CAPTURE (1<<4)
|
|
#define TRIGGER_CHECKER_HFP_DONE (TRIGGER_CHECKER_HFP_BTPCM_PLAYERBLACK|TRIGGER_CHECKER_HFP_BTPCM_CAPTURE|TRIGGER_CHECKER_HFP_AUDPCM_PLAYERBLACK|TRIGGER_CHECKER_HFP_AUDPCM_CAPTURE)
|
|
|
|
|
|
static bool app_bt_stream_trigger_enable = 0;
|
|
static uint32_t app_bt_stream_trigger_checker = 0;
|
|
static void app_bt_stream_trigger_timeout_cb(void const *n);
|
|
osTimerDef(APP_BT_STREAM_TRIGGER_TIMEOUT, app_bt_stream_trigger_timeout_cb);
|
|
osTimerId app_bt_stream_trigger_timeout_id = NULL;
|
|
|
|
static void app_bt_stream_trigger_timeout_cb(void const *n)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][CHK]timeout_cb\n");
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][CHK]-->A2DP_SBC\n");
|
|
#if defined(IBRT)
|
|
app_ibrt_if_force_audio_retrigger();
|
|
#else
|
|
app_audio_sendrequest_param(APP_BT_STREAM_A2DP_SBC, (uint8_t)APP_BT_SETTING_RESTART, 0, 0);
|
|
#endif
|
|
}else if (app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM)){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][CHK]-->HFP_PCM\n");
|
|
app_audio_sendrequest(APP_BT_STREAM_HFP_PCM, (uint8_t)APP_BT_SETTING_RESTART, 0);
|
|
}
|
|
|
|
}
|
|
|
|
static int app_bt_stream_trigger_checker_init(void)
|
|
{
|
|
if (app_bt_stream_trigger_timeout_id == NULL){
|
|
app_bt_stream_trigger_enable = false;
|
|
app_bt_stream_trigger_checker = 0;
|
|
app_bt_stream_trigger_timeout_id = osTimerCreate(osTimer(APP_BT_STREAM_TRIGGER_TIMEOUT), osTimerOnce, NULL);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int app_bt_stream_trigger_checker_start(void)
|
|
{
|
|
app_bt_stream_trigger_checker = 0;
|
|
app_bt_stream_trigger_enable = true;
|
|
osTimerStart(app_bt_stream_trigger_timeout_id, APP_BT_STREAM_TRIGGER_TIMEROUT);
|
|
return 0;
|
|
}
|
|
|
|
static int app_bt_stream_trigger_checker_stop(void)
|
|
{
|
|
app_bt_stream_trigger_enable = false;
|
|
app_bt_stream_trigger_checker = 0;
|
|
osTimerStop(app_bt_stream_trigger_timeout_id);
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_trigger_checker_handler(uint32_t trigger_checker)
|
|
{
|
|
bool trigger_ok = false;
|
|
|
|
if (app_bt_stream_trigger_enable){
|
|
app_bt_stream_trigger_checker |= trigger_checker;
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
if (app_bt_stream_trigger_checker == TRIGGER_CHECKER_A2DP_DONE){
|
|
trigger_ok = true;
|
|
}
|
|
}else if (app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM)){
|
|
if (app_bt_stream_trigger_checker == TRIGGER_CHECKER_HFP_DONE){
|
|
trigger_ok = true;
|
|
}
|
|
}
|
|
if (trigger_ok){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][CHK] ok\n");
|
|
app_bt_stream_trigger_checker_stop();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef A2DP_LHDC_ON
|
|
extern struct BT_DEVICE_T app_bt_device;
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define LHDC_AUDIO_96K_BUFF_SIZE (256*2*4*8)
|
|
//#define LHDC_AUDIO_96K_16BITS_BUFF_SIZE (256*2*2*8)
|
|
|
|
#define LHDC_AUDIO_BUFF_SIZE (256*2*4*4)
|
|
//#define LHDC_AUDIO_16BITS_BUFF_SIZE (256*2*2*4)
|
|
#define LHDC_LLC_AUDIO_BUFF_SIZE (256*2*2*2)
|
|
#else
|
|
#define LHDC_AUDIO_BUFF_SIZE (512*2*4)
|
|
//#define LHDC_AUDIO_16BITS_BUFF_SIZE (512*2*2)
|
|
#endif
|
|
#endif
|
|
uint16_t gStreamplayer = APP_BT_STREAM_INVALID;
|
|
|
|
uint32_t a2dp_audio_more_data(uint8_t codec_type, uint8_t *buf, uint32_t len);
|
|
int a2dp_audio_init(void);
|
|
int a2dp_audio_deinit(void);
|
|
enum AUD_SAMPRATE_T a2dp_sample_rate = AUD_SAMPRATE_48000;
|
|
uint32_t a2dp_data_buf_size;
|
|
#ifdef RB_CODEC
|
|
extern int app_rbplay_audio_onoff(bool onoff, uint16_t aud_id);
|
|
#endif
|
|
|
|
#if defined(APP_LINEIN_A2DP_SOURCE)||defined(APP_I2S_A2DP_SOURCE)
|
|
int app_a2dp_source_linein_on(bool on);
|
|
#endif
|
|
#if defined(APP_I2S_A2DP_SOURCE)
|
|
#include "app_status_ind.h"
|
|
#include "app_a2dp_source.h"
|
|
//player channel should <= capture channel number
|
|
//player must be 2 channel
|
|
#define LINEIN_PLAYER_CHANNEL (2)
|
|
#ifdef __AUDIO_INPUT_MONO_MODE__
|
|
#define LINEIN_CAPTURE_CHANNEL (1)
|
|
#else
|
|
#define LINEIN_CAPTURE_CHANNEL (2)
|
|
#endif
|
|
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
#define LINEIN_PLAYER_BUFFER_SIZE (1024*LINEIN_PLAYER_CHANNEL)
|
|
#define LINEIN_CAPTURE_BUFFER_SIZE (LINEIN_PLAYER_BUFFER_SIZE/2)
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
#define LINEIN_PLAYER_BUFFER_SIZE (1024*LINEIN_PLAYER_CHANNEL)
|
|
//#define LINEIN_CAPTURE_BUFFER_SIZE (LINEIN_PLAYER_BUFFER_SIZE)
|
|
#define LINEIN_CAPTURE_BUFFER_SIZE (1024*10)
|
|
#endif
|
|
|
|
static int16_t *app_linein_play_cache = NULL;
|
|
|
|
int8_t app_linein_buffer_is_empty(void)
|
|
{
|
|
if (app_audio_pcmbuff_length())
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
uint32_t app_linein_pcm_come(uint8_t * pcm_buf, uint32_t len)
|
|
{
|
|
//DUMP16("%d ", pcm_buf, 10);
|
|
DUMP8("0x%02x ", pcm_buf, 10);
|
|
TRACE_AUD_STREAM_I("app_linein_pcm_come");
|
|
app_audio_pcmbuff_put(pcm_buf, len);
|
|
|
|
return len;
|
|
}
|
|
|
|
uint32_t app_linein_need_pcm_data(uint8_t* pcm_buf, uint32_t len)
|
|
{
|
|
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
app_audio_pcmbuff_get((uint8_t *)app_linein_play_cache, len/2);
|
|
//app_play_audio_lineinmode_more_data((uint8_t *)app_linein_play_cache,len/2);
|
|
app_bt_stream_copy_track_one_to_two_16bits((int16_t *)pcm_buf, app_linein_play_cache, len/2/2);
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
app_audio_pcmbuff_get((uint8_t *)pcm_buf, len);
|
|
//app_play_audio_lineinmode_more_data((uint8_t *)pcm_buf, len);
|
|
#endif
|
|
|
|
#if defined(__AUDIO_OUTPUT_MONO_MODE__)
|
|
merge_stereo_to_mono_16bits((int16_t *)buf, (int16_t *)pcm_buf, len/2);
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
bt_audio_updata_eq_for_anc(app_anc_work_status());
|
|
#endif
|
|
|
|
audio_process_run(pcm_buf, len);
|
|
|
|
return len;
|
|
}
|
|
extern "C" void pmu_linein_onoff(unsigned char en);
|
|
extern "C" int hal_analogif_reg_read(unsigned short reg, unsigned short *val);
|
|
int app_a2dp_source_I2S_onoff(bool onoff)
|
|
{
|
|
static bool isRun = false;
|
|
uint8_t *linein_audio_cap_buff = 0;
|
|
uint8_t *linein_audio_play_buff = 0;
|
|
uint8_t *linein_audio_loop_buf = NULL;
|
|
struct AF_STREAM_CONFIG_T stream_cfg;
|
|
|
|
TRACE_AUD_STREAM_I("app_a2dp_source_I2S_onoff work:%d op:%d", isRun, onoff);
|
|
|
|
if (isRun == onoff)
|
|
return 0;
|
|
|
|
if (onoff)
|
|
{
|
|
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_104M);
|
|
app_overlay_select(APP_OVERLAY_A2DP);
|
|
app_audio_mempool_init();
|
|
app_audio_mempool_get_buff(&linein_audio_cap_buff, LINEIN_CAPTURE_BUFFER_SIZE);
|
|
// app_audio_mempool_get_buff(&linein_audio_play_buff, LINEIN_PLAYER_BUFFER_SIZE);
|
|
// app_audio_mempool_get_buff(&linein_audio_loop_buf, LINEIN_PLAYER_BUFFER_SIZE<<2);
|
|
// app_audio_pcmbuff_init(linein_audio_loop_buf, LINEIN_PLAYER_BUFFER_SIZE<<2);
|
|
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
app_audio_mempool_get_buff((uint8_t **)&app_linein_play_cache, LINEIN_PLAYER_BUFFER_SIZE/2/2);
|
|
//app_play_audio_lineinmode_init(LINEIN_CAPTURE_CHANNEL, LINEIN_PLAYER_BUFFER_SIZE/2/2);
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
//app_play_audio_lineinmode_init(LINEIN_CAPTURE_CHANNEL, LINEIN_PLAYER_BUFFER_SIZE/2);
|
|
#endif
|
|
|
|
sRet = memset_s(&stream_cfg, sizeof(stream_cfg), 0, sizeof(stream_cfg));
|
|
if (sRet){
|
|
TRACE_AUD_STREAM_W("func-s line:%d sRet:%d %s ", __LINE__, sRet, __func__);
|
|
}
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)LINEIN_PLAYER_CHANNEL;
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_44100;
|
|
|
|
#if 0
|
|
#if FPGA==0
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
#else
|
|
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
|
#endif
|
|
|
|
stream_cfg.vol = 10;//stream_linein_volume;
|
|
//TRACE_AUD_STREAM_I("vol = %d",stream_linein_volume);
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
stream_cfg.handler = app_linein_need_pcm_data;
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(linein_audio_play_buff);
|
|
stream_cfg.data_size = LINEIN_PLAYER_BUFFER_SIZE;
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
#if 1
|
|
stream_cfg.device = AUD_STREAM_USE_I2S0_SLAVE;
|
|
// stream_cfg.io_path = AUD_INPUT_PATH_LINEIN;
|
|
// stream_cfg.handler = app_linein_pcm_come;
|
|
stream_cfg.handler = a2dp_source_linein_more_pcm_data;
|
|
// stream_cfg.handler = app_linein_pcm_come;
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(linein_audio_cap_buff);
|
|
stream_cfg.data_size = LINEIN_CAPTURE_BUFFER_SIZE;//2k
|
|
|
|
// pmu_linein_onoff(1);
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
|
|
audio_process_open(stream_cfg.sample_rate, stream_cfg.bits, stream_cfg.channel_num, NULL, 0);
|
|
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
//app_status_indication_set(APP_STATUS_INDICATION_LINEIN_ON);
|
|
}
|
|
else
|
|
{
|
|
// clear buffer data
|
|
a2dp_source.pcm_queue.write=0;
|
|
a2dp_source.pcm_queue.len=0;
|
|
a2dp_source.pcm_queue.read=0;
|
|
// pmu_linein_onoff(0);
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
//app_status_indication_set(APP_STATUS_INDICATION_LINEIN_OFF);
|
|
app_overlay_unloadall();
|
|
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
|
}
|
|
|
|
isRun = onoff;
|
|
TRACE_AUD_STREAM_I("%s end!\n", __func__);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
enum AUD_SAMPRATE_T bt_parse_sbc_sample_rate(uint8_t sbc_samp_rate)
|
|
{
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
sbc_samp_rate = sbc_samp_rate & A2D_STREAM_SAMP_FREQ_MSK;
|
|
|
|
switch (sbc_samp_rate)
|
|
{
|
|
case A2D_SBC_IE_SAMP_FREQ_16:
|
|
// sample_rate = AUD_SAMPRATE_16000;
|
|
// break;
|
|
case A2D_SBC_IE_SAMP_FREQ_32:
|
|
// sample_rate = AUD_SAMPRATE_32000;
|
|
// break;
|
|
case A2D_SBC_IE_SAMP_FREQ_48:
|
|
sample_rate = AUD_SAMPRATE_48000;
|
|
break;
|
|
case A2D_SBC_IE_SAMP_FREQ_44:
|
|
sample_rate = AUD_SAMPRATE_44100;
|
|
break;
|
|
#if defined(A2DP_LHDC_ON) || defined(A2DP_LDAC_ON) || defined(A2DP_SCALABLE_ON)
|
|
case A2D_SBC_IE_SAMP_FREQ_96:
|
|
sample_rate = AUD_SAMPRATE_96000;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
ASSERT(0, "[%s] 0x%x is invalid", __func__, sbc_samp_rate);
|
|
break;
|
|
}
|
|
return sample_rate;
|
|
}
|
|
|
|
void bt_store_sbc_sample_rate(enum AUD_SAMPRATE_T sample_rate)
|
|
{
|
|
a2dp_sample_rate = sample_rate;
|
|
}
|
|
|
|
enum AUD_SAMPRATE_T bt_get_sbc_sample_rate(void)
|
|
{
|
|
return a2dp_sample_rate;
|
|
}
|
|
|
|
enum AUD_SAMPRATE_T bt_parse_store_sbc_sample_rate(uint8_t sbc_samp_rate)
|
|
{
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
|
|
sample_rate = bt_parse_sbc_sample_rate(sbc_samp_rate);
|
|
bt_store_sbc_sample_rate(sample_rate);
|
|
|
|
return sample_rate;
|
|
}
|
|
|
|
int bt_sbc_player_setup(uint8_t freq)
|
|
{
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
static uint8_t sbc_samp_rate = 0xff;
|
|
uint32_t ret;
|
|
|
|
if (sbc_samp_rate == freq)
|
|
return 0;
|
|
|
|
switch (freq)
|
|
{
|
|
case A2D_SBC_IE_SAMP_FREQ_16:
|
|
case A2D_SBC_IE_SAMP_FREQ_32:
|
|
case A2D_SBC_IE_SAMP_FREQ_48:
|
|
a2dp_sample_rate = AUD_SAMPRATE_48000;
|
|
break;
|
|
#if defined(A2DP_LHDC_ON) || defined(A2DP_LDAC_ON) || defined(A2DP_SCALABLE_ON)
|
|
case A2D_SBC_IE_SAMP_FREQ_96:
|
|
a2dp_sample_rate = AUD_SAMPRATE_96000;
|
|
break;
|
|
#if defined(A2DP_LDAC_ON)
|
|
case A2D_SBC_IE_SAMP_FREQ_88:
|
|
a2dp_sample_rate = AUD_SAMPRATE_88200;
|
|
break;
|
|
#endif
|
|
#endif
|
|
case A2D_SBC_IE_SAMP_FREQ_44:
|
|
a2dp_sample_rate = AUD_SAMPRATE_44100;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
TRACE_AUD_STREAM_I("%s:Sample rate :%d", __func__, a2dp_sample_rate);
|
|
|
|
ret = af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, true);
|
|
if (ret == 0) {
|
|
stream_cfg->sample_rate = a2dp_sample_rate;
|
|
af_stream_setup(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, stream_cfg);
|
|
}
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
ret = af_stream_get_cfg(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg, true);
|
|
if (ret == 0) {
|
|
stream_cfg->sample_rate = a2dp_sample_rate;
|
|
sample_rate_play_bt=stream_cfg->sample_rate;
|
|
af_stream_setup(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, stream_cfg);
|
|
anc_mc_run_setup(hal_codec_anc_convert_rate(sample_rate_play_bt));
|
|
}
|
|
#endif
|
|
|
|
sbc_samp_rate = freq;
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
if (audio_prompt_is_playing_ongoing())
|
|
{
|
|
audio_prompt_forcefully_stop();
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void merge_stereo_to_mono_16bits(int16_t *src_buf, int16_t *dst_buf, uint32_t src_len)
|
|
{
|
|
uint32_t i = 0;
|
|
for (i = 0; i < src_len; i+=2)
|
|
{
|
|
dst_buf[i] = (src_buf[i]>>1) + (src_buf[i+1]>>1);
|
|
dst_buf[i+1] = dst_buf[i];
|
|
}
|
|
}
|
|
|
|
void merge_stereo_to_mono_24bits(int32_t *src_buf, int32_t *dst_buf, uint32_t src_len)
|
|
{
|
|
uint32_t i = 0;
|
|
for (i = 0; i < src_len; i+=2)
|
|
{
|
|
dst_buf[i] = (src_buf[i]>>1) + (src_buf[i+1]>>1);
|
|
dst_buf[i+1] = dst_buf[i];
|
|
}
|
|
}
|
|
|
|
static char _player_type_str[168];
|
|
static char *_catstr(char *dst, const char *src) {
|
|
while(*dst) dst++;
|
|
while((*dst++ = *src++));
|
|
return --dst;
|
|
}
|
|
const char *player2str(uint16_t player_type) {
|
|
const char *s = NULL;
|
|
char _cat = 0, first = 1, *d = NULL;
|
|
_player_type_str[0] = '\0';
|
|
d = _player_type_str;
|
|
d = _catstr(d, "[");
|
|
if (player_type != 0) {
|
|
for (int i = 15 ; i >= 0; i--) {
|
|
_cat = 1;
|
|
//TRACE_AUD_STREAM_I("i=%d,player_type=0x%d,player_type&(1<<i)=0x%x", i, player_type, player_type&(1<<i));
|
|
switch(player_type&(1<<i)) {
|
|
case 0: _cat = 0; break;
|
|
case APP_BT_STREAM_HFP_PCM: s = "HFP_PCM"; break;
|
|
case APP_BT_STREAM_HFP_CVSD: s = "HFP_CVSD"; break;
|
|
case APP_BT_STREAM_HFP_VENDOR: s = "HFP_VENDOR"; break;
|
|
case APP_BT_STREAM_A2DP_SBC: s = "A2DP_SBC"; break;
|
|
case APP_BT_STREAM_A2DP_AAC: s = "A2DP_AAC"; break;
|
|
case APP_BT_STREAM_A2DP_VENDOR: s = "A2DP_VENDOR"; break;
|
|
#ifdef __FACTORY_MODE_SUPPORT__
|
|
case APP_FACTORYMODE_AUDIO_LOOP: s = "AUDIO_LOOP"; break;
|
|
#endif
|
|
case APP_PLAY_BACK_AUDIO: s = "BACK_AUDIO"; break;
|
|
#ifdef RB_CODEC
|
|
case APP_BT_STREAM_RBCODEC: s = "RBCODEC"; break;
|
|
#endif
|
|
#ifdef AUDIO_LINEIN
|
|
case APP_PLAY_LINEIN_AUDIO: s = "LINEIN_AUDIO"; break;
|
|
#endif
|
|
#if defined(APP_LINEIN_A2DP_SOURCE)||defined(__APP_A2DP_SOURCE__)||(APP_I2S_A2DP_SOURCE)
|
|
case APP_A2DP_SOURCE_LINEIN_AUDIO: s = "SRC_LINEIN_AUDIO"; break;
|
|
case APP_A2DP_SOURCE_I2S_AUDIO: s = "I2S_AUDIO"; break;
|
|
#endif
|
|
#ifdef VOICE_DATAPATH
|
|
case APP_BT_STREAM_VOICEPATH: s = "VOICEPATH"; break;
|
|
#endif
|
|
#ifdef __AI_VOICE__
|
|
case APP_BT_STREAM_AI_VOICE: s = "AI_VOICE"; break;
|
|
#endif
|
|
#ifdef __THIRDPARTY
|
|
case APP_BT_STREAM_THIRDPARTY_VOICE: s = "THIRDPARTY"; break;
|
|
#endif
|
|
default: s = "UNKNOWN"; break;
|
|
}
|
|
if (_cat) {
|
|
if (!first)
|
|
d = _catstr(d, "|");
|
|
//TRACE_AUD_STREAM_I("d=%s,s=%s", d, s);
|
|
d = _catstr(d, s);
|
|
first = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
_catstr(d, "]");
|
|
|
|
return _player_type_str;
|
|
}
|
|
|
|
|
|
#ifdef __HEAR_THRU_PEAK_DET__
|
|
#include "peak_detector.h"
|
|
// Depend on codec_dac_vol
|
|
const float pkd_vol_multiple[18] = {0.281838, 0.000010, 0.005623, 0.007943, 0.011220, 0.015849, 0.022387, 0.031623, 0.044668, 0.063096, 0.089125, 0.125893, 0.177828, 0.251189, 0.354813, 0.501187, 0.707946, 1.000000};
|
|
int app_bt_stream_local_volume_get(void);
|
|
#endif
|
|
//extern void a2dp_get_curStream_remDev(btif_remote_device_t ** p_remDev);
|
|
uint16_t a2dp_Get_curr_a2dp_conhdl(void);
|
|
|
|
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
static struct APP_RESAMPLE_T *force48k_resample;
|
|
static int app_force48k_resample_iter(uint8_t *buf, uint32_t len);
|
|
struct APP_RESAMPLE_T *app_force48k_resample_any_open(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step);
|
|
int app_playback_resample_run(struct APP_RESAMPLE_T *resamp, uint8_t *buf, uint32_t len);
|
|
#endif
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
|
|
#define BT_USPERCLK (625)
|
|
#define BT_MUTIUSPERSECOND (1000000/BT_USPERCLK)
|
|
|
|
#define CALIB_DEVIATION_MS (2)
|
|
#define CALIB_FACTOR_MAX_THRESHOLD (0.0001f)
|
|
#define CALIB_BT_CLOCK_FACTOR_STEP (0.0000005f)
|
|
|
|
#define CALIB_FACTOR_DELAY (0.001f)
|
|
|
|
//bt time
|
|
static int32_t bt_old_clock_us=0;
|
|
static uint32_t bt_old_clock_mutius=0;
|
|
static int32_t bt_old_offset_us=0;
|
|
|
|
static int32_t bt_clock_us=0;
|
|
static uint32_t bt_clock_total_mutius=0;
|
|
static int32_t bt_total_offset_us=0;
|
|
|
|
static int32_t bt_clock_ms=0;
|
|
|
|
//local time
|
|
static uint32_t local_total_samples=0;
|
|
static uint32_t local_total_frames=0;
|
|
|
|
//static uint32_t local_clock_us=0;
|
|
static int32_t local_clock_ms=0;
|
|
|
|
//bt and local time
|
|
static uint32_t bt_local_clock_s=0;
|
|
|
|
//calib time
|
|
static int32_t calib_total_delay=0;
|
|
static int32_t calib_flag=0;
|
|
|
|
//calib factor
|
|
static float calib_factor_offset=0.0f;
|
|
static int32_t calib_factor_flag=0;
|
|
static volatile int calib_reset=1;
|
|
#endif
|
|
|
|
bool process_delay(int32_t delay_ms)
|
|
{
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
if (delay_ms == 0)return 0;
|
|
|
|
TRACE_AUD_STREAM_I("delay_ms:%d", delay_ms);
|
|
|
|
if(calib_flag==0)
|
|
{
|
|
calib_total_delay=calib_total_delay+delay_ms;
|
|
calib_flag=1;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
void a2dp_clock_calib_process(uint32_t len)
|
|
{
|
|
// btif_remote_device_t * p_a2dp_remDev=NULL;
|
|
uint32_t smplcnt = 0;
|
|
int32_t btoffset = 0;
|
|
|
|
uint32_t btclk = 0;
|
|
uint32_t btcnt = 0;
|
|
uint32_t btofs = 0;
|
|
btclk = *((volatile uint32_t*)0xd02201fc);
|
|
btcnt = *((volatile uint32_t*)0xd02201f8);
|
|
btcnt=0;
|
|
|
|
// TRACE_AUD_STREAM_I("bt_sbc_player_more_data btclk:%08x,btcnt:%08x\n", btclk, btcnt);
|
|
|
|
|
|
// a2dp_get_curStream_remDev(&p_a2dp_remDev);
|
|
if(a2dp_Get_curr_a2dp_conhdl() >=0x80 && a2dp_Get_curr_a2dp_conhdl()<=0x82)
|
|
{
|
|
btofs = btdrv_rf_bitoffset_get( a2dp_Get_curr_a2dp_conhdl() -0x80);
|
|
|
|
if(calib_reset==1)
|
|
{
|
|
calib_reset=0;
|
|
|
|
bt_clock_total_mutius=0;
|
|
|
|
bt_old_clock_us=btcnt;
|
|
bt_old_clock_mutius=btclk;
|
|
|
|
bt_total_offset_us=0;
|
|
|
|
|
|
local_total_samples=0;
|
|
local_total_frames=0;
|
|
local_clock_ms = 0;
|
|
|
|
bt_local_clock_s=0;
|
|
bt_clock_us = 0;
|
|
bt_clock_ms = 0;
|
|
|
|
bt_old_offset_us=btofs;
|
|
|
|
calib_factor_offset=0.0f;
|
|
calib_factor_flag=0;
|
|
calib_total_delay=0;
|
|
calib_flag=0;
|
|
}
|
|
else
|
|
{
|
|
btoffset=btofs-bt_old_offset_us;
|
|
|
|
if(btoffset<-BT_USPERCLK/3)
|
|
{
|
|
btoffset=btoffset+BT_USPERCLK;
|
|
}
|
|
else if(btoffset>BT_USPERCLK/3)
|
|
{
|
|
btoffset=btoffset-BT_USPERCLK;
|
|
}
|
|
|
|
bt_total_offset_us=bt_total_offset_us+btoffset;
|
|
bt_old_offset_us=btofs;
|
|
|
|
local_total_frames++;
|
|
if(lowdelay_sample_size_play_bt==AUD_BITS_16)
|
|
{
|
|
smplcnt=len/(2*lowdelay_playback_ch_num_bt);
|
|
}
|
|
else
|
|
{
|
|
smplcnt=len/(4*lowdelay_playback_ch_num_bt);
|
|
}
|
|
|
|
local_total_samples=local_total_samples+smplcnt;
|
|
|
|
bt_clock_us=btcnt-bt_old_clock_us-bt_total_offset_us;
|
|
|
|
btoffset=btclk-bt_old_clock_mutius;
|
|
if(btoffset<0)
|
|
{
|
|
btoffset=0;
|
|
}
|
|
bt_clock_total_mutius=bt_clock_total_mutius+btoffset;
|
|
|
|
bt_old_clock_us=btcnt;
|
|
bt_old_clock_mutius=btclk;
|
|
|
|
if((bt_clock_total_mutius>BT_MUTIUSPERSECOND)&&(local_total_samples>lowdelay_sample_rate_play_bt))
|
|
{
|
|
bt_local_clock_s++;
|
|
bt_clock_total_mutius=bt_clock_total_mutius-BT_MUTIUSPERSECOND;
|
|
local_total_samples=local_total_samples-lowdelay_sample_rate_play_bt;
|
|
}
|
|
|
|
bt_clock_ms=(bt_clock_total_mutius*BT_USPERCLK/1000)+bt_clock_us/625;
|
|
local_clock_ms=(local_total_samples*1000)/lowdelay_sample_rate_play_bt;
|
|
|
|
local_clock_ms=local_clock_ms+calib_total_delay;
|
|
|
|
//TRACE_AUD_STREAM_I("A2DP bt_clock_ms:%8d,local_clock_ms:%8d,bt_total_offset_us:%8d\n",bt_clock_ms, local_clock_ms,bt_total_offset_us);
|
|
|
|
if(bt_clock_ms>(local_clock_ms+CALIB_DEVIATION_MS))
|
|
{
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE)
|
|
app_resample_tune(a2dp_resample, CALIB_FACTOR_DELAY);
|
|
#else
|
|
af_codec_tune(AUD_STREAM_PLAYBACK, CALIB_FACTOR_DELAY);
|
|
#endif
|
|
calib_factor_flag=1;
|
|
//TRACE_AUD_STREAM_I("*************1***************");
|
|
}
|
|
else if(bt_clock_ms<(local_clock_ms-CALIB_DEVIATION_MS))
|
|
{
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE)
|
|
app_resample_tune(a2dp_resample, -CALIB_FACTOR_DELAY);
|
|
#else
|
|
af_codec_tune(AUD_STREAM_PLAYBACK, -CALIB_FACTOR_DELAY);
|
|
#endif
|
|
calib_factor_flag=-1;
|
|
//TRACE_AUD_STREAM_I("*************-1***************");
|
|
}
|
|
else
|
|
{
|
|
if((calib_factor_flag==1||calib_factor_flag==-1)&&(bt_clock_ms==local_clock_ms))
|
|
{
|
|
if(calib_factor_offset<CALIB_FACTOR_MAX_THRESHOLD&&calib_flag==0)
|
|
{
|
|
if(calib_factor_flag==1)
|
|
{
|
|
calib_factor_offset=calib_factor_offset+CALIB_BT_CLOCK_FACTOR_STEP;
|
|
}
|
|
else
|
|
{
|
|
calib_factor_offset=calib_factor_offset-CALIB_BT_CLOCK_FACTOR_STEP;
|
|
}
|
|
|
|
}
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE)
|
|
app_resample_tune(a2dp_resample, calib_factor_offset);
|
|
#else
|
|
af_codec_tune(AUD_STREAM_PLAYBACK, calib_factor_offset);
|
|
#endif
|
|
calib_factor_flag=0;
|
|
calib_flag=0;
|
|
//TRACE_AUD_STREAM_I("*************0***************");
|
|
}
|
|
}
|
|
// TRACE_AUD_STREAM_I("factoroffset:%d\n",(int32_t)((factoroffset)*(float)10000000.0f));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
bool app_if_need_fix_target_rxbit(void)
|
|
{
|
|
return (!bt_drv_is_enhanced_ibrt_rom());
|
|
}
|
|
|
|
static uint8_t isBtPlaybackTriggered = false;
|
|
|
|
bool bt_is_playback_triggered(void)
|
|
{
|
|
return isBtPlaybackTriggered;
|
|
}
|
|
|
|
static void bt_set_playback_triggered(bool isEnable)
|
|
{
|
|
isBtPlaybackTriggered = isEnable;
|
|
}
|
|
|
|
FRAM_TEXT_LOC uint32_t bt_sbc_player_more_data(uint8_t *buf, uint32_t len)
|
|
{
|
|
app_bt_stream_trigger_checker_handler(TRIGGER_CHECKER_A2DP_PLAYERBLACK);
|
|
#ifdef A2DP_STREAM_AUDIO_DUMP
|
|
audio_dump_clear_up();
|
|
audio_dump_add_channel_data_from_multi_channels(0, buf, len / sizeof(int) / 2, 2, 0);
|
|
audio_dump_run();
|
|
#endif
|
|
|
|
bt_set_playback_triggered(true);
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
a2dp_clock_calib_process(len);
|
|
#endif
|
|
|
|
#if defined(IBRT) && defined(RSSI_GATHERING_ENABLED)
|
|
app_ibrt_ui_rssi_process();
|
|
#endif
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
//if (AI_SPEC_GSOUND == ai_manager_get_current_spec())
|
|
{
|
|
if (app_voicepath_get_stream_pending_state(VOICEPATH_STREAMING))
|
|
{
|
|
#ifdef __DUAL_MIC_RECORDING__
|
|
app_ibrt_voice_capture_trigger_init();
|
|
#endif
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
#ifdef MIX_MIC_DURING_MUSIC
|
|
app_voicepath_enable_hw_sidetone(0, HW_SIDE_TONE_MAX_ATTENUATION_COEF);
|
|
#endif
|
|
app_voicepath_set_stream_state(VOICEPATH_STREAMING, true);
|
|
app_voicepath_set_pending_started_stream(VOICEPATH_STREAMING, false);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef BT_XTAL_SYNC
|
|
#ifdef BT_XTAL_SYNC_NEW_METHOD
|
|
if(a2dp_Get_curr_a2dp_conhdl() >=0x80 && a2dp_Get_curr_a2dp_conhdl()<=0x82)
|
|
{
|
|
uint32_t bitoffset = btdrv_rf_bitoffset_get( a2dp_Get_curr_a2dp_conhdl() -0x80);
|
|
if(app_if_need_fix_target_rxbit() == false)
|
|
{
|
|
if(bitoffset<XTAL_OFFSET)
|
|
bitoffset = XTAL_OFFSET;
|
|
else if(bitoffset>SLOT_SIZE-XTAL_OFFSET)
|
|
bitoffset = SLOT_SIZE-XTAL_OFFSET;
|
|
}
|
|
#ifdef BT_XTAL_SYNC_SLOW
|
|
bt_xtal_sync_new(bitoffset,app_if_need_fix_target_rxbit(),BT_XTAL_SYNC_MODE_WITH_MOBILE);
|
|
#else
|
|
bt_xtal_sync_new_new(bitoffset,app_if_need_fix_target_rxbit(),BT_XTAL_SYNC_MODE_WITH_MOBILE);
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
bt_xtal_sync(BT_XTAL_SYNC_MODE_MUSIC);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef FPGA
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
uint32_t overlay_id = 0;
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC)
|
|
{
|
|
overlay_id = APP_OVERLAY_A2DP_AAC;
|
|
}
|
|
else if(codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
#if defined(A2DP_LHDC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC)
|
|
{
|
|
overlay_id = APP_OVERLAY_A2DP_LHDC;
|
|
}
|
|
#endif
|
|
|
|
#if defined(A2DP_LDAC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC)
|
|
{
|
|
overlay_id = APP_OVERLAY_A2DP_LDAC;
|
|
}
|
|
#endif
|
|
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE)
|
|
{
|
|
overlay_id = APP_OVERLAY_A2DP_SCALABLE;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
overlay_id = APP_OVERLAY_A2DP;
|
|
}
|
|
|
|
memset(buf, 0, len);
|
|
|
|
if(app_get_current_overlay() != overlay_id)
|
|
{
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
app_playback_resample_run(force48k_resample, buf, len);
|
|
#else
|
|
#if (A2DP_DECODER_VER == 2)
|
|
a2dp_audio_playback_handler(buf, len);
|
|
#else
|
|
#ifndef FPGA
|
|
a2dp_audio_more_data(overlay_id, buf, len);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __AUDIO_SPECTRUM__
|
|
audio_spectrum_run(buf, len);
|
|
#endif
|
|
|
|
|
|
#ifdef __KWS_AUDIO_PROCESS__
|
|
short* pdata = (short*)buf;
|
|
short pdata_mono = 0;
|
|
for(unsigned int i = 0;i<len/4;i++)
|
|
{
|
|
pdata_mono = pdata[2*i]/2+pdata[2*i+1]/2;
|
|
pdata[2*i] = pdata_mono;
|
|
pdata[2*i+1] = pdata_mono;
|
|
}
|
|
#endif
|
|
|
|
#ifdef __AUDIO_OUTPUT_MONO_MODE__
|
|
#ifdef A2DP_EQ_24BIT
|
|
merge_stereo_to_mono_24bits((int32_t *)buf, (int32_t *)buf, len/sizeof(int32_t));
|
|
#else
|
|
merge_stereo_to_mono_16bits((int16_t *)buf, (int16_t *)buf, len/sizeof(int16_t));
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __HEAR_THRU_PEAK_DET__
|
|
#ifdef ANC_APP
|
|
if(app_anc_work_status())
|
|
#endif
|
|
{
|
|
int vol_level = 0;
|
|
vol_level = app_bt_stream_local_volume_get();
|
|
peak_detector_run(buf, len, pkd_vol_multiple[vol_level]);
|
|
}
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
bt_audio_updata_eq_for_anc(app_anc_work_status());
|
|
#endif
|
|
|
|
audio_process_run(buf, len);
|
|
|
|
|
|
|
|
|
|
#if defined(IBRT) && !defined(FPGA)
|
|
app_tws_ibrt_audio_analysis_audiohandler_tick();
|
|
#endif
|
|
|
|
osapi_notify_evm();
|
|
|
|
return len;
|
|
}
|
|
|
|
FRAM_TEXT_LOC void bt_sbc_player_playback_post_handler(uint8_t *buf, uint32_t len, void *cfg)
|
|
{
|
|
POSSIBLY_UNUSED struct AF_STREAM_CONFIG_T *config = (struct AF_STREAM_CONFIG_T *)cfg;
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
#ifdef TWS_PROMPT_SYNC
|
|
tws_playback_ticks_check_for_mix_prompt();
|
|
#endif
|
|
if (audio_prompt_is_playing_ongoing())
|
|
{
|
|
audio_prompt_processing_handler(len, buf);
|
|
}
|
|
#else
|
|
app_ring_merge_more_data(buf, len);
|
|
#endif
|
|
}
|
|
|
|
#ifdef __THIRDPARTY
|
|
bool start_by_sbc = false;
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
static int32_t mid_p_8_old_l=0;
|
|
static int32_t mid_p_8_old_r=0;
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
#define ADJ_MC_STREAM_ID AUD_STREAM_ID_1
|
|
|
|
#define ADJ_MC_SAMPLE_BITS (16)
|
|
#define ADJ_MC_SAMPLE_BYTES (ADJ_MC_SAMPLE_BITS / 8)
|
|
#define ADJ_MC_CHANNEL_NUM (2)
|
|
#define ADJ_MC_FRAME_LEN (256)
|
|
#define ADJ_MC_BUF_SIZE (ADJ_MC_FRAME_LEN * ADJ_MC_CHANNEL_NUM * ADJ_MC_SAMPLE_BYTES * 2)//pingpong
|
|
static uint8_t POSSIBLY_UNUSED adj_mc_buf[ADJ_MC_BUF_SIZE];
|
|
|
|
static uint32_t audio_adj_mc_data_playback_a2dp(uint8_t *buf, uint32_t mc_len_bytes)
|
|
{
|
|
uint32_t begin_time;
|
|
//uint32_t end_time;
|
|
begin_time = hal_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[A2DP][MUSIC_CANCEL] begin_time: %d",begin_time);
|
|
|
|
float left_gain;
|
|
float right_gain;
|
|
int playback_len_bytes,mc_len_bytes_run;
|
|
int i,j,k;
|
|
int delay_sample;
|
|
|
|
hal_codec_get_dac_gain(&left_gain,&right_gain);
|
|
|
|
//TRACE_AUD_STREAM_I("[A2DP][MUSIC_CANCEL]playback_samplerate_ratio: %d",playback_samplerate_ratio);
|
|
|
|
// TRACE_AUD_STREAM_I("[A2DP][MUSIC_CANCEL]left_gain: %d",(int)(left_gain*(1<<12)));
|
|
// TRACE_AUD_STREAM_I("[A2DP][MUSIC_CANCEL]right_gain: %d",(int)(right_gain*(1<<12)));
|
|
|
|
playback_len_bytes=mc_len_bytes/playback_samplerate_ratio_bt;
|
|
|
|
mc_len_bytes_run=mc_len_bytes/SAMPLERATE_RATIO_THRESHOLD;
|
|
|
|
if (sample_size_play_bt == AUD_BITS_16)
|
|
{
|
|
int16_t *sour_p=(int16_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int16_t *mid_p=(int16_t *)(buf);
|
|
int16_t *mid_p_8=(int16_t *)(buf+mc_len_bytes-mc_len_bytes_run);
|
|
int16_t *dest_p=(int16_t *)buf;
|
|
|
|
if(buf == playback_buf_mc)
|
|
{
|
|
sour_p=(int16_t *)playback_buf_bt;
|
|
}
|
|
|
|
delay_sample=DELAY_SAMPLE_MC/2;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/2-delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/2;i=i+1)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=SAMPLERATE_RATIO_THRESHOLD)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+(SAMPLERATE_RATIO_THRESHOLD/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+1)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_adj_mc_run_mono((uint8_t *)mid_p_8,mc_len_bytes_run,AUD_BITS_16);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_run)/2;i=i+1)
|
|
{
|
|
float delta_l=(mid_p_8[i]-mid_p_8_old_l)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
for(k=1;k<=SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8_old_l+(int32_t)(delta_l*k);
|
|
}
|
|
mid_p_8_old_l=mid_p_8[i];
|
|
}
|
|
|
|
|
|
}
|
|
else if (sample_size_play_bt == AUD_BITS_24)
|
|
{
|
|
int32_t *sour_p=(int32_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int32_t *mid_p=(int32_t *)(buf);
|
|
int32_t *mid_p_8=(int32_t *)(buf+mc_len_bytes-mc_len_bytes_run);
|
|
int32_t *dest_p=(int32_t *)buf;
|
|
|
|
if(buf == (playback_buf_mc))
|
|
{
|
|
sour_p=(int32_t *)playback_buf_bt;
|
|
}
|
|
|
|
delay_sample=DELAY_SAMPLE_MC/2;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/4-delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/4;i=i+1)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=SAMPLERATE_RATIO_THRESHOLD)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+(SAMPLERATE_RATIO_THRESHOLD/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+1)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_adj_mc_run_mono((uint8_t *)mid_p_8,mc_len_bytes_run,AUD_BITS_24);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_run)/4;i=i+1)
|
|
{
|
|
float delta_l=(mid_p_8[i]-mid_p_8_old_l)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
for(k=1;k<=SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8_old_l+(int32_t)(delta_l*k);
|
|
}
|
|
mid_p_8_old_l=mid_p_8[i];
|
|
}
|
|
}
|
|
|
|
// end_time = hal_sys_timer_get();
|
|
|
|
// TRACE_AUD_STREAM_I("[A2DP][MUSIC_CANCEL] run time: %d", end_time-begin_time);
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
static uint32_t audio_mc_data_playback_a2dp(uint8_t *buf, uint32_t mc_len_bytes)
|
|
{
|
|
// uint32_t begin_time;
|
|
// uint32_t end_time;
|
|
// begin_time = hal_sys_timer_get();
|
|
// TRACE_AUD_STREAM_I("music cancel: %d",begin_time);
|
|
|
|
float left_gain;
|
|
float right_gain;
|
|
int playback_len_bytes,mc_len_bytes_run;
|
|
int i,j,k;
|
|
int delay_sample;
|
|
|
|
hal_codec_get_dac_gain(&left_gain,&right_gain);
|
|
|
|
//TRACE_AUD_STREAM_I("playback_samplerate_ratio: %d",playback_samplerate_ratio);
|
|
|
|
// TRACE_AUD_STREAM_I("left_gain: %d",(int)(left_gain*(1<<12)));
|
|
// TRACE_AUD_STREAM_I("right_gain: %d",(int)(right_gain*(1<<12)));
|
|
|
|
playback_len_bytes=mc_len_bytes/playback_samplerate_ratio_bt;
|
|
|
|
mc_len_bytes_run=mc_len_bytes/SAMPLERATE_RATIO_THRESHOLD;
|
|
|
|
if (sample_size_play_bt == AUD_BITS_16)
|
|
{
|
|
int16_t *sour_p=(int16_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int16_t *mid_p=(int16_t *)(buf);
|
|
int16_t *mid_p_8=(int16_t *)(buf+mc_len_bytes-mc_len_bytes_run);
|
|
int16_t *dest_p=(int16_t *)buf;
|
|
|
|
if(buf == playback_buf_mc)
|
|
{
|
|
sour_p=(int16_t *)playback_buf_bt;
|
|
}
|
|
|
|
delay_sample=DELAY_SAMPLE_MC;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
mid_p[j++]=delay_buf_bt[i+1];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/2-delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
mid_p[j++]=sour_p[i+1];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/2;i=i+2)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
delay_buf_bt[j++]=sour_p[i+1];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=SAMPLERATE_RATIO_THRESHOLD)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+2*(SAMPLERATE_RATIO_THRESHOLD/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+2)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_stereo((uint8_t *)mid_p_8,mc_len_bytes_run,left_gain,right_gain,AUD_BITS_16);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_run)/2;i=i+2)
|
|
{
|
|
float delta_l=(mid_p_8[i]-mid_p_8_old_l)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
float delta_r=(mid_p_8[i+1]-mid_p_8_old_r)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
for(k=1;k<=SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8_old_l+(int32_t)(delta_l*k);
|
|
dest_p[j++]=mid_p_8_old_r+(int32_t)(delta_r*k);
|
|
}
|
|
mid_p_8_old_l=mid_p_8[i];
|
|
mid_p_8_old_r=mid_p_8[i+1];
|
|
}
|
|
|
|
|
|
}
|
|
else if (sample_size_play_bt == AUD_BITS_24)
|
|
{
|
|
int32_t *sour_p=(int32_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int32_t *mid_p=(int32_t *)(buf);
|
|
int32_t *mid_p_8=(int32_t *)(buf+mc_len_bytes-mc_len_bytes_run);
|
|
int32_t *dest_p=(int32_t *)buf;
|
|
|
|
if(buf == (playback_buf_mc))
|
|
{
|
|
sour_p=(int32_t *)playback_buf_bt;
|
|
}
|
|
|
|
delay_sample=DELAY_SAMPLE_MC;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
mid_p[j++]=delay_buf_bt[i+1];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/4-delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
mid_p[j++]=sour_p[i+1];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/4;i=i+2)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
delay_buf_bt[j++]=sour_p[i+1];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=SAMPLERATE_RATIO_THRESHOLD)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+2*(SAMPLERATE_RATIO_THRESHOLD/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+2)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_stereo((uint8_t *)mid_p_8,mc_len_bytes_run,left_gain,right_gain,AUD_BITS_24);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_run)/4;i=i+2)
|
|
{
|
|
float delta_l=(mid_p_8[i]-mid_p_8_old_l)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
float delta_r=(mid_p_8[i+1]-mid_p_8_old_r)/(float)SAMPLERATE_RATIO_THRESHOLD;
|
|
for(k=1;k<=SAMPLERATE_RATIO_THRESHOLD;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8_old_l+(int32_t)(delta_l*k);
|
|
dest_p[j++]=mid_p_8_old_r+(int32_t)(delta_r*k);
|
|
}
|
|
mid_p_8_old_l=mid_p_8[i];
|
|
mid_p_8_old_r=mid_p_8[i+1];
|
|
}
|
|
}
|
|
|
|
// end_time = hal_sys_timer_get();
|
|
|
|
// TRACE_AUD_STREAM_I("%s:run time: %d", __FUNCTION__, end_time-begin_time);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
static uint8_t g_current_eq_index = 0xff;
|
|
static bool isMeridianEQON = false;
|
|
|
|
bool app_is_meridian_on()
|
|
{
|
|
return isMeridianEQON;
|
|
}
|
|
|
|
uint8_t app_audio_get_eq()
|
|
{
|
|
return g_current_eq_index;
|
|
}
|
|
|
|
bool app_meridian_eq(bool onoff)
|
|
{
|
|
isMeridianEQON = onoff;
|
|
return onoff;
|
|
}
|
|
|
|
int app_audio_set_eq(uint8_t index)
|
|
{
|
|
#ifdef __SW_IIR_EQ_PROCESS__
|
|
if (index >=EQ_SW_IIR_LIST_NUM)
|
|
return -1;
|
|
#endif
|
|
#ifdef __HW_FIR_EQ_PROCESS__
|
|
if (index >=EQ_HW_FIR_LIST_NUM)
|
|
return -1;
|
|
#endif
|
|
#ifdef __HW_DAC_IIR_EQ_PROCESS__
|
|
if (index >=EQ_HW_DAC_IIR_LIST_NUM)
|
|
return -1;
|
|
#endif
|
|
#ifdef __HW_IIR_EQ_PROCESS__
|
|
if (index >=EQ_HW_IIR_LIST_NUM)
|
|
return -1;
|
|
#endif
|
|
g_current_eq_index = index;
|
|
return index;
|
|
}
|
|
|
|
void bt_audio_updata_eq(uint8_t index)
|
|
{
|
|
TRACE_AUD_STREAM_I("[EQ] update idx = %d", index);
|
|
#if defined(__SW_IIR_EQ_PROCESS__) || defined(__HW_FIR_EQ_PROCESS__)|| defined(__HW_DAC_IIR_EQ_PROCESS__)|| defined(__HW_IIR_EQ_PROCESS__)
|
|
AUDIO_EQ_TYPE_T audio_eq_type;
|
|
#ifdef __SW_IIR_EQ_PROCESS__
|
|
audio_eq_type = AUDIO_EQ_TYPE_SW_IIR;
|
|
#endif
|
|
|
|
#ifdef __HW_FIR_EQ_PROCESS__
|
|
audio_eq_type = AUDIO_EQ_TYPE_HW_FIR;
|
|
#endif
|
|
|
|
#ifdef __HW_DAC_IIR_EQ_PROCESS__
|
|
audio_eq_type = AUDIO_EQ_TYPE_HW_DAC_IIR;
|
|
#endif
|
|
|
|
#ifdef __HW_IIR_EQ_PROCESS__
|
|
audio_eq_type = AUDIO_EQ_TYPE_HW_IIR;
|
|
#endif
|
|
bt_audio_set_eq(audio_eq_type,index);
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef ANC_APP
|
|
uint8_t bt_audio_updata_eq_for_anc(uint8_t anc_status)
|
|
{
|
|
anc_status = app_anc_work_status();
|
|
if(anc_status_record != anc_status)
|
|
{
|
|
anc_status_record = anc_status;
|
|
TRACE_AUD_STREAM_I("[EQ] update anc_status = %d", anc_status);
|
|
#ifdef __SW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_SW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_SW_IIR,anc_status));
|
|
#endif
|
|
|
|
#ifdef __HW_FIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_FIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_FIR,anc_status));
|
|
#endif
|
|
|
|
#ifdef __HW_DAC_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_DAC_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_DAC_IIR,anc_status));
|
|
#endif
|
|
|
|
#ifdef __HW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_IIR,anc_status));
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
uint8_t bt_audio_get_eq_index(AUDIO_EQ_TYPE_T audio_eq_type,uint8_t anc_status)
|
|
{
|
|
uint8_t index_eq=0;
|
|
|
|
#if defined(__SW_IIR_EQ_PROCESS__) || defined(__HW_FIR_EQ_PROCESS__)|| defined(__HW_DAC_IIR_EQ_PROCESS__)|| defined(__HW_IIR_EQ_PROCESS__)
|
|
switch (audio_eq_type)
|
|
{
|
|
#if defined(__SW_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_SW_IIR:
|
|
{
|
|
if(anc_status)
|
|
{
|
|
index_eq=audio_eq_sw_iir_index+1;
|
|
}
|
|
else
|
|
{
|
|
index_eq=audio_eq_sw_iir_index;
|
|
}
|
|
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_FIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_FIR:
|
|
{
|
|
if(a2dp_sample_rate == AUD_SAMPRATE_44100) {
|
|
index_eq = 0;
|
|
} else if(a2dp_sample_rate == AUD_SAMPRATE_48000) {
|
|
index_eq = 1;
|
|
} else if(a2dp_sample_rate == AUD_SAMPRATE_96000) {
|
|
index_eq = 2;
|
|
} else {
|
|
ASSERT(0, "[%s] sample_rate_recv(%d) is not supported", __func__, a2dp_sample_rate);
|
|
}
|
|
audio_eq_hw_fir_index=index_eq;
|
|
|
|
if(anc_status)
|
|
{
|
|
index_eq=index_eq+3;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_DAC_IIR:
|
|
{
|
|
if(anc_status)
|
|
{
|
|
index_eq=audio_eq_hw_dac_iir_index+1;
|
|
}
|
|
else
|
|
{
|
|
index_eq=audio_eq_hw_dac_iir_index;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_IIR:
|
|
{
|
|
if(anc_status)
|
|
{
|
|
index_eq=audio_eq_hw_iir_index+1;
|
|
}
|
|
else
|
|
{
|
|
index_eq=audio_eq_hw_iir_index;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
{
|
|
ASSERT(false,"[%s]Error eq type!",__func__);
|
|
}
|
|
}
|
|
#endif
|
|
return index_eq;
|
|
}
|
|
|
|
|
|
uint32_t bt_audio_set_eq(AUDIO_EQ_TYPE_T audio_eq_type, uint8_t index)
|
|
{
|
|
const FIR_CFG_T *fir_cfg=NULL;
|
|
const IIR_CFG_T *iir_cfg=NULL;
|
|
|
|
TRACE_AUD_STREAM_I("[EQ] set type=%d,index=%d", audio_eq_type,index);
|
|
|
|
#if defined(__SW_IIR_EQ_PROCESS__) || defined(__HW_FIR_EQ_PROCESS__)|| defined(__HW_DAC_IIR_EQ_PROCESS__)|| defined(__HW_IIR_EQ_PROCESS__)
|
|
switch (audio_eq_type)
|
|
{
|
|
#if defined(__SW_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_SW_IIR:
|
|
{
|
|
if(index >= EQ_SW_IIR_LIST_NUM)
|
|
{
|
|
TRACE_AUD_STREAM_W("[EQ] SET index %u > EQ_SW_IIR_LIST_NUM", index);
|
|
return 1;
|
|
}
|
|
|
|
iir_cfg=audio_eq_sw_iir_cfg_list[index];
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_FIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_FIR:
|
|
{
|
|
if(index >= EQ_HW_FIR_LIST_NUM)
|
|
{
|
|
TRACE_AUD_STREAM_W("[EQ] SET index %u > EQ_HW_FIR_LIST_NUM", index);
|
|
return 1;
|
|
}
|
|
|
|
fir_cfg=audio_eq_hw_fir_cfg_list[index];
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_DAC_IIR:
|
|
{
|
|
if(index >= EQ_HW_DAC_IIR_LIST_NUM)
|
|
{
|
|
TRACE_AUD_STREAM_W("[EQ] SET index %u > EQ_HW_DAC_IIR_LIST_NUM", index);
|
|
return 1;
|
|
}
|
|
|
|
iir_cfg=audio_eq_hw_dac_iir_cfg_list[index];
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if defined(__HW_IIR_EQ_PROCESS__)
|
|
case AUDIO_EQ_TYPE_HW_IIR:
|
|
{
|
|
if(index >= EQ_HW_IIR_LIST_NUM)
|
|
{
|
|
TRACE_AUD_STREAM_W("[EQ] SET index %u > EQ_HW_IIR_LIST_NUM", index);
|
|
return 1;
|
|
}
|
|
|
|
iir_cfg=audio_eq_hw_iir_cfg_list[index];
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
{
|
|
ASSERT(false,"[%s]Error eq type!",__func__);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef AUDIO_SECTION_ENABLE
|
|
const IIR_CFG_T *iir_cfg_from_audio_section = (const IIR_CFG_T *)load_audio_cfg_from_audio_section(AUDIO_PROCESS_TYPE_IIR_EQ);
|
|
if (iir_cfg_from_audio_section)
|
|
{
|
|
iir_cfg = iir_cfg_from_audio_section;
|
|
}
|
|
#endif
|
|
|
|
return audio_eq_set_cfg(fir_cfg,iir_cfg,audio_eq_type);
|
|
}
|
|
|
|
#define A2DP_PLAYER_PLAYBACK_WATER_LINE ((uint32_t)(3.f * a2dp_audio_latency_factor_get() + 0.5f))
|
|
#define A2DP_PLAYER_PLAYBACK_WATER_LINE_UPPER (25)
|
|
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
dma_buffer_delay_us
|
|
scalable delay = 864/sample*1000*n ms
|
|
scalable delay = 864/44100*1000*13 = 117ms
|
|
scalable delay = 864/96000*1000*6 = 118ms
|
|
waterline delay = 864/sample*1000*n ms
|
|
waterline delay = 864/44100*1000*3 = 58ms
|
|
waterline delay = 864/96000*1000*3 = 27ms
|
|
audio_delay = scalable delay + waterline delay
|
|
*********************************/
|
|
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_MTU (13)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_BASE (9000)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_US (A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_BASE*A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_MTU)
|
|
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_MTU (6)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_BASE (19500)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_US (A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_BASE*A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_MTU)
|
|
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
dma_buffer_delay_us
|
|
aac delay = 1024/sample*1000*n ms
|
|
aac delay = 1024/44100*1000*5 = 116ms
|
|
waterline delay = 1024/sample*1000*n ms
|
|
waterline delay = 1024/44100*1000*3 = 69ms
|
|
audio_delay = aac delay + waterline delay
|
|
*********************************/
|
|
#ifndef A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU (3)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU (6)
|
|
#endif
|
|
#endif
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_AAC_BASE (23000)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_AAC_US (A2DP_PLAYER_PLAYBACK_DELAY_AAC_BASE*A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU)
|
|
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
sbc delay = 128/sample*n ms
|
|
sbc delay = 128/44100*45 = 130ms
|
|
sbc_delay = sbc delay(23219us)
|
|
waterline delay = 128/sample*SBC_FRAME_MTU*n ms
|
|
waterline delay = 128/44100*5*3 = 43ms
|
|
audio_delay = aac delay + waterline delay
|
|
*********************************/
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SBC_FRAME_MTU (5)
|
|
#ifndef A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU (35)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU (50)
|
|
#endif
|
|
#endif
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SBC_BASE (2800)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_SBC_US (A2DP_PLAYER_PLAYBACK_DELAY_SBC_BASE*A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU)
|
|
|
|
#if defined(A2DP_LHDC_ON)
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
lhdc delay = 512/sample*1000*n ms
|
|
lhdc delay = *28 = 149ms
|
|
audio_delay = lhdc delay
|
|
|
|
lhdc_v2 delay = 512/96000*1000*38 = 202ms
|
|
lhdc_v3 delay = 256/96000*1000*58 = 154ms
|
|
audio_delay = lhdc_v3 delay
|
|
*********************************/
|
|
#if defined(IBRT)
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU (68)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU (38)
|
|
#endif
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU (28)
|
|
#endif
|
|
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_BASE (2666)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_BASE (5333)
|
|
#endif
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_US (A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_BASE)
|
|
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
lhdc delay = 512/sample*1000*n ms
|
|
lhdc_v2 delay = 512/48000*1000*14 = 149ms
|
|
lhdc_v3 delay = 256/48000*1000*28 = 149ms
|
|
audio_delay = lhdc delay
|
|
*********************************/
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU (38)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU (14)
|
|
#endif
|
|
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_BASE (5333)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_BASE (10666)
|
|
#endif
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_US (A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_BASE)
|
|
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
lhdc delay = 512/sample*1000*n ms
|
|
lhdc_v2 delay = 512/48000*1000*9 = 96ms
|
|
lhdc_v3 delay = 256/48000*1000*19 = 101ms
|
|
audio_delay = lhdc delay
|
|
*********************************/
|
|
#if defined(IBRT)
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU (15)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU (9)
|
|
#endif
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU (6)
|
|
#endif
|
|
|
|
#if defined(A2DP_LHDC_V3)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_BASE (5333)
|
|
#else
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_BASE (10666)
|
|
#endif
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_US (A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_BASE)
|
|
#endif
|
|
|
|
#if defined(A2DP_LDAC_ON)
|
|
/********************************
|
|
AUD_BITS_16
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
AUD_BITS_24
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
|
|
ldac delay = 256/sample*1000*n ms
|
|
ldac delay = 256/96000*1000*56 = 149ms
|
|
audio_delay = ldac delay
|
|
*********************************/
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LDAC_FRAME_MTU (5)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU (60)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LDAC_BASE (2667)
|
|
#define A2DP_PLAYER_PLAYBACK_DELAY_LDAC_US (A2DP_PLAYER_PLAYBACK_DELAY_LDAC_BASE*A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU)
|
|
#endif
|
|
|
|
enum BT_STREAM_TRIGGER_STATUS_T {
|
|
BT_STREAM_TRIGGER_STATUS_NULL = 0,
|
|
BT_STREAM_TRIGGER_STATUS_INIT,
|
|
BT_STREAM_TRIGGER_STATUS_WAIT,
|
|
BT_STREAM_TRIGGER_STATUS_OK,
|
|
};
|
|
|
|
static uint32_t tg_acl_trigger_time = 0;
|
|
static uint32_t tg_acl_trigger_start_time = 0;
|
|
static uint32_t tg_acl_trigger_init_time = 0;
|
|
static enum BT_STREAM_TRIGGER_STATUS_T bt_stream_trigger_status = BT_STREAM_TRIGGER_STATUS_NULL;
|
|
|
|
void app_bt_stream_playback_irq_notification(enum AUD_STREAM_ID_T id, enum AUD_STREAM_T stream);
|
|
|
|
inline void app_bt_stream_trigger_stauts_set(enum BT_STREAM_TRIGGER_STATUS_T stauts)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG] stauts_set %d->%d", bt_stream_trigger_status,stauts);
|
|
bt_stream_trigger_status = stauts;
|
|
}
|
|
|
|
inline enum BT_STREAM_TRIGGER_STATUS_T app_bt_stream_trigger_stauts_get(void)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG] stauts_get:%d", bt_stream_trigger_status);
|
|
return bt_stream_trigger_status;
|
|
}
|
|
|
|
uint32_t app_bt_stream_get_dma_buffer_delay_us(void)
|
|
{
|
|
uint32_t dma_buffer_delay_us = 0;
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
if (!af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, false)){
|
|
if (stream_cfg->bits <= AUD_BITS_16){
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/2*1000000LL/stream_cfg->sample_rate;
|
|
}else{
|
|
dma_buffer_delay_us = stream_cfg->data_size/stream_cfg->channel_num/4*1000000LL/stream_cfg->sample_rate;
|
|
}
|
|
}
|
|
return dma_buffer_delay_us;
|
|
}
|
|
|
|
uint32_t app_bt_stream_get_dma_buffer_samples(void)
|
|
{
|
|
uint32_t dma_buffer_delay_samples = 0;
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
if (!af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, false)){
|
|
if (stream_cfg->bits <= AUD_BITS_16){
|
|
dma_buffer_delay_samples = stream_cfg->data_size/stream_cfg->channel_num/2;
|
|
}else{
|
|
dma_buffer_delay_samples = stream_cfg->data_size/stream_cfg->channel_num/4;
|
|
}
|
|
}
|
|
return dma_buffer_delay_samples;
|
|
}
|
|
|
|
#if defined(IBRT)
|
|
typedef enum {
|
|
APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_IDLE,
|
|
APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_ONPROCESS,
|
|
APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_SYNCOK,
|
|
}APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_TYPE;
|
|
|
|
#define APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_CNT_LIMIT (100)
|
|
void app_bt_stream_ibrt_set_trigger_time(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger);
|
|
void app_bt_stream_ibrt_auto_synchronize_initsync_start(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger);
|
|
static APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T app_bt_stream_ibrt_auto_synchronize_trigger;
|
|
static uint32_t app_bt_stream_ibrt_auto_synchronize_cnt = 0;
|
|
int app_bt_stream_ibrt_audio_mismatch_stopaudio(void);
|
|
void app_bt_stream_ibrt_auto_synchronize_hungup(void);
|
|
void app_bt_stream_ibrt_auto_synchronize_stop(void);
|
|
static APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_TYPE ibrt_auto_synchronize_status = APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_IDLE;
|
|
|
|
int app_bt_stream_ibrt_auto_synchronize_status_set(APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_TYPE status)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC] status:%d", status);
|
|
ibrt_auto_synchronize_status = status;
|
|
return 0;
|
|
}
|
|
|
|
APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_TYPE app_bt_stream_ibrt_auto_synchronize_status_get(void)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC] status:%d", ibrt_auto_synchronize_status);
|
|
return ibrt_auto_synchronize_status;
|
|
}
|
|
|
|
int app_bt_stream_ibrt_auto_synchronize_trigger_start(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger = &app_bt_stream_ibrt_auto_synchronize_trigger;
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC] trigger:%d Seq:%d timestamp:%d SubSeq:%d/%d currSeq:%d",
|
|
sync_trigger->trigger_time,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
sync_trigger->audio_info.timestamp,
|
|
sync_trigger->audio_info.curSubSequenceNumber,
|
|
sync_trigger->audio_info.totalSubSequenceNumber,
|
|
header->sequenceNumber
|
|
);
|
|
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
|
|
if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
if (sync_trigger->trigger_time >= bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle)){
|
|
app_bt_stream_ibrt_set_trigger_time(sync_trigger);
|
|
}else{
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC]failed trigger(%d)-->tg(%d) need resume", bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle),
|
|
sync_trigger->trigger_time);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
//app_tws_ibrt_audio_sync_mismatch_resume_notify();
|
|
}
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC] ok but currRole:%d mismatch\n", p_ibrt_ctrl->current_role);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_ibrt_auto_synchronize_dataind_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger = &app_bt_stream_ibrt_auto_synchronize_trigger;
|
|
bool synchronize_ok = false;
|
|
int32_t timestamp_diff = 0;
|
|
int32_t dma_buffer_samples = 0;
|
|
int32_t frame_totle_samples = 0;
|
|
|
|
frame_totle_samples = sync_trigger->audio_info.totalSubSequenceNumber * sync_trigger->audio_info.frame_samples;
|
|
timestamp_diff = sync_trigger->audio_info.timestamp - header->timestamp;
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] seq:%d/%d timestamp:%d/%d cnt:%d", header->sequenceNumber,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
header->timestamp,
|
|
sync_trigger->audio_info.timestamp,
|
|
app_bt_stream_ibrt_auto_synchronize_cnt);
|
|
|
|
if (++app_bt_stream_ibrt_auto_synchronize_cnt > APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_CNT_LIMIT){
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][DATAIND] SYNCHRONIZE_CNT_LIMIT, we need force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else if (app_tws_ibrt_mobile_link_connected()){
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][DATAIND] find role to master, we need force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else if (sync_trigger->audio_info.sequenceNumber < header->sequenceNumber){
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][DATAIND] seq timestamp:%d/%d mismatch need resume", header->timestamp,
|
|
sync_trigger->audio_info.timestamp);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
if (header->sequenceNumber >= sync_trigger->audio_info.sequenceNumber &&
|
|
!sync_trigger->audio_info.totalSubSequenceNumber){
|
|
synchronize_ok = true;
|
|
}else if (header->timestamp == sync_trigger->audio_info.timestamp){
|
|
synchronize_ok = true;
|
|
}
|
|
|
|
dma_buffer_samples = app_bt_stream_get_dma_buffer_samples()/2;
|
|
|
|
if (sync_trigger->audio_info.timestamp >= header->timestamp && sync_trigger->audio_info.totalSubSequenceNumber){
|
|
if (timestamp_diff < dma_buffer_samples){
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] timestamp_diff < dma_buffer_samples synchronize ok");
|
|
synchronize_ok = true;
|
|
}else if (timestamp_diff < frame_totle_samples){
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] timestamp_diff < frame_totle_samples synchronize ok");
|
|
synchronize_ok = true;
|
|
}
|
|
}
|
|
|
|
if (!synchronize_ok && header->sequenceNumber >= sync_trigger->audio_info.sequenceNumber){
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] timestamp %d vs %d", sync_trigger->audio_info.timestamp - header->timestamp,
|
|
frame_totle_samples);
|
|
if ((sync_trigger->audio_info.timestamp - header->timestamp) <= (uint32_t)(frame_totle_samples*3)){
|
|
sync_trigger->audio_info.sequenceNumber++;
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] timestamp try sequenceNumber:%d", header->sequenceNumber);
|
|
}
|
|
}
|
|
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
|
|
if (synchronize_ok){
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info) < 0){
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND]synchronize ok but lastframe error");
|
|
goto exit;
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND]synchronize ok timestamp_diff:%d frame_samples:%d", timestamp_diff,
|
|
lastframe_info.frame_samples);
|
|
sync_trigger->trigger_type = APP_TWS_IBRT_AUDIO_TRIGGER_TYPE_LOCAL;
|
|
sync_trigger->audio_info.sequenceNumber = header->sequenceNumber;
|
|
sync_trigger->audio_info.timestamp = header->timestamp;
|
|
if (sync_trigger->audio_info.totalSubSequenceNumber){
|
|
sync_trigger->audio_info.curSubSequenceNumber = timestamp_diff/lastframe_info.frame_samples;
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND]synchronize ok tstmp_diff:%d/%d SubSeq:%d", timestamp_diff, sync_trigger->audio_info.frame_samples,
|
|
sync_trigger->audio_info.curSubSequenceNumber);
|
|
}else{
|
|
sync_trigger->audio_info.curSubSequenceNumber = 0;
|
|
}
|
|
sync_trigger->audio_info.totalSubSequenceNumber = lastframe_info.totalSubSequenceNumber;
|
|
sync_trigger->audio_info.frame_samples = lastframe_info.frame_samples;
|
|
if (sync_trigger->audio_info.totalSubSequenceNumber &&
|
|
sync_trigger->audio_info.curSubSequenceNumber >= sync_trigger->audio_info.totalSubSequenceNumber){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][DATAIND]synchronize ok but sbc & timestamp is ms so force trigger");
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
a2dp_audio_detect_store_packet_callback_register(app_bt_stream_ibrt_auto_synchronize_trigger_start);
|
|
}
|
|
}else{
|
|
a2dp_audio_detect_first_packet();
|
|
}
|
|
}
|
|
exit:
|
|
return 0;
|
|
}
|
|
|
|
void app_bt_stream_ibrt_auto_synchronize_start(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][DATAIND] trigger_time:%d seq:%d timestamp:%d SubSeq:%d/%d", sync_trigger->trigger_time,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
sync_trigger->audio_info.timestamp,
|
|
sync_trigger->audio_info.curSubSequenceNumber,
|
|
sync_trigger->audio_info.totalSubSequenceNumber
|
|
);
|
|
app_bt_stream_ibrt_auto_synchronize_status_set(APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_ONPROCESS);
|
|
app_bt_stream_ibrt_auto_synchronize_cnt = 0;
|
|
app_bt_stream_ibrt_auto_synchronize_trigger = *sync_trigger;
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_auto_synchronize_dataind_cb);
|
|
a2dp_audio_detect_first_packet();
|
|
}
|
|
|
|
|
|
void app_bt_stream_ibrt_auto_synchronize_hungup(void)
|
|
{
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
}
|
|
|
|
void app_bt_stream_ibrt_auto_synchronize_stop(void)
|
|
{
|
|
app_bt_stream_ibrt_auto_synchronize_hungup();
|
|
app_bt_stream_ibrt_auto_synchronize_cnt = 0;
|
|
app_bt_stream_ibrt_auto_synchronize_status_set(APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_IDLE);
|
|
}
|
|
|
|
bool app_bt_stream_ibrt_auto_synchronize_on_porcess(void)
|
|
{
|
|
bool nRet = true;
|
|
APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_TYPE synchronize_status = app_bt_stream_ibrt_auto_synchronize_status_get();
|
|
if (synchronize_status == APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_IDLE){
|
|
nRet = false;
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
void app_bt_stream_ibrt_start_sbc_player_callback(uint32_t status, uint32_t param)
|
|
{
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
TRACE_AUD_STREAM_I("start_sbc_player_cb trigger(%d)-->tg(%d)", param, ((APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *)(uintptr_t)param)->trigger_time);
|
|
app_bt_stream_ibrt_set_trigger_time((APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *)(uintptr_t)param);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("start_sbc_player_cb try again");
|
|
app_audio_manager_sendrequest_need_callback(
|
|
APP_BT_STREAM_MANAGER_START,BT_STREAM_SBC,
|
|
BT_DEVICE_ID_1,
|
|
MAX_RECORD_NUM,
|
|
(uint32_t)(uintptr_t)app_bt_stream_ibrt_start_sbc_player_callback,
|
|
(uint32_t)param);
|
|
}
|
|
}
|
|
|
|
int app_bt_stream_ibrt_start_sbc_player(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger)
|
|
{
|
|
TRACE_AUD_STREAM_I("start_sbc_player tg(%d)", sync_trigger->trigger_time);
|
|
app_audio_manager_sendrequest_need_callback(
|
|
APP_BT_STREAM_MANAGER_START,BT_STREAM_SBC,
|
|
BT_DEVICE_ID_1,
|
|
MAX_RECORD_NUM,
|
|
(uint32_t)(uintptr_t)app_bt_stream_ibrt_start_sbc_player_callback,
|
|
(uint32_t)(uintptr_t)sync_trigger);
|
|
return 0;
|
|
}
|
|
|
|
uint16_t app_bt_stream_ibrt_trigger_seq_diff_calc(int32_t dma_samples, int32_t frame_samples, int32_t total_subseq, int32_t interval)
|
|
{
|
|
float seq_factor = 1.0f;
|
|
if (total_subseq){
|
|
seq_factor = (float)(dma_samples/frame_samples)/(float)total_subseq;
|
|
}else{
|
|
seq_factor = (float)(dma_samples/frame_samples);
|
|
}
|
|
return (uint16_t)(seq_factor * (float)interval);
|
|
}
|
|
|
|
#define MOBILE_LINK_PLAYBACK_INFO_TRIG_DUMMY_DMA_CNT (5)
|
|
#define SYNCHRONIZE_DATAIND_CNT_LIMIT (25)
|
|
|
|
static int synchronize_need_discards_dma_cnt = 0;
|
|
static int synchronize_dataind_cnt = 0;
|
|
|
|
int app_bt_stream_ibrt_auto_synchronize_initsync_dataind_cb_v2(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
bool synchronize_ok = false;
|
|
bool discards_samples_finished = false;
|
|
int dest_discards_samples = 0;
|
|
uint32_t list_samples = 0;
|
|
uint32_t curr_ticks = 0;
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger = &app_bt_stream_ibrt_auto_synchronize_trigger;
|
|
|
|
synchronize_dataind_cnt++;
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2] mobile_link is connect retrigger because role switch");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return 0;
|
|
}
|
|
|
|
if (synchronize_dataind_cnt >= SYNCHRONIZE_DATAIND_CNT_LIMIT){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2] mobile_link is connect retrigger because CNT_LIMIT");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return 0;
|
|
}
|
|
|
|
dest_discards_samples = app_bt_stream_get_dma_buffer_samples()/2*synchronize_need_discards_dma_cnt;
|
|
a2dp_audio_convert_list_to_samples(&list_samples);
|
|
if ((int)list_samples > dest_discards_samples){
|
|
discards_samples_finished = true;
|
|
a2dp_audio_discards_samples(dest_discards_samples);
|
|
}
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2] sample:%d->%d seq:%d sub_seq:%d/%d",
|
|
list_samples,dest_discards_samples,
|
|
headframe_info.sequenceNumber,
|
|
headframe_info.curSubSequenceNumber,
|
|
headframe_info.totalSubSequenceNumber);
|
|
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2] trig:%x/%x", curr_ticks, sync_trigger->trigger_time);
|
|
|
|
if (discards_samples_finished){
|
|
if (sync_trigger->trigger_time > curr_ticks){
|
|
synchronize_ok = true;
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2] synchronize_failed");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return 0;
|
|
}
|
|
}
|
|
if (synchronize_ok){
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2] synchronize_ok");
|
|
tg_acl_trigger_time = sync_trigger->trigger_time;
|
|
btdrv_syn_trigger_codec_en(1);
|
|
btdrv_syn_clr_trigger();
|
|
btdrv_enable_playback_triggler(ACL_TRIGGLE_MODE);
|
|
bt_syn_set_tg_ticks(sync_trigger->trigger_time, p_ibrt_ctrl->ibrt_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
app_tws_ibrt_audio_analysis_start(sync_trigger->handler_cnt, AUDIO_ANALYSIS_CHECKER_INTERVEL_INVALID);
|
|
app_tws_ibrt_audio_sync_start();
|
|
app_tws_ibrt_audio_sync_new_reference(sync_trigger->factor_reference);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2] trigger curr(%d)-->tg(%d)",
|
|
bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle),
|
|
sync_trigger->trigger_time);
|
|
synchronize_need_discards_dma_cnt = 0;
|
|
synchronize_dataind_cnt = 0;
|
|
a2dp_audio_detect_first_packet_clear();
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
}else{
|
|
a2dp_audio_detect_first_packet();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void app_bt_stream_ibrt_mobile_link_playback_info_receive(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger)
|
|
{
|
|
uint32_t tg_tick = 0;
|
|
uint32_t next_dma_cnt = 0;
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
A2DP_AUDIO_SYNCFRAME_INFO_T sync_info;
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger_loc = &app_bt_stream_ibrt_auto_synchronize_trigger;
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] session:%d hdl:%d clk:%d cnt:%d seq:%d/%d/%d", sync_trigger->a2dp_session,
|
|
sync_trigger->handler_cnt,
|
|
sync_trigger->trigger_bt_clk,
|
|
sync_trigger->trigger_bt_cnt,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
sync_trigger->audio_info.curSubSequenceNumber,
|
|
sync_trigger->audio_info.totalSubSequenceNumber);
|
|
|
|
if (app_bt_stream_ibrt_auto_synchronize_on_porcess()){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] auto_synchronize_on_porcess skip it");
|
|
return;
|
|
}
|
|
|
|
if (!app_bt_is_a2dp_streaming(BTIF_DEVICE_ID_1)){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] streaming not ready skip it");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
if (a2dp_ibrt_session_get() != sync_trigger->a2dp_session){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] session mismatch skip it loc:%d rmt:%d", a2dp_ibrt_session_get(), sync_trigger->a2dp_session);
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] session froce resume and try retrigger");
|
|
a2dp_ibrt_session_set(sync_trigger->a2dp_session);
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info) < 0){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] lastframe not ready mismatch_stopaudio");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
*sync_trigger_loc = *sync_trigger;
|
|
|
|
sync_info.sequenceNumber = sync_trigger->audio_info.sequenceNumber;
|
|
sync_info.timestamp = sync_trigger->audio_info.timestamp;
|
|
sync_info.curSubSequenceNumber = sync_trigger->audio_info.curSubSequenceNumber;
|
|
sync_info.totalSubSequenceNumber = sync_trigger->audio_info.totalSubSequenceNumber;
|
|
sync_info.frame_samples = sync_trigger->audio_info.frame_samples;
|
|
if (a2dp_audio_synchronize_packet(&sync_info, A2DP_AUDIO_SYNCFRAME_MASK_ALL)){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNCV2][INFO_RECV] synchronize_packe mismatch");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return;
|
|
}
|
|
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] sync with master packet step1 seq:%d sub_seq:%d/%d",
|
|
headframe_info.sequenceNumber,
|
|
headframe_info.curSubSequenceNumber,
|
|
headframe_info.totalSubSequenceNumber);
|
|
a2dp_audio_discards_samples(lastframe_info.list_samples);
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] sync with master packet step2 seq:%d sub_seq:%d/%d",
|
|
headframe_info.sequenceNumber,
|
|
headframe_info.curSubSequenceNumber,
|
|
headframe_info.totalSubSequenceNumber);
|
|
|
|
uint32_t btclk;
|
|
uint16_t btcnt;
|
|
uint32_t mobile_master_clk = 0;
|
|
uint16_t mobile_master_cnt = 0;
|
|
int64_t mobile_master_us = 0;
|
|
btclk = btdrv_syn_get_curr_ticks()/2;
|
|
btcnt = 0;
|
|
app_tws_ibrt_audio_mobile_clkcnt_get(btclk, btcnt,
|
|
&mobile_master_clk, &mobile_master_cnt);
|
|
mobile_master_us = (int64_t)mobile_master_clk * (int64_t)SLOT_SIZE + (int64_t)mobile_master_cnt;
|
|
|
|
uint32_t rmt_mobile_master_clk = sync_trigger->trigger_bt_clk;
|
|
uint16_t rmt_mobile_master_cnt = sync_trigger->trigger_bt_cnt;
|
|
int64_t rmt_mobile_master_us = 0;
|
|
int64_t tmp_mobile_master_us = 0;
|
|
rmt_mobile_master_us = (int64_t)rmt_mobile_master_clk * (int64_t)SLOT_SIZE + (int64_t)rmt_mobile_master_cnt;
|
|
|
|
uint32_t dma_buffer_us = 0;
|
|
dma_buffer_us = app_bt_stream_get_dma_buffer_delay_us()/2;
|
|
|
|
tmp_mobile_master_us = rmt_mobile_master_us;
|
|
do{
|
|
if (tmp_mobile_master_us - mobile_master_us >= 0){
|
|
break;
|
|
}
|
|
tmp_mobile_master_us += dma_buffer_us;
|
|
next_dma_cnt++;
|
|
}while(1);
|
|
next_dma_cnt += MOBILE_LINK_PLAYBACK_INFO_TRIG_DUMMY_DMA_CNT ;
|
|
tmp_mobile_master_us += dma_buffer_us * (MOBILE_LINK_PLAYBACK_INFO_TRIG_DUMMY_DMA_CNT-1);
|
|
synchronize_need_discards_dma_cnt = next_dma_cnt + a2dp_audio_frame_delay_get() - 1;
|
|
synchronize_dataind_cnt = 0;
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] loc:%08x%08x rmt:%08x%08x tg:%08x%08x", (uint32_t)((uint64_t)mobile_master_us>>32U), (uint32_t)((uint64_t)mobile_master_us&0xffffffff),
|
|
(uint32_t)((uint64_t)rmt_mobile_master_us>>32U), (uint32_t)((uint64_t)rmt_mobile_master_us&0xffffffff),
|
|
(uint32_t)((uint64_t)tmp_mobile_master_us>>32U), (uint32_t)((uint64_t)tmp_mobile_master_us&0xffffffff));
|
|
|
|
tmp_mobile_master_us = tmp_mobile_master_us/SLOT_SIZE;
|
|
|
|
tg_tick = tmp_mobile_master_us * 2;
|
|
tg_tick &= 0x0fffffff;
|
|
|
|
sync_trigger_loc->trigger_type = APP_TWS_IBRT_AUDIO_TRIGGER_TYPE_LOCAL;
|
|
sync_trigger_loc->trigger_time = tg_tick;
|
|
sync_trigger_loc->handler_cnt += next_dma_cnt;
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_auto_synchronize_initsync_dataind_cb_v2);
|
|
a2dp_audio_detect_first_packet();
|
|
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] mobile clk:%x/%x tg:%x", bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle)/2,
|
|
mobile_master_clk,
|
|
tg_tick/2);
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNCV2][INFO_RECV] master_us:%x/%x/%x dma_cnt:%d/%d", (int32_t)mobile_master_us, (int32_t)rmt_mobile_master_us, (int32_t)tmp_mobile_master_us,
|
|
next_dma_cnt, sync_trigger_loc->handler_cnt);
|
|
}
|
|
|
|
|
|
void app_bt_stream_ibrt_set_trigger_time(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger)
|
|
{
|
|
uint32_t curr_ticks = 0;
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
uint32_t tg_tick = sync_trigger->trigger_time;
|
|
A2DP_AUDIO_SYNCFRAME_INFO_T sync_info;
|
|
int synchronize_ret;
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
|
|
if (app_bt_stream_ibrt_auto_synchronize_on_porcess()){
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] auto_synchronize_on_porcess skip it");
|
|
return;
|
|
}
|
|
|
|
if (!app_bt_is_a2dp_streaming(BTIF_DEVICE_ID_1)){
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] streaming not ready skip it");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
if (a2dp_ibrt_session_get() != sync_trigger->a2dp_session){
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] session mismatch skip it loc:%d rmt:%d", a2dp_ibrt_session_get(), sync_trigger->a2dp_session);
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] session froce resume and try retrigger");
|
|
a2dp_ibrt_session_set(sync_trigger->a2dp_session);
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info) < 0){
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] lastframe not ready mismatch_stopaudio");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
return;
|
|
}
|
|
|
|
if (a2dp_audio_decoder_headframe_info_get(&headframe_info) < 0){
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] lastframe not ready mismatch_stopaudio");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
goto exit;
|
|
}
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] info base_seq:%d/%d", headframe_info.sequenceNumber, sync_trigger->sequenceNumberStart);
|
|
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
|
|
sync_info.sequenceNumber = sync_trigger->sequenceNumberStart;
|
|
synchronize_ret = a2dp_audio_synchronize_packet(&sync_info, A2DP_AUDIO_SYNCFRAME_MASK_SEQ);
|
|
if (synchronize_ret){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] synchronize_packet failed");
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
goto exit;
|
|
}
|
|
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle);
|
|
if (tg_tick < curr_ticks){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] synchronize tick failed:%x->%x", curr_ticks, tg_tick);
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
goto exit;
|
|
}
|
|
sync_info.sequenceNumber = sync_trigger->audio_info.sequenceNumber;
|
|
sync_info.timestamp = sync_trigger->audio_info.timestamp;
|
|
sync_info.curSubSequenceNumber = sync_trigger->audio_info.curSubSequenceNumber;
|
|
sync_info.totalSubSequenceNumber = sync_trigger->audio_info.totalSubSequenceNumber;
|
|
sync_info.frame_samples = sync_trigger->audio_info.frame_samples;
|
|
|
|
if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
if (sync_trigger->trigger_type == APP_TWS_IBRT_AUDIO_TRIGGER_TYPE_INIT_SYNC){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] TRIGGER_TYPE_INIT_SYNC needskip:%d", sync_trigger->trigger_skip_frame);
|
|
//limter to water line upper
|
|
uint32_t list_samples = 0;
|
|
uint32_t limter_water_line_samples = 0;
|
|
limter_water_line_samples = (a2dp_audio_dest_packet_mut_get() * lastframe_info.list_samples);
|
|
a2dp_audio_convert_list_to_samples(&list_samples);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] synchronize:%d/%d", list_samples, limter_water_line_samples);
|
|
if (list_samples > limter_water_line_samples){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] skip discards:%d", list_samples - limter_water_line_samples);
|
|
a2dp_audio_discards_samples(list_samples - limter_water_line_samples);
|
|
}
|
|
app_bt_stream_ibrt_auto_synchronize_initsync_start(sync_trigger);
|
|
app_bt_stream_ibrt_auto_synchronize_status_set(APP_TWS_IBRT_AUDIO_SYNCHRONIZE_STATUS_SYNCOK);
|
|
}
|
|
}else if (!app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM)){
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][IBRT] sbc player not active, so try to start it");
|
|
app_bt_stream_ibrt_auto_synchronize_trigger = *sync_trigger;
|
|
app_bt_stream_ibrt_audio_mismatch_stopaudio();
|
|
}
|
|
}else{
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][A2DP][IBRT] Not Connected");
|
|
}
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
void app_bt_stream_ibrt_audio_mismatch_resume(void)
|
|
{
|
|
ibrt_a2dp_status_t a2dp_status;
|
|
|
|
a2dp_ibrt_sync_get_status(&a2dp_status);
|
|
|
|
TRACE_AUD_STREAM_I("[MISMATCH] resume state:%d", a2dp_status.state);
|
|
|
|
if (a2dp_status.state == BTIF_AVDTP_STRM_STATE_STREAMING){
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
TRACE_AUD_STREAM_I("[MISMATCH] resume find role switch so force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
app_tws_ibrt_audio_sync_mismatch_resume_notify();
|
|
}
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_ibrt_audio_mismatch_stopaudio_cb(uint32_t status, uint32_t param)
|
|
{
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio_cb");
|
|
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio_cb try again");
|
|
app_audio_manager_sendrequest_need_callback(
|
|
APP_BT_STREAM_MANAGER_STOP,BT_STREAM_SBC,
|
|
BT_DEVICE_ID_1,
|
|
MAX_RECORD_NUM,
|
|
(uintptr_t)app_bt_stream_ibrt_audio_mismatch_stopaudio_cb,
|
|
(uint32_t)NULL);
|
|
}else{
|
|
app_bt_stream_ibrt_audio_mismatch_resume();
|
|
}
|
|
}
|
|
|
|
int app_bt_stream_ibrt_audio_mismatch_stopaudio(void)
|
|
{
|
|
ibrt_a2dp_status_t a2dp_status;
|
|
|
|
a2dp_ibrt_sync_get_status(&a2dp_status);
|
|
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio state:%d sco:%d sbc:%d media:%d", a2dp_status.state,
|
|
app_audio_manager_hfp_is_active(BT_DEVICE_ID_1),
|
|
app_audio_manager_a2dp_is_active(BT_DEVICE_ID_1),
|
|
app_bt_stream_isrun(APP_PLAY_BACK_AUDIO));
|
|
|
|
if (a2dp_status.state == BTIF_AVDTP_STRM_STATE_STREAMING){
|
|
if (app_audio_manager_a2dp_is_active(BT_DEVICE_ID_1)){
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio");
|
|
app_audio_sendrequest_param(APP_BT_STREAM_A2DP_SBC, (uint8_t)APP_BT_SETTING_RESTART, 0, APP_SYSFREQ_52M);
|
|
app_bt_stream_ibrt_audio_mismatch_resume();
|
|
}else{
|
|
if (app_ibrt_ui_is_profile_exchanged()){
|
|
if (!bt_media_is_sbc_media_active()){
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio not active resume it & force retrigger");
|
|
app_audio_manager_sendrequest(APP_BT_STREAM_MANAGER_START,BT_STREAM_SBC, BT_DEVICE_ID_1,MAX_RECORD_NUM);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
if (app_bt_stream_isrun(APP_PLAY_BACK_AUDIO)
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
&&app_play_audio_get_aud_id() == AUDIO_ID_BT_MUTE
|
|
#endif
|
|
){
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio resum on process skip it");
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio cancel_media and force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}
|
|
}
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[MISMATCH] stopaudio profile not exchanged skip it");
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void app_bt_stream_set_trigger_time(uint32_t trigger_time_us)
|
|
{
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
uint32_t curr_ticks = 0;
|
|
uint32_t dma_buffer_delay_us = 0;
|
|
uint32_t tg_acl_trigger_offset_time = 0;
|
|
|
|
|
|
if (trigger_time_us){
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
uint16_t conhandle = INVALID_HANDLE;
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
conhandle = p_ibrt_ctrl->mobile_conhandle;
|
|
curr_ticks = bt_syn_get_curr_ticks(conhandle);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
conhandle = p_ibrt_ctrl->ibrt_conhandle;
|
|
curr_ticks = bt_syn_get_curr_ticks(conhandle);
|
|
}else{
|
|
return;
|
|
}
|
|
#else
|
|
curr_ticks = btdrv_syn_get_curr_ticks();
|
|
#endif
|
|
af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, false);
|
|
btdrv_syn_trigger_codec_en(0);
|
|
btdrv_syn_clr_trigger();
|
|
|
|
btdrv_enable_playback_triggler(ACL_TRIGGLE_MODE);
|
|
|
|
dma_buffer_delay_us = app_bt_stream_get_dma_buffer_delay_us();
|
|
dma_buffer_delay_us /= 2;
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][SETTIME] %d-%d-%d dma_sz:%d dly:%d", stream_cfg->sample_rate, stream_cfg->channel_num, stream_cfg->bits,
|
|
stream_cfg->data_size, dma_buffer_delay_us);
|
|
|
|
tg_acl_trigger_offset_time = US_TO_BTCLKS(trigger_time_us-dma_buffer_delay_us);
|
|
tg_acl_trigger_time = curr_ticks + tg_acl_trigger_offset_time;
|
|
tg_acl_trigger_start_time = curr_ticks;
|
|
#if defined(IBRT)
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_time, conhandle, BT_TRIG_SLAVE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][SETTIME] %d->%d trig_dly:%d aud_dly:%dus",
|
|
curr_ticks, tg_acl_trigger_time, trigger_time_us-dma_buffer_delay_us, trigger_time_us+dma_buffer_delay_us);
|
|
#else
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_time, 0, BT_TRIG_NONE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][SETTIME] %d->%d trig_dly:%d aud_dly:%dus",
|
|
curr_ticks, tg_acl_trigger_time, trigger_time_us-dma_buffer_delay_us, trigger_time_us+dma_buffer_delay_us);
|
|
#endif
|
|
|
|
btdrv_syn_trigger_codec_en(1);
|
|
app_bt_stream_trigger_stauts_set(BT_STREAM_TRIGGER_STATUS_WAIT);
|
|
}else{
|
|
tg_acl_trigger_time = 0;
|
|
tg_acl_trigger_start_time = 0;
|
|
btdrv_syn_trigger_codec_en(0);
|
|
btdrv_syn_clr_trigger();
|
|
app_bt_stream_trigger_stauts_set(BT_STREAM_TRIGGER_STATUS_NULL);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][SETTIME] trigger clear");
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_trigger_result(void)
|
|
{
|
|
uint32_t curr_ticks = 0;
|
|
|
|
if(tg_acl_trigger_time){
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->mobile_conhandle);
|
|
bt_syn_trig_checker(p_ibrt_ctrl->mobile_conhandle);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle);
|
|
bt_syn_trig_checker(p_ibrt_ctrl->ibrt_conhandle);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][RESULT] mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
curr_ticks = btdrv_syn_get_curr_ticks();
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][RESULT] trig:%d curr:%d tg:%d start:%d", (curr_ticks - (uint32_t)US_TO_BTCLKS(app_bt_stream_get_dma_buffer_delay_us()/2)),
|
|
curr_ticks, tg_acl_trigger_time, tg_acl_trigger_start_time);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][RESULT] tg_trig_diff:%d trig_diff:%d", (uint32_t)BTCLKS_TO_US(curr_ticks-tg_acl_trigger_time),
|
|
(uint32_t)BTCLKS_TO_US(curr_ticks-tg_acl_trigger_start_time));
|
|
app_bt_stream_set_trigger_time(0);
|
|
app_bt_stream_trigger_stauts_set(BT_STREAM_TRIGGER_STATUS_OK);
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][RESULT] synchronize_ok :%d", headframe_info.sequenceNumber);
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_playback_irq_notification(enum AUD_STREAM_ID_T id, enum AUD_STREAM_T stream)
|
|
{
|
|
if (id != AUD_STREAM_ID_0 || stream != AUD_STREAM_PLAYBACK) {
|
|
return;
|
|
}
|
|
app_bt_stream_trigger_result();
|
|
#if defined(IBRT)
|
|
app_tws_ibrt_audio_analysis_interrupt_tick();
|
|
#endif
|
|
}
|
|
extern void a2dp_audio_set_mtu_limit(uint8_t mut);
|
|
extern float a2dp_audio_latency_factor_get(void);
|
|
extern uint8_t a2dp_lhdc_config_llc_get(void);
|
|
|
|
void app_bt_stream_trigger_init(void)
|
|
{
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
tg_acl_trigger_init_time = bt_syn_get_curr_ticks(p_ibrt_ctrl->mobile_conhandle);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
tg_acl_trigger_init_time = bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][INIT] mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
tg_acl_trigger_init_time = btdrv_syn_get_curr_ticks();
|
|
#endif
|
|
app_bt_stream_set_trigger_time(0);
|
|
#ifdef PLAYBACK_USE_I2S
|
|
af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, false);
|
|
af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, true);
|
|
#else
|
|
af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false);
|
|
af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, true);
|
|
#endif
|
|
app_bt_stream_trigger_stauts_set(BT_STREAM_TRIGGER_STATUS_INIT);
|
|
}
|
|
|
|
void app_bt_stream_trigger_deinit(void)
|
|
{
|
|
app_bt_stream_set_trigger_time(0);
|
|
}
|
|
|
|
void app_bt_stream_trigger_start(uint8_t offset)
|
|
{
|
|
float tg_trigger_time = 0;
|
|
uint32_t curr_ticks;
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, false);
|
|
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->mobile_conhandle);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
curr_ticks = bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle);
|
|
}else{
|
|
return;
|
|
}
|
|
#else
|
|
curr_ticks = btdrv_syn_get_curr_ticks();
|
|
#endif
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][START] init(%d)-->set_trig(%d) %dus", tg_acl_trigger_init_time, curr_ticks, (uint32_t)BTCLKS_TO_US(curr_ticks-tg_acl_trigger_init_time));
|
|
|
|
#if defined(A2DP_AAC_ON)
|
|
if(bt_sbc_player_get_codec_type() == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC){
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_AAC_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_AAC_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU);
|
|
#endif
|
|
}else
|
|
#endif
|
|
if(bt_sbc_player_get_codec_type() == BTIF_AVDTP_CODEC_TYPE_NON_A2DP){
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE){
|
|
if(stream_cfg->sample_rate > AUD_SAMPRATE_48000){
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_US * a2dp_audio_latency_factor_get();
|
|
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_MTU);
|
|
#endif
|
|
}else{
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_MTU);
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LHDC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC){
|
|
if (a2dp_lhdc_config_llc_get()){
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU);
|
|
#endif
|
|
}else if(stream_cfg->sample_rate > AUD_SAMPRATE_48000){
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU);
|
|
#endif
|
|
}else{
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_BASE;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU);
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC){
|
|
uint32_t frame_mtu = A2DP_PLAYER_PLAYBACK_DELAY_LDAC_FRAME_MTU;
|
|
#if (A2DP_DECODER_VER == 2)
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
if (!a2dp_audio_lastframe_info_get(&lastframe_info)){
|
|
frame_mtu = lastframe_info.totalSubSequenceNumber;
|
|
}
|
|
#endif
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_LDAC_US * a2dp_audio_latency_factor_get();
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_LDAC_BASE*frame_mtu;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU);
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][A2DP][START] [%d,%d,%d]", A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU,A2DP_PLAYER_PLAYBACK_DELAY_LDAC_BASE,A2DP_PLAYER_PLAYBACK_DELAY_LDAC_US);
|
|
|
|
}
|
|
#endif
|
|
}else
|
|
{
|
|
uint32_t frame_mtu = A2DP_PLAYER_PLAYBACK_DELAY_SBC_FRAME_MTU;
|
|
#if (A2DP_DECODER_VER == 2)
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
if (!a2dp_audio_lastframe_info_get(&lastframe_info)){
|
|
frame_mtu = lastframe_info.totalSubSequenceNumber;
|
|
}
|
|
#endif
|
|
tg_trigger_time = A2DP_PLAYER_PLAYBACK_DELAY_SBC_US;
|
|
tg_trigger_time += offset*A2DP_PLAYER_PLAYBACK_DELAY_SBC_BASE*frame_mtu;
|
|
#if (A2DP_DECODER_VER < 2)
|
|
a2dp_audio_set_mtu_limit(A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU);
|
|
#endif
|
|
}
|
|
app_bt_stream_set_trigger_time((uint32_t)tg_trigger_time);
|
|
}
|
|
|
|
bool app_bt_stream_trigger_onprocess(void)
|
|
{
|
|
if (app_bt_stream_trigger_stauts_get() == BT_STREAM_TRIGGER_STATUS_INIT){
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#if defined(IBRT)
|
|
#ifdef A2DP_CP_ACCEL
|
|
#define APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME (8)
|
|
#define APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC (12)
|
|
|
|
#else
|
|
#define APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME (4)
|
|
#endif
|
|
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T app_bt_stream_ibrt_auto_synchronize_initsync_trigger;
|
|
|
|
int app_bt_stream_ibrt_auto_synchronize_initsync_dataind_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger = &app_bt_stream_ibrt_auto_synchronize_initsync_trigger;
|
|
bool synchronize_ok = false;
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][INITSYNC][DATAIND] dataind_seq:%d/%d timestamp:%d/%d", header->sequenceNumber,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
header->timestamp,
|
|
sync_trigger->audio_info.timestamp);
|
|
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info)<0){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return 0;
|
|
}
|
|
|
|
if (app_bt_stream_trigger_stauts_get() != BT_STREAM_TRIGGER_STATUS_WAIT){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] already end");
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
return 0;
|
|
}
|
|
|
|
if (sync_trigger->audio_info.sequenceNumber < header->sequenceNumber){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] force retrigger");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
if (header->sequenceNumber >= sync_trigger->audio_info.sequenceNumber){
|
|
synchronize_ok = true;
|
|
}
|
|
|
|
if (synchronize_ok && app_bt_stream_trigger_stauts_get() != BT_STREAM_TRIGGER_STATUS_WAIT){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] synchronize_failed");
|
|
app_ibrt_if_force_audio_retrigger();
|
|
return 0;
|
|
}
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
//limter to water line upper
|
|
uint32_t list_samples = 0;
|
|
uint32_t limter_water_line_samples = 0;
|
|
limter_water_line_samples = (a2dp_audio_dest_packet_mut_get() * lastframe_info.list_samples);
|
|
a2dp_audio_convert_list_to_samples(&list_samples);
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] synchronize:%d/%d", list_samples, limter_water_line_samples);
|
|
if (list_samples > limter_water_line_samples){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] skip discards:%d", list_samples - limter_water_line_samples);
|
|
a2dp_audio_discards_samples(list_samples - limter_water_line_samples);
|
|
}
|
|
#else
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
#endif
|
|
if (synchronize_ok){
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][INITSYNC][DATAIND] synchronize_ok :%d", headframe_info.sequenceNumber);
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
}else{
|
|
a2dp_audio_detect_first_packet();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void app_bt_stream_ibrt_auto_synchronize_initsync_start(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T *sync_trigger)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][INITSYNC] start trigger_time:%d seq:%d timestamp:%d SubSeq:%d/%d", sync_trigger->trigger_time,
|
|
sync_trigger->audio_info.sequenceNumber,
|
|
sync_trigger->audio_info.timestamp,
|
|
sync_trigger->audio_info.curSubSequenceNumber,
|
|
sync_trigger->audio_info.totalSubSequenceNumber
|
|
);
|
|
app_bt_stream_ibrt_auto_synchronize_initsync_trigger = *sync_trigger;
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_auto_synchronize_initsync_dataind_cb);
|
|
a2dp_audio_detect_first_packet();
|
|
if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (sync_trigger->trigger_time > bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle)){
|
|
uint32_t tg_tick = sync_trigger->trigger_time;
|
|
btdrv_syn_trigger_codec_en(1);
|
|
btdrv_syn_clr_trigger();
|
|
btdrv_enable_playback_triggler(ACL_TRIGGLE_MODE);
|
|
bt_syn_set_tg_ticks(tg_tick, p_ibrt_ctrl->ibrt_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
tg_acl_trigger_time = tg_tick;
|
|
app_bt_stream_trigger_stauts_set(BT_STREAM_TRIGGER_STATUS_WAIT);
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][INITSYNC] start slave trigger curr(%d)-->tg(%d)", bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle), tg_tick);
|
|
app_tws_ibrt_audio_analysis_start(sync_trigger->handler_cnt, AUDIO_ANALYSIS_CHECKER_INTERVEL_INVALID);
|
|
app_tws_ibrt_audio_sync_start();
|
|
app_tws_ibrt_audio_sync_new_reference(sync_trigger->factor_reference);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][INITSYNC] start slave failed trigger(%d)-->tg(%d) need resume",
|
|
bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle),
|
|
sync_trigger->trigger_time);
|
|
app_tws_ibrt_audio_sync_mismatch_resume_notify();
|
|
}
|
|
}
|
|
}
|
|
|
|
int app_bt_stream_ibrt_audio_master_detect_next_packet_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
A2DP_AUDIO_SYNCFRAME_INFO_T sync_info;
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
#endif
|
|
|
|
if(app_bt_stream_trigger_stauts_get() == BT_STREAM_TRIGGER_STATUS_INIT){
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
int32_t dma_buffer_samples = app_bt_stream_get_dma_buffer_samples()/2;
|
|
|
|
if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][MASTER] cache ok but currRole:%d mismatch\n", p_ibrt_ctrl->current_role);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else if (!app_ibrt_ui_is_profile_exchanged() &&
|
|
!app_ibrt_if_start_ibrt_onporcess() &&
|
|
!app_ibrt_sync_a2dp_status_onporcess()){
|
|
if (p_ibrt_ctrl->mobile_mode == IBRT_SNIFF_MODE){
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
a2dp_audio_detect_first_packet();
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache skip delay dma trigger1\n");
|
|
return 0;
|
|
}
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache ok use dma trigger1\n");
|
|
a2dp_audio_detect_next_packet_callback_register(NULL);
|
|
a2dp_audio_detect_store_packet_callback_register(NULL);
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
app_bt_stream_trigger_start(A2DP_PLAYER_PLAYBACK_WATER_LINE);
|
|
#else
|
|
app_bt_stream_trigger_start(0);
|
|
#endif
|
|
}else if (app_ibrt_if_start_ibrt_onporcess() ||
|
|
app_ibrt_sync_a2dp_status_onporcess() ||
|
|
app_ibrt_waiting_cmd_rsp()){
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
a2dp_audio_detect_first_packet();
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache skip profile_exchanged sync_a2dp_status_onporcess\n");
|
|
return 0;
|
|
}else{
|
|
if (p_ibrt_ctrl->tws_mode == IBRT_SNIFF_MODE ||
|
|
p_ibrt_ctrl->mobile_mode == IBRT_SNIFF_MODE){
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
a2dp_audio_detect_first_packet();
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache skip delay dma trigger2\n");
|
|
return 0;
|
|
}
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
uint32_t dest_waterline_samples = 0;
|
|
uint32_t list_samples = 0;
|
|
dest_waterline_samples = app_bt_stream_get_dma_buffer_samples()/2*A2DP_PLAYER_PLAYBACK_WATER_LINE;
|
|
a2dp_audio_convert_list_to_samples(&list_samples);
|
|
if (list_samples < dest_waterline_samples){
|
|
a2dp_audio_detect_first_packet();
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache skip fill data sample:%d\n", list_samples);
|
|
return 0;
|
|
}
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
sync_info.sequenceNumber = headframe_info.sequenceNumber;
|
|
}
|
|
else
|
|
{
|
|
sync_info.sequenceNumber = headframe_info.sequenceNumber + 1;
|
|
}
|
|
a2dp_audio_synchronize_packet(&sync_info, A2DP_AUDIO_SYNCFRAME_MASK_SEQ);
|
|
#else
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] cache ok use dma trigger2\n");
|
|
//uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
#ifdef A2DP_CP_ACCEL
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC - a2dp_audio_frame_delay_get());
|
|
}
|
|
else
|
|
{
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME - a2dp_audio_frame_delay_get());
|
|
}
|
|
#else
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME);
|
|
#endif
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T sync_trigger;
|
|
A2DP_AUDIO_HEADFRAME_INFO_T headframe_info;
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info;
|
|
sync_trigger.trigger_time = tg_acl_trigger_time;
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
sync_trigger.trigger_skip_frame = APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC - a2dp_audio_frame_delay_get();
|
|
}
|
|
else
|
|
{
|
|
sync_trigger.trigger_skip_frame = APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME - a2dp_audio_frame_delay_get();
|
|
}
|
|
sync_trigger.trigger_type = APP_TWS_IBRT_AUDIO_TRIGGER_TYPE_INIT_SYNC;
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info)<0){
|
|
goto exit;
|
|
}
|
|
|
|
a2dp_audio_decoder_headframe_info_get(&headframe_info);
|
|
sync_trigger.sequenceNumberStart = headframe_info.sequenceNumber;
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
sync_trigger.audio_info.sequenceNumber = lastframe_info.sequenceNumber + APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC;
|
|
if (lastframe_info.totalSubSequenceNumber){
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp +
|
|
(lastframe_info.totalSubSequenceNumber * lastframe_info.frame_samples) *
|
|
APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC;
|
|
}else{
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp + dma_buffer_samples * APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sync_trigger.audio_info.sequenceNumber = lastframe_info.sequenceNumber + APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME;
|
|
if (lastframe_info.totalSubSequenceNumber){
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp +
|
|
(lastframe_info.totalSubSequenceNumber * lastframe_info.frame_samples) *
|
|
APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME;
|
|
}else{
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp + dma_buffer_samples * APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME;
|
|
}
|
|
}
|
|
sync_trigger.audio_info.curSubSequenceNumber = lastframe_info.curSubSequenceNumber;
|
|
sync_trigger.audio_info.totalSubSequenceNumber = lastframe_info.totalSubSequenceNumber;
|
|
sync_trigger.audio_info.frame_samples = lastframe_info.frame_samples;
|
|
sync_trigger.factor_reference = a2dp_audio_get_output_config()->factor_reference;
|
|
sync_trigger.a2dp_session = a2dp_ibrt_session_get();
|
|
sync_trigger.handler_cnt = 0;
|
|
|
|
app_bt_stream_ibrt_auto_synchronize_initsync_start(&sync_trigger);
|
|
|
|
if (app_tws_ibrt_mobile_link_connected() &&
|
|
app_ibrt_ui_is_profile_exchanged()){
|
|
tws_ctrl_send_cmd_high_priority(APP_TWS_CMD_SET_TRIGGER_TIME, (uint8_t*)&sync_trigger, sizeof(APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T));
|
|
}
|
|
}
|
|
}else{
|
|
if(app_bt_stream_trigger_stauts_get() == BT_STREAM_TRIGGER_STATUS_NULL){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][MASTER] audio not ready skip it");
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] unhandle status:%d", app_bt_stream_trigger_stauts_get());
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}
|
|
}
|
|
exit:
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_ibrt_audio_master_detect_next_packet_start(void)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][MASTER] start");
|
|
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_audio_master_detect_next_packet_cb);
|
|
return 0;
|
|
}
|
|
|
|
#define SLAVE_DETECT_NEXT_PACKET_TO_RETRIGGER_THRESHOLD (120)
|
|
static uint32_t slave_detect_next_packet_cnt = 0;
|
|
int app_bt_stream_ibrt_audio_slave_detect_next_packet_waitforever_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
if (app_tws_ibrt_mobile_link_connected() || ++slave_detect_next_packet_cnt > SLAVE_DETECT_NEXT_PACKET_TO_RETRIGGER_THRESHOLD){
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][SLAVE] detect_next_packet ok but currRole:%d mismatch packet_cnt:%d\n", p_ibrt_ctrl->current_role,
|
|
slave_detect_next_packet_cnt);
|
|
slave_detect_next_packet_cnt = 0;
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][SLAVE] detect_next_packet cnt:%d\n", slave_detect_next_packet_cnt);
|
|
a2dp_audio_detect_first_packet();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_ibrt_audio_slave_detect_next_packet_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
if(app_bt_stream_trigger_onprocess()){
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
int32_t dma_buffer_samples = app_bt_stream_get_dma_buffer_samples()/2;
|
|
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][SLAVE]cache ok but currRole:%d mismatch\n", p_ibrt_ctrl->current_role);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}else{
|
|
if (app_tws_ibrt_slave_ibrt_link_connected() &&
|
|
(p_ibrt_ctrl->tws_mode == IBRT_SNIFF_MODE ||
|
|
p_ibrt_ctrl->mobile_mode == IBRT_SNIFF_MODE ||
|
|
!app_ibrt_ui_is_profile_exchanged())){
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
a2dp_audio_detect_first_packet();
|
|
TRACE_AUD_STREAM_W("[AUTO_SYNC][SLAVE]cache skip delay dma trigger2\n");
|
|
return 0;
|
|
}
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][SLAVE]cache ok use dma trigger2\n");
|
|
//flush all
|
|
a2dp_audio_synchronize_dest_packet_mut(0);
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
#ifdef A2DP_CP_ACCEL
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC - a2dp_audio_frame_delay_get());
|
|
}
|
|
else
|
|
{
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME - a2dp_audio_frame_delay_get());
|
|
}
|
|
#else
|
|
app_bt_stream_trigger_start(APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME);
|
|
#endif
|
|
APP_TWS_IBRT_AUDIO_SYNC_TRIGGER_T sync_trigger = {0,};
|
|
A2DP_AUDIO_LASTFRAME_INFO_T lastframe_info = {0,};
|
|
sync_trigger.trigger_time = tg_acl_trigger_time;
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
sync_trigger.trigger_skip_frame = APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC - a2dp_audio_frame_delay_get();
|
|
}
|
|
else
|
|
{
|
|
sync_trigger.trigger_skip_frame = APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME - a2dp_audio_frame_delay_get();
|
|
}
|
|
sync_trigger.trigger_type = APP_TWS_IBRT_AUDIO_TRIGGER_TYPE_INIT_SYNC;
|
|
if (a2dp_audio_lastframe_info_get(&lastframe_info)<0){
|
|
goto exit;
|
|
}
|
|
if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC)
|
|
{
|
|
sync_trigger.audio_info.sequenceNumber = lastframe_info.sequenceNumber + APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC;
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp + dma_buffer_samples * APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME_LHDC;
|
|
}
|
|
else
|
|
{
|
|
sync_trigger.audio_info.sequenceNumber = lastframe_info.sequenceNumber + APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME;
|
|
sync_trigger.audio_info.timestamp = lastframe_info.timestamp + dma_buffer_samples * APP_BT_STREAM_IBRT_AUTO_SYNCHRONIZE_INITSYNC_SKIP_FRAME;
|
|
}
|
|
sync_trigger.audio_info.curSubSequenceNumber = lastframe_info.curSubSequenceNumber;
|
|
sync_trigger.audio_info.totalSubSequenceNumber = lastframe_info.totalSubSequenceNumber;
|
|
sync_trigger.audio_info.frame_samples = lastframe_info.frame_samples;
|
|
sync_trigger.factor_reference = a2dp_audio_get_output_config() ? a2dp_audio_get_output_config()->factor_reference : 1.0f;
|
|
sync_trigger.a2dp_session = a2dp_ibrt_session_get();
|
|
sync_trigger.handler_cnt = 0;
|
|
|
|
app_bt_stream_ibrt_auto_synchronize_initsync_start(&sync_trigger);
|
|
}
|
|
}
|
|
exit:
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_ibrt_audio_slave_detect_next_packet_start(int need_autotrigger)
|
|
{
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC][SLAVE] start");
|
|
slave_detect_next_packet_cnt = 0;
|
|
if (need_autotrigger){
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_audio_slave_detect_next_packet_waitforever_cb);
|
|
}else{
|
|
app_tws_ibrt_audio_analysis_start(0, AUDIO_ANALYSIS_CHECKER_INTERVEL_INVALID);
|
|
app_tws_ibrt_audio_sync_start();
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_ibrt_audio_slave_detect_next_packet_cb);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
int app_bt_stream_detect_next_packet_cb(btif_media_header_t * header, unsigned char *buf, unsigned int len)
|
|
{
|
|
if(app_bt_stream_trigger_onprocess()){
|
|
TRACE_AUD_STREAM_I("[AUTO_SYNC] start");
|
|
app_bt_stream_trigger_start(0);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void app_audio_buffer_check(void)
|
|
{
|
|
bool buffer_check = (APP_AUDIO_BUFFER_SIZE + APP_CAPTURE_AUDIO_BUFFER_SIZE) <= syspool_original_size();
|
|
|
|
TRACE_AUD_STREAM_I("audio buf size[%d] capture buf size[%d] total available space[%d]",
|
|
APP_AUDIO_BUFFER_SIZE, APP_CAPTURE_AUDIO_BUFFER_SIZE, syspool_original_size());
|
|
|
|
ASSERT(buffer_check,
|
|
"Audio buffer[%d]+Capture buffer[%d] exceeds the maximum ram sapce[%d]",
|
|
APP_AUDIO_BUFFER_SIZE, APP_CAPTURE_AUDIO_BUFFER_SIZE, syspool_original_size());
|
|
}
|
|
|
|
static bool isRun = false;
|
|
|
|
int bt_sbc_player(enum PLAYER_OPER_T on, enum APP_SYSFREQ_FREQ_T freq)
|
|
{
|
|
struct AF_STREAM_CONFIG_T stream_cfg;
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
const char *g_log_player_oper_str[] =
|
|
{
|
|
"PLAYER_OPER_START",
|
|
"PLAYER_OPER_STOP",
|
|
"PLAYER_OPER_RESTART",
|
|
};
|
|
|
|
uint8_t* bt_audio_buff = NULL;
|
|
|
|
uint8_t POSSIBLY_UNUSED *bt_eq_buff = NULL;
|
|
uint32_t POSSIBLY_UNUSED eq_buff_size = 0;
|
|
uint8_t POSSIBLY_UNUSED play_samp_size;
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] work:%d op:%s freq:%d :sample:%d \n", isRun, g_log_player_oper_str[on], freq,a2dp_sample_rate);
|
|
|
|
bt_set_playback_triggered(false);
|
|
|
|
if ((isRun && on == PLAYER_OPER_START) || (!isRun && on == PLAYER_OPER_STOP))
|
|
{
|
|
TRACE_AUD_STREAM_W("[A2DP_PLAYER],fail,isRun=%x,on=%x",isRun,on);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
|
|
if (on == PLAYER_OPER_STOP || on == PLAYER_OPER_RESTART)
|
|
{
|
|
#ifdef __THIRDPARTY
|
|
start_by_sbc = false;
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_USE_I2S
|
|
hal_cmu_audio_resample_enable();
|
|
#endif
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
bool isToClearActiveMedia = audio_prompt_clear_pending_stream(PENDING_TO_STOP_A2DP_STREAMING);
|
|
if (isToClearActiveMedia)
|
|
{
|
|
// clear active media mark
|
|
bt_media_clear_media_type(BT_STREAM_SBC, BT_DEVICE_ID_1);
|
|
bt_media_current_sbc_set(BT_DEVICE_NUM);
|
|
}
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
app_bt_stream_ibrt_auto_synchronize_stop();
|
|
app_tws_ibrt_audio_analysis_stop();
|
|
app_tws_ibrt_audio_sync_stop();
|
|
#endif
|
|
|
|
#if (A2DP_DECODER_VER == 2)
|
|
a2dp_audio_stop();
|
|
#endif
|
|
af_codec_set_playback_post_handler(NULL);
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
af_stream_stop(ADJ_MC_STREAM_ID, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
af_stream_stop(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
calib_reset = 1;
|
|
af_stream_dma_tc_irq_disable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
af_stream_dma_tc_irq_disable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
#if defined(__AUDIO_SPECTRUM__)
|
|
audio_spectrum_close();
|
|
#endif
|
|
|
|
audio_process_close();
|
|
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] syspool free size: %d/%d", syspool_free_size(), syspool_total_size());
|
|
|
|
#if !(defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE))
|
|
af_codec_tune(AUD_STREAM_PLAYBACK, 0);
|
|
#endif
|
|
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
af_stream_close(ADJ_MC_STREAM_ID, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
|
|
af_stream_close(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
bt_sbc_mode = 0;
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
app_voicepath_set_stream_state(AUDIO_OUTPUT_STREAMING, false);
|
|
app_voicepath_set_pending_started_stream(AUDIO_OUTPUT_STREAMING, false);
|
|
#endif
|
|
#ifdef AI_AEC_CP_ACCEL
|
|
cp_aec_deinit();
|
|
#endif
|
|
af_set_irq_notification(NULL);
|
|
if (on == PLAYER_OPER_STOP)
|
|
{
|
|
|
|
osThreadId ctrl_thread_id = NULL;
|
|
osPriority ctrl_thread_priority;
|
|
ctrl_thread_id = osThreadGetId();
|
|
ctrl_thread_priority = osThreadGetPriority(ctrl_thread_id);
|
|
osThreadSetPriority(ctrl_thread_id, osPriorityLow);
|
|
app_bt_stream_trigger_checker_stop();
|
|
#ifdef USER_REBOOT_PLAY_MUSIC_AUTO
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] hal_sw_bootmode_clear HAL_SW_BOOTMODE_LOCAL_PLAYER!!!!!!");
|
|
hal_sw_bootmode_clear(HAL_SW_BOOTMODE_LOCAL_PLAYER);
|
|
#endif
|
|
#ifdef __A2DP_PLAYER_USE_BT_TRIGGER__
|
|
app_bt_stream_trigger_deinit();
|
|
#endif
|
|
#ifndef FPGA
|
|
#ifdef BT_XTAL_SYNC
|
|
bt_term_xtal_sync(false);
|
|
#ifndef BT_XTAL_SYNC_NO_RESET
|
|
bt_term_xtal_sync_default();
|
|
#endif
|
|
#endif
|
|
#endif
|
|
a2dp_audio_deinit();
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)&&defined(AUDIO_ANC_FB_ADJ_MC)
|
|
adj_mc_deinit();
|
|
#endif
|
|
app_overlay_unloadall();
|
|
#ifdef __THIRDPARTY
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_STOP2MIC);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_START);
|
|
#endif
|
|
app_sysfreq_req(APP_SYSFREQ_USER_BT_A2DP, APP_SYSFREQ_32K);
|
|
osThreadSetPriority(ctrl_thread_id, ctrl_thread_priority);
|
|
af_set_priority(AF_USER_SBC, osPriorityAboveNormal);
|
|
|
|
#if defined(__AI_VOICE__)||defined(BISTO_ENABLED)
|
|
app_ai_if_inform_music_or_prompt_status(false, 0);
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
app_ibrt_if_exec_sleep_hook_blocker_clr(APP_IBRT_IF_SLEEP_HOOK_BLOCKER_A2DP_STREAMING);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (on == PLAYER_OPER_START || on == PLAYER_OPER_RESTART)
|
|
{
|
|
#if USER_REBOOT_PLAY_MUSIC_AUTO
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] hal_sw_bootmode_set HAL_SW_BOOTMODE_LOCAL_PLAYER!!!!!!");
|
|
hal_sw_bootmode_set(HAL_SW_BOOTMODE_LOCAL_PLAYER);
|
|
#endif
|
|
|
|
#if defined(__AI_VOICE__)||defined(BISTO_ENABLED)
|
|
app_ai_if_inform_music_or_prompt_status(true, a2dp_sample_rate);
|
|
app_ai_if_pre_music_or_prompt_check();
|
|
#endif
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
audio_prompt_stop_playing();
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
app_ibrt_if_exec_sleep_hook_blocker_set(APP_IBRT_IF_SLEEP_HOOK_BLOCKER_A2DP_STREAMING);
|
|
#endif
|
|
#ifdef __THIRDPARTY
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_STOP);
|
|
#endif
|
|
af_set_priority(AF_USER_SBC, osPriorityHigh);
|
|
bt_media_volume_ptr_update_by_mediatype(BT_STREAM_SBC);
|
|
stream_local_volume = btdevice_volume_p->a2dp_vol;
|
|
app_audio_mempool_init_with_specific_size(APP_AUDIO_BUFFER_SIZE);
|
|
|
|
#ifdef __BT_ONE_BRING_TWO__
|
|
if (btif_me_get_activeCons()>1)
|
|
{
|
|
if (freq < APP_SYSFREQ_104M) {
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef __PC_CMD_UART__
|
|
if (freq < APP_SYSFREQ_104M) {
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
#endif
|
|
#if defined(__SW_IIR_EQ_PROCESS__)&&defined(__HW_FIR_EQ_PROCESS__)&&defined(CHIP_BEST1000)
|
|
if (audio_eq_hw_fir_cfg_list[bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_FIR,0)]->len>128)
|
|
{
|
|
if (freq < APP_SYSFREQ_104M)
|
|
{
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(APP_MUSIC_26M) && !defined(__SW_IIR_EQ_PROCESS__)&& !defined(__HW_IIR_EQ_PROCESS__)&& !defined(__HW_FIR_EQ_PROCESS__)
|
|
if (freq < APP_SYSFREQ_26M) {
|
|
freq = APP_SYSFREQ_26M;
|
|
}
|
|
#else
|
|
if (freq < APP_SYSFREQ_52M) {
|
|
freq = APP_SYSFREQ_52M;
|
|
}
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
if (freq < APP_SYSFREQ_104M) {
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] codec_type:%d", codec_type);
|
|
#if defined(A2DP_AAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) {
|
|
if(freq < APP_SYSFREQ_52M) {
|
|
freq = APP_SYSFREQ_52M;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
if(a2dp_sample_rate==44100)
|
|
{
|
|
if(freq < APP_SYSFREQ_78M) {
|
|
freq = APP_SYSFREQ_78M;
|
|
}
|
|
}
|
|
else if(a2dp_sample_rate==96000)
|
|
{
|
|
if (freq < APP_SYSFREQ_208M) {
|
|
freq = APP_SYSFREQ_208M;
|
|
}
|
|
}
|
|
}
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] a2dp_sample_rate=%d",a2dp_sample_rate);
|
|
#endif
|
|
|
|
#if defined(__AUDIO_DRC__) || defined(__AUDIO_DRC2__)
|
|
freq = (freq < APP_SYSFREQ_208M)?APP_SYSFREQ_208M:freq;
|
|
#endif
|
|
|
|
#ifdef AUDIO_OUTPUT_SW_GAIN
|
|
freq = (freq < APP_SYSFREQ_104M)?APP_SYSFREQ_104M:freq;
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
freq = (freq < APP_SYSFREQ_104M)?APP_SYSFREQ_104M:freq;
|
|
#endif
|
|
|
|
#ifdef A2DP_CP_ACCEL
|
|
// Default freq for SBC
|
|
freq = APP_SYSFREQ_26M;
|
|
#if defined(A2DP_AAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC) {
|
|
freq = APP_SYSFREQ_26M;
|
|
}
|
|
#endif
|
|
|
|
#if defined(A2DP_LHDC_ON) || defined(A2DP_SCALABLE_ON) || defined(A2DP_LDAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP){
|
|
freq = APP_SYSFREQ_52M;
|
|
}
|
|
|
|
if (a2dp_sample_rate==AUD_SAMPRATE_96000)
|
|
{
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
#endif
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
if (freq < APP_SYSFREQ_52M) {
|
|
freq = APP_SYSFREQ_52M;
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP){
|
|
if (a2dp_sample_rate==AUD_SAMPRATE_96000 || a2dp_sample_rate==AUD_SAMPRATE_88200)
|
|
{
|
|
freq = APP_SYSFREQ_104M;
|
|
}else
|
|
{
|
|
freq = APP_SYSFREQ_52M;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
freq = APP_SYSFREQ_52M;
|
|
app_sysfreq_req(APP_SYSFREQ_USER_BT_A2DP, freq);
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] sysfreq %d", freq);
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] sysfreq calc : %d\n", hal_sys_timer_calc_cpu_freq(5, 0));
|
|
|
|
if (on == PLAYER_OPER_START)
|
|
{
|
|
af_set_irq_notification(app_bt_stream_playback_irq_notification);
|
|
ASSERT(!app_ring_merge_isrun(), "Ring playback will be abnormal, please check.");
|
|
if (0)
|
|
{
|
|
}
|
|
#if defined(A2DP_AAC_ON)
|
|
else if (codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC)
|
|
{
|
|
app_overlay_select(APP_OVERLAY_A2DP_AAC);
|
|
}
|
|
#endif
|
|
|
|
else if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
TRACE(1,"current_a2dp_non_type %d", current_a2dp_non_type);
|
|
#if defined(A2DP_LHDC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC)
|
|
{
|
|
app_overlay_select(APP_OVERLAY_A2DP_LHDC);
|
|
}
|
|
#endif
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
else if (current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE)
|
|
{
|
|
app_overlay_select(APP_OVERLAY_A2DP_SCALABLE);
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
else if (current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC)
|
|
{
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] ldac overlay select \n"); //toto
|
|
app_overlay_select(APP_OVERLAY_A2DP_LDAC);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
app_overlay_select(APP_OVERLAY_A2DP);
|
|
}
|
|
|
|
#ifdef BT_XTAL_SYNC
|
|
|
|
#ifdef __TWS__
|
|
if(app_tws_mode_is_only_mobile())
|
|
{
|
|
btdrv_rf_bit_offset_track_enable(false);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
btdrv_rf_bit_offset_track_enable(true);
|
|
}
|
|
bt_init_xtal_sync(BT_XTAL_SYNC_MODE_MUSIC, BT_INIT_XTAL_SYNC_MIN, BT_INIT_XTAL_SYNC_MAX, BT_INIT_XTAL_SYNC_FCAP_RANGE);
|
|
#endif // BT_XTAL_SYNC
|
|
#ifdef __THIRDPARTY
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_START2MIC);
|
|
#endif
|
|
|
|
bt_sbc_mode = 1;
|
|
}
|
|
|
|
#ifdef __THIRDPARTY
|
|
//app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_STOP);
|
|
start_by_sbc = true;
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_START);
|
|
#endif
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE)
|
|
sample_rate = AUD_SAMPRATE_50781;
|
|
#else
|
|
sample_rate = a2dp_sample_rate;
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_USE_I2S
|
|
hal_cmu_audio_resample_disable();
|
|
#endif
|
|
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
|
|
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_48000;
|
|
#else
|
|
stream_cfg.sample_rate = sample_rate;
|
|
#endif
|
|
|
|
#ifdef FPGA
|
|
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
|
#else
|
|
#ifdef PLAYBACK_USE_I2S
|
|
stream_cfg.device = AUD_STREAM_USE_I2S0_MASTER;
|
|
#else
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
#endif
|
|
#endif
|
|
#ifdef PLAYBACK_USE_I2S
|
|
stream_cfg.io_path = AUD_IO_PATH_NULL;
|
|
#else
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
#endif
|
|
|
|
stream_cfg.vol = stream_local_volume;
|
|
stream_cfg.handler = bt_sbc_player_more_data;
|
|
|
|
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP){
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if (current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE){
|
|
stream_cfg.data_size = SCALABLE_FRAME_SIZE*8;
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LHDC_ON)
|
|
if (current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC){
|
|
#if defined(A2DP_LHDC_V3)
|
|
if (bt_get_sbc_sample_rate() == AUD_SAMPRATE_96000) {
|
|
stream_cfg.data_size = LHDC_AUDIO_96K_BUFF_SIZE;
|
|
} else {
|
|
stream_cfg.data_size = LHDC_AUDIO_BUFF_SIZE;
|
|
}
|
|
if (a2dp_lhdc_config_llc_get()){
|
|
TRACE_AUD_STREAM_I("[A2DP_PLAYER] USE LHDC_LLC");
|
|
stream_cfg.data_size = LHDC_LLC_AUDIO_BUFF_SIZE;
|
|
}
|
|
#else
|
|
stream_cfg.data_size = LHDC_AUDIO_BUFF_SIZE;
|
|
#endif
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC)
|
|
{
|
|
stream_cfg.data_size = BT_AUDIO_BUFF_SIZE_LDAC;
|
|
}
|
|
#endif
|
|
}else
|
|
|
|
#if defined(A2DP_AAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC){
|
|
stream_cfg.data_size = BT_AUDIO_BUFF_AAC_SIZE;
|
|
}else
|
|
#endif
|
|
{
|
|
if (stream_cfg.sample_rate == AUD_SAMPRATE_44100){
|
|
stream_cfg.data_size = BT_AUDIO_BUFF_SBC_44P1K_SIZE;
|
|
}else{
|
|
stream_cfg.data_size = BT_AUDIO_BUFF_SBC_48K_SIZE;
|
|
}
|
|
}
|
|
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
|
|
#ifdef A2DP_EQ_24BIT
|
|
stream_cfg.data_size *= 2;
|
|
stream_cfg.bits = AUD_BITS_24;
|
|
#elif defined(A2DP_SCALABLE_ON) || defined(A2DP_LHDC_ON) || defined(A2DP_LDAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP) {
|
|
stream_cfg.data_size *= 2;
|
|
stream_cfg.bits = AUD_BITS_24;
|
|
}
|
|
#endif
|
|
|
|
#if 0//defined(A2DP_LHDC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
if(bt_sbc_player_get_sample_bit() == AUD_BITS_16)
|
|
{
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
a2dp_data_buf_size = stream_cfg.data_size;
|
|
|
|
app_audio_mempool_get_buff(&bt_audio_buff, stream_cfg.data_size);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
lowdelay_sample_size_play_bt=stream_cfg.bits;
|
|
lowdelay_sample_rate_play_bt=stream_cfg.sample_rate;
|
|
lowdelay_data_size_play_bt=stream_cfg.data_size;
|
|
lowdelay_playback_ch_num_bt=stream_cfg.channel_num;
|
|
#endif
|
|
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
uint8_t* promptTmpSourcePcmDataBuf;
|
|
uint8_t* promptTmpTargetPcmDataBuf;
|
|
uint8_t* promptPcmDataBuf;
|
|
uint8_t* promptResamplerBuf;
|
|
|
|
app_audio_mempool_get_buff(&promptTmpSourcePcmDataBuf, AUDIO_PROMPT_SOURCE_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptTmpTargetPcmDataBuf, AUDIO_PROMPT_TARGET_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptPcmDataBuf, AUDIO_PROMPT_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptResamplerBuf, AUDIO_PROMPT_BUF_SIZE_FOR_RESAMPLER);
|
|
|
|
audio_prompt_buffer_config(MIX_WITH_A2DP_STREAMING,
|
|
stream_cfg.channel_num,
|
|
stream_cfg.bits,
|
|
promptTmpSourcePcmDataBuf,
|
|
promptTmpTargetPcmDataBuf,
|
|
promptPcmDataBuf,
|
|
AUDIO_PROMPT_PCM_BUFFER_SIZE,
|
|
promptResamplerBuf,
|
|
AUDIO_PROMPT_BUF_SIZE_FOR_RESAMPLER);
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
sample_size_play_bt=stream_cfg.bits;
|
|
sample_rate_play_bt=stream_cfg.sample_rate;
|
|
data_size_play_bt=stream_cfg.data_size;
|
|
playback_buf_bt=stream_cfg.data_ptr;
|
|
playback_size_bt=stream_cfg.data_size;
|
|
if(sample_rate_play_bt==AUD_SAMPRATE_96000)
|
|
{
|
|
playback_samplerate_ratio_bt=4;
|
|
}
|
|
else
|
|
{
|
|
playback_samplerate_ratio_bt=8;
|
|
}
|
|
playback_ch_num_bt=stream_cfg.channel_num;
|
|
mid_p_8_old_l=0;
|
|
mid_p_8_old_r=0;
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
force48k_resample= app_force48k_resample_any_open( stream_cfg.channel_num,
|
|
app_force48k_resample_iter, stream_cfg.data_size / stream_cfg.channel_num,
|
|
(float)sample_rate / AUD_SAMPRATE_48000);
|
|
#endif
|
|
|
|
TRACE(4, "A2DP Playback: sample rate: %d, bits = %d, channel number = %d, data size:%d",
|
|
stream_cfg.sample_rate,
|
|
stream_cfg.bits,
|
|
stream_cfg.channel_num,
|
|
stream_cfg.data_size);
|
|
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
stream_cfg.bits = sample_size_play_bt;
|
|
stream_cfg.channel_num = playback_ch_num_bt;
|
|
stream_cfg.sample_rate = sample_rate_play_bt;
|
|
stream_cfg.device = AUD_STREAM_USE_MC;
|
|
stream_cfg.vol = 0;
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
stream_cfg.handler = audio_adj_mc_data_playback_a2dp;
|
|
#else
|
|
stream_cfg.handler = audio_mc_data_playback_a2dp;
|
|
#endif
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
app_audio_mempool_get_buff(&bt_audio_buff, data_size_play_bt*playback_samplerate_ratio_bt);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
stream_cfg.data_size = data_size_play_bt*playback_samplerate_ratio_bt;
|
|
|
|
playback_buf_mc=stream_cfg.data_ptr;
|
|
playback_size_mc=stream_cfg.data_size;
|
|
|
|
anc_mc_run_init(hal_codec_anc_convert_rate(sample_rate_play_bt));
|
|
|
|
memset(delay_buf_bt,0,sizeof(delay_buf_bt));
|
|
|
|
af_stream_open(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
//ASSERT(ret == 0, "af_stream_open playback failed: %d", ret);
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
adj_mc_capture_sample_rate = sample_rate_play_bt / 3;
|
|
adj_mc_init(ADJ_MC_FRAME_LEN);
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)ADJ_MC_CHANNEL_NUM;
|
|
stream_cfg.data_size = ADJ_MC_BUF_SIZE;
|
|
stream_cfg.sample_rate = (enum AUD_SAMPRATE_T)adj_mc_capture_sample_rate;
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
stream_cfg.vol = 12;
|
|
stream_cfg.chan_sep_buf = true;
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
stream_cfg.io_path = AUD_INPUT_PATH_ASRMIC;
|
|
stream_cfg.handler = adj_mc_filter_estimate;
|
|
stream_cfg.data_ptr = adj_mc_buf;
|
|
TRACE(2,"[A2DP_PLAYER] capture sample_rate:%d, data_size:%d",stream_cfg.sample_rate,stream_cfg.data_size);
|
|
af_stream_open(ADJ_MC_STREAM_ID, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef A2DP_STREAM_AUDIO_DUMP
|
|
audio_dump_init(1024, sizeof(int), 1);
|
|
#endif
|
|
|
|
#ifdef __HEAR_THRU_PEAK_DET__
|
|
PEAK_DETECTOR_CFG_T peak_detector_cfg;
|
|
peak_detector_cfg.fs = stream_cfg.sample_rate;
|
|
peak_detector_cfg.bits = stream_cfg.bits;
|
|
peak_detector_cfg.factor_up = 0.6;
|
|
peak_detector_cfg.factor_down = 2.0;
|
|
peak_detector_cfg.reduce_dB = -30;
|
|
peak_detector_init();
|
|
peak_detector_setup(&peak_detector_cfg);
|
|
#endif
|
|
|
|
#if defined(__AUDIO_SPECTRUM__)
|
|
audio_spectrum_open(stream_cfg.sample_rate, stream_cfg.bits);
|
|
#endif
|
|
|
|
#if defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
|
|
eq_buff_size = stream_cfg.data_size*2;
|
|
#elif defined(__HW_FIR_EQ_PROCESS__) && !defined(__HW_IIR_EQ_PROCESS__)
|
|
|
|
play_samp_size = (stream_cfg.bits <= AUD_BITS_16) ? 2 : 4;
|
|
#if defined(CHIP_BEST2000)
|
|
eq_buff_size = stream_cfg.data_size * sizeof(int32_t) / play_samp_size;
|
|
#elif defined(CHIP_BEST1000)
|
|
eq_buff_size = stream_cfg.data_size * sizeof(int16_t) / play_samp_size;
|
|
#elif defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)
|
|
eq_buff_size = stream_cfg.data_size;
|
|
#endif
|
|
#elif !defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
|
|
eq_buff_size = stream_cfg.data_size;
|
|
#else
|
|
eq_buff_size = 0;
|
|
bt_eq_buff = NULL;
|
|
#endif
|
|
|
|
if(eq_buff_size > 0)
|
|
{
|
|
app_audio_mempool_get_buff(&bt_eq_buff, eq_buff_size);
|
|
}
|
|
|
|
#if defined(IBRT)
|
|
enum AUD_CHANNEL_NUM_T sw_ch_num = AUD_CHANNEL_NUM_1;
|
|
#else
|
|
enum AUD_CHANNEL_NUM_T sw_ch_num = stream_cfg.channel_num;
|
|
#endif
|
|
|
|
audio_process_open(stream_cfg.sample_rate, stream_cfg.bits, sw_ch_num, stream_cfg.channel_num, stream_cfg.data_size/stream_cfg.channel_num/(stream_cfg.bits <= AUD_BITS_16 ? 2 : 4)/2, bt_eq_buff, eq_buff_size);
|
|
|
|
// disable audio eq config on a2dp start for audio tuning tools
|
|
#ifndef __PC_CMD_UART__
|
|
#ifdef __SW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_SW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_SW_IIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_FIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_FIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_FIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_DAC_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_DAC_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_DAC_IIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_IIR,0));
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
anc_status_record = 0xff;
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
APP_TWS_IBRT_AUDIO_SYNC_CFG_T sync_config;
|
|
sync_config.factor_reference = TWS_IBRT_AUDIO_SYNC_FACTOR_REFERENCE;
|
|
sync_config.factor_fast_limit = TWS_IBRT_AUDIO_SYNC_FACTOR_FAST_LIMIT;
|
|
sync_config.factor_slow_limit = TWS_IBRT_AUDIO_SYNC_FACTOR_SLOW_LIMIT;;
|
|
sync_config.dead_zone_us = TWS_IBRT_AUDIO_SYNC_DEAD_ZONE_US;
|
|
app_tws_ibrt_audio_sync_reconfig(&sync_config);
|
|
#else
|
|
#if !(defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE))
|
|
af_codec_tune(AUD_STREAM_PLAYBACK, 0);
|
|
#endif
|
|
#endif
|
|
if (on == PLAYER_OPER_START)
|
|
{
|
|
// This might use all of the rest buffer in the mempool,
|
|
// so it must be the last configuration before starting stream.
|
|
#if (A2DP_DECODER_VER == 2)
|
|
A2DP_AUDIO_OUTPUT_CONFIG_T output_config;
|
|
A2DP_AUDIO_CODEC_TYPE a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_SBC;
|
|
output_config.sample_rate = sample_rate;
|
|
output_config.num_channels = 2;
|
|
#ifdef A2DP_EQ_24BIT
|
|
output_config.bits_depth = 24;
|
|
#else
|
|
output_config.bits_depth = 16;
|
|
#endif
|
|
output_config.frame_samples = app_bt_stream_get_dma_buffer_samples()/2;
|
|
output_config.factor_reference = 1.0f;
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
float dest_packet_mut = 0;
|
|
int need_autotrigger = a2dp_ibrt_stream_need_autotrigger_getandclean_flag();
|
|
|
|
uint32_t offset_mut = 0;
|
|
switch (codec_type)
|
|
{
|
|
case BTIF_AVDTP_CODEC_TYPE_SBC:
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_SBC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU;
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
offset_mut = A2DP_PLAYER_PLAYBACK_DELAY_SBC_FRAME_MTU * A2DP_PLAYER_PLAYBACK_WATER_LINE;
|
|
#endif
|
|
break;
|
|
case BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC:
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_MPEG2_4_AAC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU;
|
|
#ifdef A2DP_PLAYER_PLAYBACK_WATER_LINE
|
|
offset_mut = A2DP_PLAYER_PLAYBACK_WATER_LINE;
|
|
#endif
|
|
break;
|
|
case BTIF_AVDTP_CODEC_TYPE_NON_A2DP:
|
|
#if defined(A2DP_LHDC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_LHDC;
|
|
if (a2dp_lhdc_config_llc_get()){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU;
|
|
}else if (sample_rate > AUD_SAMPRATE_48000){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU;
|
|
}else{
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_LDAC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_SCALABL;
|
|
if (sample_rate > AUD_SAMPRATE_48000){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_MTU;
|
|
}else{
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_MTU;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
output_config.factor_reference = TWS_IBRT_AUDIO_SYNC_FACTOR_REFERENCE;
|
|
#if defined(A2DP_LHDC_ON) || defined(A2DP_SCALABLE_ON) || defined(A2DP_LDAC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
if(bt_sbc_player_get_sample_bit() == AUD_BITS_16)
|
|
{
|
|
output_config.curr_bits = AUD_BITS_16;
|
|
}
|
|
else
|
|
{
|
|
output_config.curr_bits = AUD_BITS_24;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
dest_packet_mut *= a2dp_audio_latency_factor_get();
|
|
A2DP_AUDIO_CHANNEL_SELECT_E a2dp_audio_channel_sel = A2DP_AUDIO_CHANNEL_SELECT_STEREO;
|
|
switch ((AUDIO_CHANNEL_SELECT_E)p_ibrt_ctrl->audio_chnl_sel)
|
|
{
|
|
case AUDIO_CHANNEL_SELECT_STEREO:
|
|
a2dp_audio_channel_sel = A2DP_AUDIO_CHANNEL_SELECT_STEREO;
|
|
break;
|
|
case AUDIO_CHANNEL_SELECT_LRMERGE:
|
|
a2dp_audio_channel_sel = A2DP_AUDIO_CHANNEL_SELECT_LRMERGE;
|
|
break;
|
|
case AUDIO_CHANNEL_SELECT_LCHNL:
|
|
a2dp_audio_channel_sel = A2DP_AUDIO_CHANNEL_SELECT_LCHNL;
|
|
break;
|
|
case AUDIO_CHANNEL_SELECT_RCHNL:
|
|
a2dp_audio_channel_sel = A2DP_AUDIO_CHANNEL_SELECT_RCHNL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
dest_packet_mut += offset_mut;
|
|
a2dp_audio_init(freq, a2dp_audio_codec_type, &output_config, a2dp_audio_channel_sel, (uint16_t)dest_packet_mut);
|
|
|
|
app_tws_ibrt_audio_analysis_interval_set(sample_rate > AUD_SAMPRATE_48000 ? AUDIO_ANALYSIS_INTERVAL*2 : AUDIO_ANALYSIS_INTERVAL);
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
app_tws_ibrt_audio_analysis_start(0, AUDIO_ANALYSIS_CHECKER_INTERVEL_INVALID);
|
|
app_tws_ibrt_audio_sync_start();
|
|
app_bt_stream_ibrt_audio_master_detect_next_packet_start();
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
app_bt_stream_ibrt_audio_slave_detect_next_packet_start(need_autotrigger);
|
|
}else{
|
|
TRACE_AUD_STREAM_E("[A2DP_PLAYER] mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
uint16_t dest_packet_mut = 0;
|
|
|
|
switch (codec_type)
|
|
{
|
|
case BTIF_AVDTP_CODEC_TYPE_SBC:
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_SBC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SBC_MTU;
|
|
break;
|
|
case BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC:
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_MPEG2_4_AAC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_AAC_MTU;
|
|
break;
|
|
case BTIF_AVDTP_CODEC_TYPE_NON_A2DP:
|
|
#if defined(A2DP_LHDC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LHDC)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_LHDC;
|
|
if (a2dp_lhdc_config_llc_get()){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_LLC_MTU;
|
|
}else if (sample_rate > AUD_SAMPRATE_48000){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_HIRES_MTU;
|
|
}else{
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LHDC_BASERES_MTU;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(A2DP_LDAC_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_LDAC)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_LDAC;
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_LDAC_MTU;
|
|
}
|
|
#endif
|
|
#if defined(A2DP_SCALABLE_ON)
|
|
if(current_a2dp_non_type == A2DP_NON_CODEC_TYPE_SCALABLE)
|
|
{
|
|
a2dp_audio_codec_type = A2DP_AUDIO_CODEC_TYPE_SCALABL;
|
|
if (sample_rate > AUD_SAMPRATE_48000){
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_HIRES_MTU;
|
|
}else{
|
|
dest_packet_mut = A2DP_PLAYER_PLAYBACK_DELAY_SCALABLE_BASERES_MTU;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
if(bt_sbc_player_get_sample_bit() == AUD_BITS_16)
|
|
{
|
|
output_config.curr_bits = AUD_BITS_16;
|
|
}
|
|
else
|
|
{
|
|
output_config.curr_bits = AUD_BITS_24;
|
|
}
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#if defined(A2DP_LHDC_ON)
|
|
if (codec_type == BTIF_AVDTP_CODEC_TYPE_NON_A2DP)
|
|
{
|
|
if(bt_sbc_player_get_sample_bit() == AUD_BITS_16)
|
|
{
|
|
output_config.curr_bits = AUD_BITS_16;
|
|
}
|
|
else
|
|
{
|
|
output_config.curr_bits = AUD_BITS_24;
|
|
}
|
|
}
|
|
#endif
|
|
a2dp_audio_init(freq,a2dp_audio_codec_type, &output_config, A2DP_AUDIO_CHANNEL_SELECT_STEREO, dest_packet_mut);
|
|
a2dp_audio_detect_next_packet_callback_register(app_bt_stream_detect_next_packet_cb);
|
|
#endif
|
|
a2dp_audio_start();
|
|
#else
|
|
a2dp_audio_init();
|
|
#endif
|
|
}
|
|
|
|
|
|
#if defined(MUSIC_DELAY_CONTROL) && (defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)|| defined(CHIP_BEST1400)|| defined(CHIP_BEST1402))
|
|
calib_reset = 1;
|
|
#endif
|
|
af_stream_dma_tc_irq_enable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_codec_set_playback_post_handler(bt_sbc_player_playback_post_handler);
|
|
#ifdef __A2DP_PLAYER_USE_BT_TRIGGER__
|
|
app_bt_stream_trigger_init();
|
|
#endif
|
|
#ifdef VOICE_DATAPATH
|
|
if (app_voicepath_get_stream_state(VOICEPATH_STREAMING))
|
|
{
|
|
app_voicepath_set_pending_started_stream(AUDIO_OUTPUT_STREAMING, true);
|
|
}
|
|
else
|
|
{
|
|
app_voicepath_set_stream_state(AUDIO_OUTPUT_STREAMING, true);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
}
|
|
#else
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
#ifdef AI_AEC_CP_ACCEL
|
|
cp_aec_init();
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_start(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#ifdef AUDIO_ANC_FB_ADJ_MC
|
|
af_stream_start(ADJ_MC_STREAM_ID, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __THIRDPARTY
|
|
//app_thirdparty_specific_lib_event_handle(THIRDPARTY_ID_NO1,THIRDPARTY_OTHER_EVENT);
|
|
#endif
|
|
app_bt_stream_trigger_checker_start();
|
|
}
|
|
|
|
isRun = (on != PLAYER_OPER_STOP);
|
|
return 0;
|
|
}
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
static uint32_t sco_trigger_wait_codecpcm = 0;
|
|
static uint32_t sco_trigger_wait_btpcm = 0;
|
|
void app_bt_stream_sco_trigger_set_codecpcm_triggle(uint8_t triggle_en)
|
|
{
|
|
sco_trigger_wait_codecpcm = triggle_en;
|
|
}
|
|
|
|
uint32_t app_bt_stream_sco_trigger_wait_codecpcm_triggle(void)
|
|
{
|
|
return sco_trigger_wait_codecpcm;
|
|
}
|
|
|
|
void app_bt_stream_sco_trigger_set_btpcm_triggle(uint32_t triggle_en)
|
|
{
|
|
sco_trigger_wait_btpcm = triggle_en;
|
|
}
|
|
|
|
uint32_t app_bt_stream_sco_trigger_wait_btpcm_triggle(void)
|
|
{
|
|
return sco_trigger_wait_btpcm;
|
|
}
|
|
|
|
int app_bt_stream_sco_trigger_codecpcm_tick(void)
|
|
{
|
|
if(app_bt_stream_sco_trigger_wait_codecpcm_triggle()){
|
|
app_bt_stream_sco_trigger_set_codecpcm_triggle(0);
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] codecpcm_tick:%x/%x", btdrv_syn_get_curr_ticks(), bt_syn_get_curr_ticks(p_ibrt_ctrl->mobile_conhandle));
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] codecpcm_tick:%x/%x", btdrv_syn_get_curr_ticks(), bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle));
|
|
}else{
|
|
TRACE_AUD_STREAM_E("[SCO_PLAYER] codecpcm_tick mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
uint16_t conhdl = 0xFFFF;
|
|
int curr_sco;
|
|
|
|
curr_sco = app_audio_manager_get_active_sco_num();
|
|
if (curr_sco != BT_DEVICE_NUM)
|
|
{
|
|
conhdl = btif_hf_get_remote_hci_handle(*app_audio_manager_get_active_sco_chnl());
|
|
}
|
|
if (conhdl != 0xFFFF){
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] codecpcm_tick:%x", bt_syn_get_curr_ticks(conhdl));
|
|
}
|
|
#endif
|
|
btdrv_syn_clr_trigger();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_sco_trigger_btpcm_tick(void)
|
|
{
|
|
if(app_bt_stream_sco_trigger_wait_btpcm_triggle()){
|
|
app_bt_stream_sco_trigger_set_btpcm_triggle(0);
|
|
btdrv_set_bt_pcm_triggler_en(0);
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] btpcm_tick:%x/%x", btdrv_syn_get_curr_ticks(), bt_syn_get_curr_ticks(p_ibrt_ctrl->mobile_conhandle));
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] btpcm_tick:tick:%x/%x", btdrv_syn_get_curr_ticks(), bt_syn_get_curr_ticks(p_ibrt_ctrl->ibrt_conhandle));
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] btpcm_tick: mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
uint16_t conhdl = 0xFFFF;
|
|
int curr_sco;
|
|
|
|
curr_sco = app_audio_manager_get_active_sco_num();
|
|
if (curr_sco != BT_DEVICE_NUM)
|
|
{
|
|
conhdl = btif_hf_get_remote_hci_handle(*app_audio_manager_get_active_sco_chnl());
|
|
}
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] btpcm_tick:%x", bt_syn_get_curr_ticks(conhdl));
|
|
#endif
|
|
btdrv_syn_clr_trigger();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void app_bt_stream_sco_trigger_btpcm_start(void )
|
|
{
|
|
uint32_t curr_ticks = 0;
|
|
uint32_t tg_acl_trigger_offset_time = 0;
|
|
uint16_t conhdl = 0xFFFF;
|
|
|
|
uint32_t lock;
|
|
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
conhdl = p_ibrt_ctrl->mobile_conhandle;
|
|
#ifdef __SW_TRIG__
|
|
btdrv_sync_sw_trig_store_conhdl(p_ibrt_ctrl->mobile_conhandle);
|
|
#endif
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
conhdl = p_ibrt_ctrl->ibrt_conhandle;
|
|
#ifdef __SW_TRIG__
|
|
btdrv_sync_sw_trig_store_conhdl(p_ibrt_ctrl->ibrt_conhandle);
|
|
#endif
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr mobile:%d %04x ibrt:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
int curr_sco;
|
|
curr_sco = app_audio_manager_get_active_sco_num();
|
|
if (curr_sco != BT_DEVICE_NUM)
|
|
{
|
|
conhdl = btif_hf_get_remote_hci_handle(*app_audio_manager_get_active_sco_chnl());
|
|
}
|
|
#endif
|
|
|
|
lock = int_lock();
|
|
curr_ticks = bt_syn_get_curr_ticks(conhdl);
|
|
|
|
tg_acl_trigger_offset_time = (curr_ticks+0x180) - ((curr_ticks+0x180)%192);
|
|
|
|
btdrv_set_bt_pcm_triggler_en(0);
|
|
btdrv_set_bt_pcm_en(0);
|
|
btdrv_syn_clr_trigger();
|
|
btdrv_enable_playback_triggler(SCO_TRIGGLE_MODE);
|
|
|
|
#if defined(IBRT)
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, p_ibrt_ctrl->mobile_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr set ticks:%d,",tg_acl_trigger_offset_time);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, p_ibrt_ctrl->ibrt_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr set ticks:%d,",tg_acl_trigger_offset_time);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr mobile:%d %04x ibrt:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr get ticks:%d,",curr_ticks);
|
|
|
|
#else
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, conhdl, BT_TRIG_SLAVE_ROLE);
|
|
#endif
|
|
btdrv_set_bt_pcm_triggler_en(1);
|
|
btdrv_set_bt_pcm_en(1);
|
|
app_bt_stream_sco_trigger_set_btpcm_triggle(1);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] btpcm_startr curr:%x, trig:%x, curr:%x",
|
|
btdrv_syn_get_curr_ticks(),
|
|
tg_acl_trigger_offset_time,
|
|
bt_syn_get_curr_ticks(conhdl));
|
|
int_unlock(lock);
|
|
}
|
|
|
|
void app_bt_stream_sco_trigger_btpcm_stop(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
#define TIRG_DELAY_THRESHOLD_325US (15) //total:TIRG_DELAY_THRESHOLD_325US*325us
|
|
#define TIRG_DELAY_MAX (20) //total:20*TIRG_DELAY_325US*325us
|
|
|
|
#define TIRG_DELAY_325US (96) //total:TIRG_DELAY_325US*325us It' up to the codec and bt pcm pingpang buffer.
|
|
|
|
void app_bt_stream_sco_trigger_codecpcm_start(uint32_t btclk, uint16_t btcnt )
|
|
{
|
|
uint32_t curr_ticks = 0;
|
|
uint32_t tg_acl_trigger_offset_time = 0;
|
|
uint32_t lock;
|
|
uint16_t conhdl = 0xFFFF;
|
|
//must lock the interrupts when set trig ticks.
|
|
|
|
#if defined(IBRT)
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
conhdl = p_ibrt_ctrl->mobile_conhandle;
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
conhdl = p_ibrt_ctrl->ibrt_conhandle;
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] codecpcm_start mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
int curr_sco;
|
|
curr_sco = app_audio_manager_get_active_sco_num();
|
|
if (curr_sco != BT_DEVICE_NUM)
|
|
{
|
|
conhdl = btif_hf_get_remote_hci_handle(*app_audio_manager_get_active_sco_chnl());
|
|
}
|
|
#endif
|
|
|
|
lock = int_lock();
|
|
curr_ticks = bt_syn_get_curr_ticks(conhdl);
|
|
TRACE_AUD_STREAM_I("[[STRM_TRIG][SCO] codecpcm_start 1 curr:%d clk:%dcnt:%d", curr_ticks,btclk,btcnt);
|
|
#ifdef LOW_DELAY_SCO
|
|
tg_acl_trigger_offset_time=btclk+12+MASTER_MOBILE_BTCLK_OFFSET;
|
|
#else
|
|
tg_acl_trigger_offset_time=btclk+24+MASTER_MOBILE_BTCLK_OFFSET;
|
|
#endif
|
|
|
|
tg_acl_trigger_offset_time = tg_acl_trigger_offset_time * 2;
|
|
if(tg_acl_trigger_offset_time<curr_ticks+TIRG_DELAY_THRESHOLD_325US)
|
|
{
|
|
int tirg_delay=0;
|
|
tirg_delay=((curr_ticks+TIRG_DELAY_THRESHOLD_325US)-tg_acl_trigger_offset_time)/TIRG_DELAY_325US;
|
|
tirg_delay=tirg_delay+1;
|
|
if(tirg_delay>TIRG_DELAY_MAX)
|
|
{
|
|
tirg_delay=TIRG_DELAY_MAX;
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][SCO] codecpcm_start bt clk convolution!");
|
|
}
|
|
tg_acl_trigger_offset_time=tg_acl_trigger_offset_time+tirg_delay*TIRG_DELAY_325US;
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][SCO] codecpcm_start need more tirg_delay:%d offset:%d curr:%d,",tirg_delay,tg_acl_trigger_offset_time,curr_ticks);
|
|
}
|
|
tg_acl_trigger_offset_time &= 0x0fffffff;
|
|
|
|
btdrv_syn_trigger_codec_en(0);
|
|
// af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false);
|
|
// af_codec_sync_config(AUD_STREAM_CAPTURE, AF_CODEC_SYNC_TYPE_BT, false);
|
|
btdrv_syn_clr_trigger();
|
|
|
|
|
|
#if defined(IBRT)
|
|
if (app_tws_ibrt_mobile_link_connected()){
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, p_ibrt_ctrl->mobile_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] codecpcm_start set 2 offset:%d",tg_acl_trigger_offset_time);
|
|
}else if (app_tws_ibrt_slave_ibrt_link_connected()){
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, p_ibrt_ctrl->ibrt_conhandle, BT_TRIG_SLAVE_ROLE);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] codecpcm_start set 2 offset:%d",tg_acl_trigger_offset_time);
|
|
}else{
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] codecpcm_start mobile_link:%d %04x ibrt_link:%d %04x", app_tws_ibrt_mobile_link_connected(), p_ibrt_ctrl->mobile_conhandle,
|
|
app_tws_ibrt_slave_ibrt_link_connected(), p_ibrt_ctrl->ibrt_conhandle);
|
|
}
|
|
#else
|
|
bt_syn_set_tg_ticks(tg_acl_trigger_offset_time, conhdl, BT_TRIG_SLAVE_ROLE);
|
|
#endif
|
|
btdrv_syn_trigger_codec_en(1);
|
|
app_bt_stream_sco_trigger_set_codecpcm_triggle(1);
|
|
|
|
btdrv_enable_playback_triggler(ACL_TRIGGLE_MODE);
|
|
|
|
int_unlock(lock);
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] codecpcm_start enable curr:%x trig:%x curr:%x",
|
|
btdrv_syn_get_curr_ticks(),
|
|
tg_acl_trigger_offset_time,
|
|
curr_ticks);
|
|
|
|
|
|
|
|
// af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, true);
|
|
// af_codec_sync_config(AUD_STREAM_CAPTURE, AF_CODEC_SYNC_TYPE_BT, true);
|
|
|
|
|
|
}
|
|
|
|
void app_bt_stream_sco_trigger_codecpcm_stop(void)
|
|
{
|
|
#ifdef PLAYBACK_USE_I2S
|
|
af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, false);
|
|
#else
|
|
af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, false);
|
|
#endif
|
|
af_codec_sync_config(AUD_STREAM_CAPTURE, AF_CODEC_SYNC_TYPE_BT, false);
|
|
}
|
|
#endif
|
|
|
|
void speech_tx_aec_set_frame_len(int len);
|
|
int voicebtpcm_pcm_echo_buf_queue_init(uint32_t size);
|
|
void voicebtpcm_pcm_echo_buf_queue_reset(void);
|
|
void voicebtpcm_pcm_echo_buf_queue_deinit(void);
|
|
int voicebtpcm_pcm_audio_init(int sco_sample_rate, int codec_sample_rate);
|
|
int voicebtpcm_pcm_audio_deinit(void);
|
|
uint32_t voicebtpcm_pcm_audio_data_come(uint8_t *buf, uint32_t len);
|
|
uint32_t voicebtpcm_pcm_audio_more_data(uint8_t *buf, uint32_t len);
|
|
int store_voicebtpcm_m2p_buffer(unsigned char *buf, unsigned int len);
|
|
int get_voicebtpcm_p2m_frame(unsigned char *buf, unsigned int len);
|
|
static uint32_t mic_force_mute = 0;
|
|
static uint32_t spk_force_mute = 0;
|
|
static uint32_t bt_sco_player_code_type = 0;
|
|
|
|
static enum AUD_CHANNEL_NUM_T sco_play_chan_num;
|
|
static enum AUD_CHANNEL_NUM_T sco_cap_chan_num;
|
|
|
|
bool bt_sco_codec_is_msbc(void)
|
|
{
|
|
bool en = false;
|
|
#ifdef HFP_1_6_ENABLE
|
|
if (app_audio_manager_get_scocodecid() == BTIF_HF_SCO_CODEC_MSBC)
|
|
{
|
|
en = true;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
en = false;
|
|
}
|
|
|
|
return en;
|
|
}
|
|
|
|
void bt_sco_mobile_clkcnt_get(uint32_t btclk, uint16_t btcnt,
|
|
uint32_t *mobile_master_clk, uint16_t *mobile_master_cnt)
|
|
{
|
|
#if defined(IBRT)
|
|
app_tws_ibrt_audio_mobile_clkcnt_get(btclk, btcnt, mobile_master_clk, mobile_master_cnt);
|
|
#else
|
|
uint16_t conhdl = 0xFFFF;
|
|
int32_t clock_offset;
|
|
uint16_t bit_offset;
|
|
int curr_sco;
|
|
|
|
curr_sco = app_audio_manager_get_active_sco_num();
|
|
if (curr_sco != BT_DEVICE_NUM){
|
|
conhdl = btif_hf_get_remote_hci_handle(*app_audio_manager_get_active_sco_chnl());
|
|
}
|
|
|
|
if (conhdl != 0xFFFF){
|
|
bt_drv_reg_op_piconet_clk_offset_get(conhdl, &clock_offset, &bit_offset);
|
|
//TRACE_AUD_STREAM_I("mobile piconet clk:%d bit:%d loc clk:%d cnt:%d", clock_offset, bit_offset, btclk, btcnt);
|
|
btdrv_slave2master_clkcnt_convert(btclk, btcnt,
|
|
clock_offset, bit_offset,
|
|
mobile_master_clk, mobile_master_cnt);
|
|
}else{
|
|
TRACE_AUD_STREAM_W("[STRM_TRIG][SCO] mobile_clkcnt_get warning conhdl NULL conhdl:%x", conhdl);
|
|
*mobile_master_clk = 0;
|
|
*mobile_master_cnt = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
|
|
#ifdef CHIP_BEST1000
|
|
#error "Unsupport SW_SCO_RESAMPLE on best1000 by now"
|
|
#endif
|
|
#ifdef NO_SCO_RESAMPLE
|
|
#error "Conflicted config: NO_SCO_RESAMPLE and SW_SCO_RESAMPLE"
|
|
#endif
|
|
|
|
// The decoded playback data in the first irq is output to DAC after the second irq (PING-PONG buffer)
|
|
#define SCO_PLAY_RESAMPLE_ALIGN_CNT 2
|
|
|
|
static uint8_t sco_play_irq_cnt;
|
|
static bool sco_dma_buf_err;
|
|
static struct APP_RESAMPLE_T *sco_capture_resample;
|
|
static struct APP_RESAMPLE_T *sco_playback_resample;
|
|
|
|
static int bt_sco_capture_resample_iter(uint8_t *buf, uint32_t len)
|
|
{
|
|
voicebtpcm_pcm_audio_data_come(buf, len);
|
|
return 0;
|
|
}
|
|
|
|
static int bt_sco_playback_resample_iter(uint8_t *buf, uint32_t len)
|
|
{
|
|
voicebtpcm_pcm_audio_more_data(buf, len);
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
extern int process_downlink_bt_voice_frames(uint8_t *in_buf, uint32_t in_len, uint8_t *out_buf,uint32_t out_len,int32_t codec_type);
|
|
extern int process_uplink_bt_voice_frames(uint8_t *in_buf, uint32_t in_len, uint8_t *ref_buf, uint32_t ref_len, uint8_t *out_buf,uint32_t out_len,int32_t codec_type);
|
|
#define MSBC_FRAME_LEN (60)
|
|
#define PCM_LEN_PER_FRAME (240)
|
|
#define CAL_FRAME_NUM (22)
|
|
|
|
static void bt_sco_codec_tuning(void)
|
|
{
|
|
uint32_t btclk;
|
|
uint16_t btcnt;
|
|
|
|
uint32_t mobile_master_clk;
|
|
uint16_t mobile_master_cnt;
|
|
|
|
uint32_t mobile_master_clk_offset;
|
|
int32_t mobile_master_cnt_offset;
|
|
|
|
static float fre_offset=0.0f;
|
|
static int32_t mobile_master_cnt_offset_init;
|
|
static int32_t mobile_master_cnt_offset_old;
|
|
static uint32_t first_proc_flag=0;
|
|
#if defined( __AUDIO_RESAMPLE__) && !defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
static uint32_t frame_counter=0;
|
|
static int32_t mobile_master_cnt_offset_max=0;
|
|
static int32_t mobile_master_cnt_offset_min=0;
|
|
static int32_t mobile_master_cnt_offset_resample=0;
|
|
|
|
int32_t offset_max=0;
|
|
int32_t offset_min=0;
|
|
#endif
|
|
|
|
bt_drv_reg_op_dma_tc_clkcnt_get(&btclk, &btcnt);
|
|
bt_sco_mobile_clkcnt_get(btclk, btcnt,
|
|
&mobile_master_clk, &mobile_master_cnt);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune btclk:%d,btcnt:%d,",mobile_master_clk,mobile_master_cnt);
|
|
#endif
|
|
|
|
mobile_master_clk_offset=(mobile_master_clk-mobile_master_clk_offset_init)%12;
|
|
mobile_master_cnt_offset=mobile_master_clk_offset*625+(625-mobile_master_cnt);
|
|
mobile_master_cnt_offset=mobile_master_cnt_offset-(MASTER_MOBILE_BTCNT_OFFSET+mobile_master_cnt_offset_init);
|
|
|
|
if(app_bt_stream_sco_trigger_codecpcm_tick())
|
|
{
|
|
fre_offset=0.0f;
|
|
if(mobile_master_clk_offset<MASTER_MOBILE_BTCLK_OFFSET)
|
|
{
|
|
mobile_master_cnt_offset_init=-mobile_master_cnt;
|
|
}
|
|
else
|
|
{
|
|
mobile_master_cnt_offset_init=625-mobile_master_cnt;
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune first_cnt:%d offset_init:%d,",mobile_master_cnt,mobile_master_cnt_offset_init);
|
|
|
|
if(playback_samplerate_codecpcm==AUD_SAMPRATE_16000)
|
|
{
|
|
#ifdef ANC_APP
|
|
mobile_master_cnt_offset_init=-232;
|
|
#else
|
|
#if defined( __AUDIO_RESAMPLE__)
|
|
if (hal_cmu_get_audio_resample_status())
|
|
{
|
|
#if defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
mobile_master_cnt_offset_init=171;
|
|
#else
|
|
mobile_master_cnt_offset_init=146;
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
mobile_master_cnt_offset_init=113;
|
|
}
|
|
#endif
|
|
}
|
|
else if(playback_samplerate_codecpcm==AUD_SAMPRATE_8000)
|
|
{
|
|
#ifdef ANC_APP
|
|
mobile_master_cnt_offset_init=-512;
|
|
#else
|
|
#if defined( __AUDIO_RESAMPLE__)
|
|
if (hal_cmu_get_audio_resample_status())
|
|
{
|
|
#if defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
mobile_master_cnt_offset_init=-270;
|
|
#else
|
|
mobile_master_cnt_offset_init=-327;
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
mobile_master_cnt_offset_init=-386;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if defined( __AUDIO_RESAMPLE__) && !defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
mobile_master_cnt_offset=mobile_master_clk_offset*625+(625-mobile_master_cnt);
|
|
mobile_master_cnt_offset=mobile_master_cnt_offset-(MASTER_MOBILE_BTCNT_OFFSET+mobile_master_cnt_offset_init);
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune mobile_master_cnt_offset:%d,",mobile_master_cnt_offset);
|
|
#ifdef LOW_DELAY_SCO
|
|
fre_offset=(float)mobile_master_cnt_offset/(CAL_FRAME_NUM*7.5f*1000.0f);
|
|
#else
|
|
fre_offset=(float)mobile_master_cnt_offset/(CAL_FRAME_NUM*15.0f*1000.0f);
|
|
#endif
|
|
first_proc_flag=0;
|
|
#endif
|
|
|
|
#if defined( __AUDIO_RESAMPLE__) && !defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
if (hal_cmu_get_audio_resample_status())
|
|
{
|
|
frame_counter=0;
|
|
mobile_master_cnt_offset_max=0;
|
|
mobile_master_cnt_offset_min=0;
|
|
mobile_master_cnt_offset_resample=0;
|
|
}
|
|
#endif
|
|
mobile_master_cnt_offset=0;
|
|
mobile_master_cnt_offset_old=0;
|
|
}
|
|
|
|
|
|
#if defined( __AUDIO_RESAMPLE__) &&!defined(SW_PLAYBACK_RESAMPLE)&& !defined(AUDIO_RESAMPLE_ANTI_DITHER)
|
|
if (hal_cmu_get_audio_resample_status())
|
|
{
|
|
if(playback_samplerate_codecpcm==AUD_SAMPRATE_16000)
|
|
{
|
|
offset_max=28;
|
|
offset_min=-33;
|
|
}
|
|
else if(playback_samplerate_codecpcm==AUD_SAMPRATE_8000)
|
|
{
|
|
offset_max=12;
|
|
offset_min=-112;
|
|
}
|
|
|
|
if(mobile_master_cnt_offset>mobile_master_cnt_offset_max)
|
|
{
|
|
mobile_master_cnt_offset_max=mobile_master_cnt_offset;
|
|
}
|
|
|
|
if(mobile_master_cnt_offset<mobile_master_cnt_offset_min)
|
|
{
|
|
mobile_master_cnt_offset_min=mobile_master_cnt_offset;
|
|
}
|
|
|
|
frame_counter++;
|
|
|
|
if(frame_counter>=CAL_FRAME_NUM)
|
|
{
|
|
if(mobile_master_cnt_offset_min<offset_min)
|
|
{
|
|
mobile_master_cnt_offset_resample=mobile_master_cnt_offset_min-offset_min;
|
|
}
|
|
else if(mobile_master_cnt_offset_max>offset_max)
|
|
{
|
|
mobile_master_cnt_offset_resample=mobile_master_cnt_offset_max-offset_max;
|
|
}
|
|
else
|
|
{
|
|
mobile_master_cnt_offset_resample=0;
|
|
}
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune mobile_master_cnt_offset:%d/%d",mobile_master_cnt_offset_min,mobile_master_cnt_offset_max);
|
|
mobile_master_cnt_offset=mobile_master_cnt_offset_resample;
|
|
|
|
if(first_proc_flag==0)
|
|
{
|
|
fre_offset=((int32_t)(mobile_master_cnt_offset*0.5f))*0.0000001f
|
|
+(mobile_master_cnt_offset-mobile_master_cnt_offset_old)*0.0000001f;
|
|
first_proc_flag=1;
|
|
}
|
|
else
|
|
{
|
|
fre_offset=fre_offset+((int32_t)(mobile_master_cnt_offset*0.5f))*0.0000001f
|
|
+(mobile_master_cnt_offset-mobile_master_cnt_offset_old)*0.0000001f;
|
|
first_proc_flag=1;
|
|
}
|
|
|
|
mobile_master_cnt_offset_old=mobile_master_cnt_offset;
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune mobile_master_cnt_offset:%d", mobile_master_cnt_offset);
|
|
#endif
|
|
mobile_master_cnt_offset_max=0;
|
|
mobile_master_cnt_offset_min=0;
|
|
frame_counter=0;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
fre_offset=fre_offset+((int32_t)(mobile_master_cnt_offset*0.5f))*0.00000001f
|
|
+(mobile_master_cnt_offset-mobile_master_cnt_offset_old)*0.00000001f;
|
|
|
|
mobile_master_cnt_offset_old=mobile_master_cnt_offset;
|
|
//TRACE_AUD_STREAM_I("mobile_master_cnt_offset:%d",mobile_master_cnt_offset);
|
|
first_proc_flag=1;
|
|
|
|
}
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
TRACE_AUD_STREAM_I("[STRM_TRIG][SCO] tune fre_offset:%d",(int)(fre_offset*10000000.0f));
|
|
#endif
|
|
if(first_proc_flag==1)
|
|
{
|
|
if(fre_offset>0.0001f)fre_offset=0.0001f;
|
|
if(fre_offset<-0.0001f)fre_offset=-0.0001f;
|
|
}
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE)
|
|
app_resample_tune(playback_samplerate_codecpcm, fre_offset);
|
|
#else
|
|
af_codec_tune(AUD_STREAM_NUM, fre_offset);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
extern CQueue* get_tx_esco_queue_ptr();
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
#define MIC_TDM_FRAME_MS (15)
|
|
#define MIC_TDM_MAX_CH (3)
|
|
static int16_t mic_tdm_buf[SPEECH_FRAME_MS_TO_LEN(16000, MIC_TDM_FRAME_MS)];
|
|
|
|
// forward
|
|
static uint32_t bt_sco_codec_capture_data(uint8_t *buf, uint32_t len);
|
|
|
|
uint32_t tdm_callback_func(uint8_t *buf_ptr, uint32_t frame_len)
|
|
{
|
|
int16_t *pcm_buf = (int16_t *)buf_ptr;
|
|
|
|
// TODO: Check frame_len, depend on sample rate
|
|
|
|
for (uint32_t i = 0; i < frame_len; i++)
|
|
{
|
|
mic_tdm_buf[i] = pcm_buf[i];
|
|
}
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
ASSERT(0, "[%s] Do not support defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)", __func__);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bt_sco_get_tdm_buffer(uint8_t **buf, uint32_t *len)
|
|
{
|
|
*buf = (uint8_t *)&mic_tdm_buf[0];
|
|
*len = sizeof(mic_tdm_buf);
|
|
}
|
|
#endif
|
|
|
|
#if defined(ANC_NOISE_TRACKER)
|
|
static int16_t *anc_buf = NULL;
|
|
#endif
|
|
|
|
|
|
#if defined(ANC_WNR_ENABLED)
|
|
#if defined(SPEECH_TX_24BIT)
|
|
static int32_t wnr_buf[256*2];
|
|
#else
|
|
static short wnr_buf[256*2];
|
|
#endif
|
|
#endif
|
|
//#define BT_SCO_HANDLER_PROFILE
|
|
|
|
//( codec:mic-->btpcm:tx
|
|
// codec:mic
|
|
static uint32_t bt_sco_codec_capture_data(uint8_t *buf, uint32_t len)
|
|
{
|
|
app_bt_stream_trigger_checker_handler(TRIGGER_CHECKER_HFP_AUDPCM_CAPTURE);
|
|
|
|
#if defined(ANC_NOISE_TRACKER)
|
|
int16_t *pcm_buf = (int16_t *)buf;
|
|
uint32_t pcm_len = len / sizeof(short);
|
|
uint32_t ch_num = SPEECH_CODEC_CAPTURE_CHANNEL_NUM + ANC_NOISE_TRACKER_CHANNEL_NUM;
|
|
uint32_t remain_ch_num = SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
|
|
|
|
|
#if defined(SPEECH_TX_AEC_CODEC_REF)
|
|
ch_num += 1;
|
|
remain_ch_num += 1;
|
|
#endif
|
|
|
|
ASSERT(pcm_len % ch_num == 0, "[%s] input data length error", __FUNCTION__);
|
|
|
|
// assume anc mic in ch0
|
|
for (uint32_t i = 0, j = 0; i < pcm_len; i += ch_num, j += ANC_NOISE_TRACKER_CHANNEL_NUM)
|
|
{
|
|
for (uint32_t ch = 0; ch < ANC_NOISE_TRACKER_CHANNEL_NUM; ch++)
|
|
anc_buf[j + ch] = pcm_buf[i + ch];
|
|
}
|
|
|
|
noise_tracker_process(anc_buf, pcm_len / ch_num * ANC_NOISE_TRACKER_CHANNEL_NUM);
|
|
|
|
for (uint32_t i = 0, j = 0; i < pcm_len; i += ch_num, j += remain_ch_num)
|
|
{
|
|
for (uint32_t chi = ANC_NOISE_TRACKER_CHANNEL_NUM, cho = 0; chi < ch_num; chi++, cho++)
|
|
pcm_buf[j + cho] = pcm_buf[i + chi];
|
|
}
|
|
|
|
len = len / ch_num * remain_ch_num;
|
|
#endif
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
//TRACE_AUD_STREAM_I("[SCO][MIC] cnt = %d", codec_capture_cnt++);
|
|
#endif
|
|
|
|
#if defined(ANC_WNR_ENABLED)
|
|
|
|
#if defined(SPEECH_TX_24BIT)
|
|
int32_t *pcm_buf = (int32_t *)buf;
|
|
uint32_t pcm_len = len / sizeof(int32_t);
|
|
#else
|
|
int16_t *pcm_buf = (int16_t *)buf;
|
|
uint32_t pcm_len = len / sizeof(short);
|
|
#endif
|
|
|
|
for(uint32_t i=0;i<pcm_len/sco_cap_chan_num;i++){
|
|
wnr_buf[2*i] = pcm_buf[sco_cap_chan_num*i];
|
|
wnr_buf[2*i+1] = pcm_buf[sco_cap_chan_num*i+1];
|
|
}
|
|
|
|
//TRACE("sco_cap_chan_num=%d",sco_cap_chan_num);
|
|
if (app_anc_work_status()) {
|
|
// 2ch, interleave, 24bits
|
|
anc_wnr_process(wnr_buf, pcm_len * 2 /sco_cap_chan_num);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
if (mic_force_mute || btapp_hfp_mic_need_skip_frame() || btapp_hfp_need_mute())
|
|
{
|
|
memset(buf, 0, len);
|
|
}
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
int pingpang;
|
|
|
|
//processing ping pang flag
|
|
if(buf==capture_buf_codecpcm)
|
|
{
|
|
pingpang=0;
|
|
}
|
|
else
|
|
{
|
|
pingpang=1;
|
|
}
|
|
|
|
uint16_t *playback_dst=(uint16_t *)(playback_buf_btpcm+(pingpang)*playback_size_btpcm/2);
|
|
uint16_t *playback_src=(uint16_t *)playback_buf_btpcm_cache;
|
|
|
|
for(uint32_t i =0; i<playback_size_btpcm/4; i++)
|
|
{
|
|
playback_dst[i]=playback_src[i];
|
|
}
|
|
#ifdef TX_RX_PCM_MASK
|
|
//processing btpcm.(It must be from CPU's copy )
|
|
if(btdrv_is_pcm_mask_enable()==1&&bt_sco_codec_is_msbc())
|
|
{
|
|
uint32_t lock;
|
|
uint32_t i;
|
|
//must lock the interrupts when exchanging data.
|
|
lock = int_lock();
|
|
uint16_t *playback_src=(uint16_t *)(playback_buf_btpcm+(pingpang)*playback_size_btpcm/2);
|
|
for( i =0; i<playback_size_btpcm_copy; i++)
|
|
{
|
|
playback_buf_btpcm_copy[i]=(uint8_t)(playback_src[i]>>8);
|
|
}
|
|
int_unlock(lock);
|
|
}
|
|
#endif
|
|
|
|
|
|
//TRACE_AUD_STREAM_I("pcm length:%d",len);
|
|
|
|
//processing clock
|
|
bt_sco_codec_tuning();
|
|
|
|
|
|
//processing mic
|
|
uint8_t *capture_pcm_frame_p=capture_buf_codecpcm+pingpang*(capture_size_codecpcm)/2;
|
|
//uint8_t *dst=(uint8_t *)(playback_buf_btpcm+(pingpang)*playback_size_btpcm/2);
|
|
uint8_t *dst=playback_buf_btpcm_cache;
|
|
uint8_t *ref_pcm_frame_p=playback_buf_codecpcm+(pingpang^1)*(playback_size_codecpcm)/2;
|
|
|
|
#if defined(HFP_1_6_ENABLE)
|
|
process_uplink_bt_voice_frames(capture_pcm_frame_p,len,
|
|
ref_pcm_frame_p,(playback_size_codecpcm)/2,
|
|
dst,len,app_audio_manager_get_scocodecid());
|
|
#else
|
|
process_uplink_bt_voice_frames(capture_pcm_frame_p,len,
|
|
ref_pcm_frame_p,(playback_size_codecpcm)/2,
|
|
dst,len,BTIF_HF_SCO_CODEC_CVSD);
|
|
#endif
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][MIC] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
|
|
#else
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
int16_t *pcm_buf = (int16_t *)buf;
|
|
uint32_t frame_len = len / sizeof(short) / SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
|
uint32_t ch_num = SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1;
|
|
|
|
ASSERT(SPEECH_CODEC_CAPTURE_CHANNEL_NUM < MIC_TDM_MAX_CH, "[%s] SPEECH_CODEC_CAPTURE_CHANNEL_NUM(%d) is invalid", __func__, SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
|
// TODO: Check len, depend on sample rate
|
|
|
|
for (uint32_t ch = 0; ch < SPEECH_CODEC_CAPTURE_CHANNEL_NUM; ch++)
|
|
{
|
|
for (uint32_t i = 0; i < frame_len; i++)
|
|
{
|
|
mic_tdm_buf[ch_num * i + ch] = pcm_buf[SPEECH_CODEC_CAPTURE_CHANNEL_NUM * i + ch];
|
|
}
|
|
}
|
|
|
|
return len;
|
|
#endif
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
if(hal_cmu_get_audio_resample_status())
|
|
{
|
|
if (af_stream_buffer_error(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE)) {
|
|
sco_dma_buf_err = true;
|
|
}
|
|
// The decoded playback data in the first irq is output to DAC after the second irq (PING-PONG buffer),
|
|
// so it is aligned with the capture data after 2 playback irqs.
|
|
if (sco_play_irq_cnt < SCO_PLAY_RESAMPLE_ALIGN_CNT) {
|
|
// Skip processing
|
|
return len;
|
|
}
|
|
app_capture_resample_run(sco_capture_resample, buf, len);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
voicebtpcm_pcm_audio_data_come(buf, len);
|
|
}
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][MIC] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
#endif
|
|
}
|
|
|
|
#ifdef _SCO_BTPCM_CHANNEL_
|
|
// btpcm:tx
|
|
static uint32_t bt_sco_btpcm_playback_data(uint8_t *buf, uint32_t len)
|
|
{
|
|
app_bt_stream_trigger_checker_handler(TRIGGER_CHECKER_HFP_BTPCM_PLAYERBLACK);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
return len;
|
|
#else
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
get_voicebtpcm_p2m_frame(buf, len);
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][SPK] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
|
|
#endif
|
|
}
|
|
//)
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
void codec_capture_i2s_enable(void)
|
|
{
|
|
uint32_t lock;
|
|
|
|
TRACE_AUD_STREAM_I("[SCO][IIS] Start...", __func__);
|
|
|
|
lock = int_lock();
|
|
hal_codec_capture_enable();
|
|
hal_i2s_enable(HAL_I2S_ID_0);
|
|
int_unlock(lock);
|
|
|
|
}
|
|
#endif
|
|
|
|
extern CQueue* get_rx_esco_queue_ptr();
|
|
|
|
static volatile bool is_codec_stream_started = false;
|
|
#ifdef PCM_PRIVATE_DATA_FLAG
|
|
|
|
void bt_sco_btpcm_get_pcm_priv_data(struct PCM_DATA_FLAG_T *pcm_data, uint8_t *buf, uint32_t len)
|
|
{
|
|
uint8_t frame_num = len/120;
|
|
for(uint8_t i=0; i<frame_num; i++)
|
|
{
|
|
uint8_t head_pos = 120*i;
|
|
pcm_data[i].undef = buf[head_pos];
|
|
pcm_data[i].bitcnt = (buf[head_pos+2]|(buf[head_pos+4]<<8))&0x3ff;
|
|
pcm_data[i].softbit_flag = (buf[head_pos+4]>>5)&3;
|
|
pcm_data[i].btclk = buf[head_pos+6]|(buf[head_pos+8]<<8)|(buf[head_pos+10]<<16)|(buf[head_pos+12]<<24);
|
|
pcm_data[i].reserved = buf[head_pos+14]|(buf[head_pos+16]<<8)|(buf[head_pos+18]<<16)|(buf[head_pos+20]<<24);
|
|
//clear private msg in buffer
|
|
for(uint8_t j=0; j<PCM_PRIVATE_DATA_LENGTH; j++)
|
|
buf[head_pos+2*j] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
//( btpcm:rx-->codec:spk
|
|
// btpcm:rx
|
|
extern void bt_drv_reg_op_set_music_ongong_flag();
|
|
extern void bt_drv_reg_op_clear_music_ongong_flag();
|
|
static uint32_t bt_sco_btpcm_capture_data(uint8_t *buf, uint32_t len)
|
|
{
|
|
int POSSIBLY_UNUSED sRet = 0;
|
|
|
|
app_bt_stream_trigger_checker_handler(TRIGGER_CHECKER_HFP_BTPCM_CAPTURE);
|
|
|
|
#ifdef __BT_ONE_BRING_TWO__
|
|
if(a2dp_is_music_ongoing())
|
|
bt_drv_reg_op_set_music_ongong_flag();
|
|
else
|
|
bt_drv_reg_op_clear_music_ongong_flag();
|
|
#endif
|
|
#if defined(PCM_PRIVATE_DATA_FLAG) && defined(PCM_FAST_MODE)
|
|
bt_sco_btpcm_get_pcm_priv_data(pcm_data_param, buf, len);
|
|
|
|
#endif
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
uint32_t btclk;
|
|
uint16_t btcnt;
|
|
|
|
uint32_t mobile_master_clk;
|
|
uint16_t mobile_master_cnt;
|
|
|
|
bool codec_stream_trig = false;
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
if((is_codec_stream_started == false)&&(buf==capture_buf_btpcm))
|
|
{
|
|
if(!af_stream_buffer_error(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE))
|
|
{
|
|
bt_drv_reg_op_dma_tc_clkcnt_get(&btclk, &btcnt);
|
|
bt_sco_mobile_clkcnt_get(btclk, btcnt,&mobile_master_clk, &mobile_master_cnt);
|
|
hal_sys_timer_delay_us(1);
|
|
if(!af_stream_buffer_error(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE))
|
|
{
|
|
codec_stream_trig = true;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
uint32_t curr_ticks;
|
|
|
|
ibbt_ctrl_t *p_ibbt_ctrl = app_tws_ibbt_get_bt_ctrl_ctx();
|
|
if (app_tws_ibbt_tws_link_connected()){
|
|
curr_ticks = bt_syn_get_curr_ticks(IBBT_MASTER == p_ibbt_ctrl->current_role ? p_ibbt_ctrl->mobile_conhandle : p_ibbt_ctrl->ibbt_conhandle);
|
|
TRACE_AUD_STREAM_I("bt_sco_btpcm_capture_data +++++++++++++++++++++++++++++++++curr_ticks:%d,",curr_ticks);
|
|
}else{
|
|
curr_ticks = btdrv_syn_get_curr_ticks();
|
|
TRACE_AUD_STREAM_I("--------------------------------------");
|
|
}
|
|
*/
|
|
sco_btpcm_mute_flag=0;
|
|
|
|
if (codec_stream_trig) {
|
|
if (app_bt_stream_sco_trigger_btpcm_tick()) {
|
|
af_stream_dma_tc_irq_enable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_stream_dma_tc_irq_disable(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
af_stream_dma_tc_irq_enable(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] buf:%p,capture_buf_btpcm:%p",buf,capture_buf_btpcm);
|
|
|
|
// uint16_t *source=(uint16_t *)buf;
|
|
// DUMP16("%02x,", source, MSBC_FRAME_LEN);
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
hal_i2s_enable_delay(HAL_I2S_ID_0);
|
|
// hal_codec_capture_enable_delay();
|
|
#endif
|
|
tdm_stream_start();
|
|
#endif
|
|
mobile_master_clk_offset_init=mobile_master_clk%12;
|
|
app_bt_stream_sco_trigger_codecpcm_start(mobile_master_clk,mobile_master_cnt);
|
|
is_codec_stream_started = true;
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] btclk:%d,btcnt:%d,",mobile_master_clk,mobile_master_cnt);
|
|
#endif
|
|
}
|
|
} else {
|
|
#if defined(SCO_DMA_SNAPSHOT_DEBUG)
|
|
bt_drv_reg_op_dma_tc_clkcnt_get(&btclk, &btcnt);
|
|
bt_sco_mobile_clkcnt_get(btclk, btcnt,&mobile_master_clk, &mobile_master_cnt);
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX]:btclk:%d,btcnt:%d,",mobile_master_clk,mobile_master_cnt);
|
|
#endif
|
|
}
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
|
|
#else
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
if(!is_sco_mode()){
|
|
TRACE_AUD_STREAM_E("[SCO][BTPCMRX] player exit!");
|
|
memset(buf,0x0,len);
|
|
return len;
|
|
}
|
|
|
|
#if defined(TX_RX_PCM_MASK)
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] TX_RX_PCM_MASK");
|
|
CQueue* Rx_esco_queue_temp = NULL;
|
|
Rx_esco_queue_temp = get_rx_esco_queue_ptr();
|
|
if(bt_sco_codec_is_msbc() && btdrv_is_pcm_mask_enable() ==1 )
|
|
{
|
|
memset(buf,0,len);
|
|
int status = 0;
|
|
len /= 2;
|
|
uint8_t rx_data[len];
|
|
status = DeCQueue(Rx_esco_queue_temp,rx_data,len);
|
|
for(uint32_t i = 0; i<len; i++)
|
|
{
|
|
buf[2*i+1] = rx_data[i];
|
|
}
|
|
len*=2;
|
|
if(status)
|
|
{
|
|
TRACE_AUD_STREAM_E("[SCO][BTPCMRX] Rx Dec Fail");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (is_codec_stream_started == false) {
|
|
if (bt_sco_codec_is_msbc() == false)
|
|
hal_sys_timer_delay_us(3000);
|
|
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] start codec %d", FAST_TICKS_TO_US(hal_fast_sys_timer_get()));
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_start(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
hal_i2s_enable_delay(HAL_I2S_ID_0);
|
|
hal_codec_capture_enable_delay();
|
|
#endif
|
|
tdm_stream_start();
|
|
#endif
|
|
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
codec_capture_i2s_enable();
|
|
#endif
|
|
is_codec_stream_started = true;
|
|
|
|
return len;
|
|
}
|
|
store_voicebtpcm_m2p_buffer(buf, len);
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][BTPCMRX] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef __BT_ANC__
|
|
static void bt_anc_sco_down_sample_16bits(int16_t *dst, int16_t *src, uint32_t dst_cnt)
|
|
{
|
|
for (uint32_t i = 0; i < dst_cnt; i++) {
|
|
dst[i] = src[i * bt_sco_samplerate_ratio * sco_play_chan_num];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void bt_sco_codec_playback_data_post_handler(uint8_t *buf, uint32_t len, void *cfg)
|
|
{
|
|
POSSIBLY_UNUSED struct AF_STREAM_CONFIG_T *config = (struct AF_STREAM_CONFIG_T *)cfg;
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
#ifdef TWS_PROMPT_SYNC
|
|
tws_playback_ticks_check_for_mix_prompt();
|
|
#endif
|
|
if (audio_prompt_is_playing_ongoing())
|
|
{
|
|
audio_prompt_processing_handler(len, buf);
|
|
}
|
|
#else
|
|
app_ring_merge_more_data(buf, len);
|
|
#endif
|
|
}
|
|
|
|
static uint32_t bt_sco_codec_playback_data(uint8_t *buf, uint32_t len)
|
|
{
|
|
app_bt_stream_trigger_checker_handler(TRIGGER_CHECKER_HFP_AUDPCM_PLAYERBLACK);
|
|
|
|
bt_set_playback_triggered(true);
|
|
|
|
#if defined(IBRT) && defined(RSSI_GATHERING_ENABLED)
|
|
app_ibrt_ui_rssi_process();
|
|
#endif
|
|
|
|
#ifdef BT_XTAL_SYNC
|
|
#ifdef BT_XTAL_SYNC_NEW_METHOD
|
|
#ifdef IBRT
|
|
bool valid = false;
|
|
uint32_t bitoffset = 0;
|
|
ibrt_ctrl_t *p_ibrt_ctrl = app_tws_ibrt_get_bt_ctrl_ctx();
|
|
|
|
if (app_tws_ibrt_mobile_link_connected())
|
|
{
|
|
valid = true;
|
|
bitoffset = btdrv_rf_bitoffset_get(p_ibrt_ctrl->mobile_conhandle -0x80);
|
|
}
|
|
else if (app_tws_ibrt_slave_ibrt_link_connected())
|
|
{
|
|
valid = true;
|
|
bitoffset = btdrv_rf_bitoffset_get(p_ibrt_ctrl->ibrt_conhandle -0x80);
|
|
}
|
|
|
|
if(valid)
|
|
{
|
|
if(app_if_need_fix_target_rxbit() == false)
|
|
{
|
|
if(bitoffset<XTAL_OFFSET)
|
|
bitoffset = XTAL_OFFSET;
|
|
else if(bitoffset>SLOT_SIZE-XTAL_OFFSET)
|
|
bitoffset = SLOT_SIZE-XTAL_OFFSET;
|
|
}
|
|
#ifdef BT_XTAL_SYNC_SLOW
|
|
bt_xtal_sync_new_new(bitoffset,app_if_need_fix_target_rxbit(),BT_XTAL_SYNC_MODE_WITH_MOBILE);
|
|
#else
|
|
bt_xtal_sync_new(bitoffset,app_if_need_fix_target_rxbit(),BT_XTAL_SYNC_MODE_WITH_MOBILE);
|
|
#endif
|
|
}
|
|
#endif
|
|
#else
|
|
bt_xtal_sync(BT_XTAL_SYNC_MODE_VOICE);
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
//TRACE_AUD_STREAM_I("[%s] cnt = %d", __func__, codec_playback_cnt++);
|
|
#endif
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
//processing ping pang flag
|
|
int pingpang;
|
|
|
|
if(buf==playback_buf_codecpcm)
|
|
{
|
|
pingpang=0;
|
|
}
|
|
else
|
|
{
|
|
pingpang=1;
|
|
}
|
|
#ifdef TX_RX_PCM_MASK
|
|
//processing btpcm.(It must be from CPU's copy )
|
|
if(btdrv_is_pcm_mask_enable()==1&&bt_sco_codec_is_msbc())
|
|
{
|
|
uint32_t lock;
|
|
uint32_t i;
|
|
//must lock the interrupts when exchanging data.
|
|
lock = int_lock();
|
|
uint16_t *capture_dst=(uint16_t *)(capture_buf_btpcm + pingpang * capture_size_btpcm / 2);
|
|
|
|
for( i =0; i<capture_size_btpcm/4; i++)
|
|
{
|
|
capture_dst[i]=(uint16_t)capture_buf_btpcm_copy[i]<<8;
|
|
}
|
|
int_unlock(lock);
|
|
}
|
|
#endif
|
|
|
|
//processing spk
|
|
uint8_t *playbakce_pcm_frame_p = playback_buf_codecpcm + pingpang * playback_size_codecpcm / 2;
|
|
uint8_t *source = capture_buf_btpcm + pingpang * capture_size_btpcm / 2;
|
|
|
|
if(sco_btpcm_mute_flag == 1 || sco_disconnect_mute_flag == 1) {
|
|
for(uint32_t i =0; i < playback_size_btpcm / 2; i++) {
|
|
source[i]=MUTE_PATTERN;
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[SCO][SPK]mute....................");
|
|
} else {
|
|
sco_btpcm_mute_flag=1;
|
|
}
|
|
|
|
#if defined(HFP_1_6_ENABLE)
|
|
uint32_t source_len = playback_size_btpcm/2;
|
|
if (app_audio_manager_get_scocodecid() == BTIF_HF_SCO_CODEC_MSBC) {
|
|
uint16_t *source_u16 = (uint16_t *)source;
|
|
for (uint32_t i = 0; i < source_len/2; i++) {
|
|
source[i] = (source_u16[i] >> 8);
|
|
}
|
|
source_len >>= 1;
|
|
}
|
|
process_downlink_bt_voice_frames(source,source_len,
|
|
playbakce_pcm_frame_p,(playback_size_codecpcm)/sco_play_chan_num/2,app_audio_manager_get_scocodecid());
|
|
#else
|
|
process_downlink_bt_voice_frames(source,(playback_size_btpcm)/2,
|
|
playbakce_pcm_frame_p,(playback_size_codecpcm)/sco_play_chan_num/2,BTIF_HF_SCO_CODEC_CVSD);
|
|
#endif
|
|
|
|
if (sco_play_chan_num == AUD_CHANNEL_NUM_2) {
|
|
// Convert mono data to stereo data
|
|
#if defined(SPEECH_RX_24BIT)
|
|
app_bt_stream_copy_track_one_to_two_24bits((int32_t *)playbakce_pcm_frame_p, (int32_t *)playbakce_pcm_frame_p, playback_size_codecpcm / 2 / sco_play_chan_num / sizeof(int32_t));
|
|
#else
|
|
app_bt_stream_copy_track_one_to_two_16bits((int16_t *)playbakce_pcm_frame_p, (int16_t *)playbakce_pcm_frame_p, playback_size_codecpcm / 2 / sco_play_chan_num / sizeof(int16_t));
|
|
#endif
|
|
}
|
|
return len;
|
|
#else
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t start_ticks = hal_fast_sys_timer_get();
|
|
#endif
|
|
|
|
uint8_t *dec_buf;
|
|
uint32_t mono_len;
|
|
|
|
#if defined(SPEECH_RX_24BIT)
|
|
len /= 2;
|
|
#endif
|
|
|
|
#ifdef __BT_ANC__
|
|
mono_len = len / sco_play_chan_num / bt_sco_samplerate_ratio;
|
|
dec_buf = bt_anc_sco_dec_buf;
|
|
#else
|
|
mono_len = len / sco_play_chan_num;
|
|
dec_buf = buf;
|
|
#endif
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
if(hal_cmu_get_audio_resample_status())
|
|
{
|
|
if (sco_play_irq_cnt < SCO_PLAY_RESAMPLE_ALIGN_CNT) {
|
|
sco_play_irq_cnt++;
|
|
}
|
|
if (sco_dma_buf_err || af_stream_buffer_error(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK)) {
|
|
sco_dma_buf_err = false;
|
|
sco_play_irq_cnt = 0;
|
|
app_resample_reset(sco_playback_resample);
|
|
app_resample_reset(sco_capture_resample);
|
|
voicebtpcm_pcm_echo_buf_queue_reset();
|
|
TRACE_AUD_STREAM_I("[SCO][SPK]: DMA buffer error: reset resample");
|
|
}
|
|
app_playback_resample_run(sco_playback_resample, dec_buf, mono_len);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifdef __BT_ANC__
|
|
bt_anc_sco_down_sample_16bits((int16_t *)dec_buf, (int16_t *)buf, mono_len / 2);
|
|
#else
|
|
if (sco_play_chan_num == AUD_CHANNEL_NUM_2) {
|
|
// Convert stereo data to mono data (to save into echo_buf)
|
|
app_bt_stream_copy_track_two_to_one_16bits((int16_t *)dec_buf, (int16_t *)buf, mono_len / 2);
|
|
}
|
|
#endif
|
|
voicebtpcm_pcm_audio_more_data(dec_buf, mono_len);
|
|
}
|
|
|
|
#ifdef __BT_ANC__
|
|
voicebtpcm_pcm_resample((int16_t *)dec_buf, mono_len / 2, (int16_t *)buf);
|
|
#endif
|
|
|
|
#if defined(SPEECH_RX_24BIT)
|
|
len <<= 1;
|
|
#endif
|
|
|
|
if (sco_play_chan_num == AUD_CHANNEL_NUM_2) {
|
|
// Convert mono data to stereo data
|
|
#if defined(SPEECH_RX_24BIT)
|
|
app_bt_stream_copy_track_one_to_two_24bits((int32_t *)buf, (int32_t *)buf, len / 2 / sizeof(int32_t));
|
|
#else
|
|
app_bt_stream_copy_track_one_to_two_16bits((int16_t *)buf, (int16_t *)buf, len / 2 / sizeof(int16_t));
|
|
#endif
|
|
}
|
|
|
|
if (spk_force_mute)
|
|
{
|
|
memset(buf, 0, len);
|
|
}
|
|
|
|
#if defined(BT_SCO_HANDLER_PROFILE)
|
|
uint32_t end_ticks = hal_fast_sys_timer_get();
|
|
TRACE_AUD_STREAM_I("[SCO][SPK] takes %d us",
|
|
FAST_TICKS_TO_US(end_ticks - start_ticks));
|
|
#endif
|
|
|
|
return len;
|
|
#endif
|
|
}
|
|
|
|
int bt_sco_player_forcemute(bool mic_mute, bool spk_mute)
|
|
{
|
|
mic_force_mute = mic_mute;
|
|
spk_force_mute = spk_mute;
|
|
return 0;
|
|
}
|
|
|
|
int bt_sco_player_get_codetype(void)
|
|
{
|
|
if (gStreamplayer & APP_BT_STREAM_HFP_PCM)
|
|
{
|
|
return bt_sco_player_code_type;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
static uint32_t audio_mc_data_playback_sco(uint8_t *buf, uint32_t mc_len_bytes)
|
|
{
|
|
// uint32_t begin_time;
|
|
//uint32_t end_time;
|
|
// begin_time = hal_sys_timer_get();
|
|
// TRACE_AUD_STREAM_I("phone cancel: %d",begin_time);
|
|
|
|
float left_gain;
|
|
float right_gain;
|
|
int32_t playback_len_bytes,mc_len_bytes_8;
|
|
int32_t i,j,k;
|
|
int delay_sample;
|
|
|
|
mc_len_bytes_8=mc_len_bytes/8;
|
|
|
|
hal_codec_get_dac_gain(&left_gain,&right_gain);
|
|
|
|
TRACE_AUD_STREAM_I("[SCO][SPK][MC] playback_samplerate_ratio: %d,ch:%d,sample_size:%d.",playback_samplerate_ratio_bt,playback_ch_num_bt,sample_size_play_bt);
|
|
TRACE_AUD_STREAM_I("[SCO][SPK][MC] len: %d",mc_len_bytes);
|
|
|
|
// TRACE_AUD_STREAM_I("left_gain: %d",(int)(left_gain*(1<<12)));
|
|
// TRACE_AUD_STREAM_I("right_gain: %d",(int)(right_gain*(1<<12)));
|
|
|
|
playback_len_bytes=mc_len_bytes/playback_samplerate_ratio_bt;
|
|
|
|
if (sample_size_play_bt == AUD_BITS_16)
|
|
{
|
|
int16_t *sour_p=(int16_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int16_t *mid_p=(int16_t *)(buf);
|
|
int16_t *mid_p_8=(int16_t *)(buf+mc_len_bytes-mc_len_bytes_8);
|
|
int16_t *dest_p=(int16_t *)buf;
|
|
|
|
if(buf == playback_buf_mc)
|
|
{
|
|
sour_p=(int16_t *)playback_buf_bt;
|
|
}
|
|
|
|
if(playback_ch_num_bt==AUD_CHANNEL_NUM_2)
|
|
{
|
|
delay_sample=DELAY_SAMPLE_MC;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
mid_p[j++]=delay_buf_bt[i+1];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/2-delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
mid_p[j++]=sour_p[i+1];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/2;i=i+2)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
delay_buf_bt[j++]=sour_p[i+1];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=8)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+2*(8/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+2)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/8;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_stereo((uint8_t *)mid_p_8,mc_len_bytes_8,left_gain,right_gain,AUD_BITS_16);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_8)/2;i=i+2)
|
|
{
|
|
for(k=0;k<8;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8[i];
|
|
dest_p[j++]=mid_p_8[i+1];
|
|
}
|
|
}
|
|
|
|
}
|
|
else if(playback_ch_num_bt==AUD_CHANNEL_NUM_1)
|
|
{
|
|
delay_sample=DELAY_SAMPLE_MC/2;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/2-delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/2;i=i+1)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=8)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+1*(8/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/2;i=i+1)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/8;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_mono((uint8_t *)mid_p_8,mc_len_bytes_8,left_gain,AUD_BITS_16);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_8)/2;i=i+1)
|
|
{
|
|
for(k=0;k<8;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (sample_size_play_bt == AUD_BITS_24)
|
|
{
|
|
int32_t *sour_p=(int32_t *)(playback_buf_bt+playback_size_bt/2);
|
|
int32_t *mid_p=(int32_t *)(buf);
|
|
int32_t *mid_p_8=(int32_t *)(buf+mc_len_bytes-mc_len_bytes_8);
|
|
int32_t *dest_p=(int32_t *)buf;
|
|
|
|
if(buf == playback_buf_mc)
|
|
{
|
|
sour_p=(int32_t *)playback_buf_bt;
|
|
}
|
|
|
|
if(playback_ch_num_bt==AUD_CHANNEL_NUM_2)
|
|
{
|
|
delay_sample=DELAY_SAMPLE_MC;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
mid_p[j++]=delay_buf_bt[i+1];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/4-delay_sample;i=i+2)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
mid_p[j++]=sour_p[i+1];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/4;i=i+2)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
delay_buf_bt[j++]=sour_p[i+1];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=8)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+2*(8/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+2)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/8;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
mid_p_8[j++]=mid_p[i+1];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_stereo((uint8_t *)mid_p_8,mc_len_bytes_8,left_gain,right_gain,AUD_BITS_24);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_8)/4;i=i+2)
|
|
{
|
|
for(k=0;k<8;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8[i];
|
|
dest_p[j++]=mid_p_8[i+1];
|
|
}
|
|
}
|
|
|
|
}
|
|
else if(playback_ch_num_bt==AUD_CHANNEL_NUM_1)
|
|
{
|
|
delay_sample=DELAY_SAMPLE_MC/2;
|
|
|
|
for(i=0,j=0;i<delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=delay_buf_bt[i];
|
|
}
|
|
|
|
for(i=0;i<playback_len_bytes/4-delay_sample;i=i+1)
|
|
{
|
|
mid_p[j++]=sour_p[i];
|
|
}
|
|
|
|
for(j=0;i<playback_len_bytes/4;i=i+1)
|
|
{
|
|
delay_buf_bt[j++]=sour_p[i];
|
|
}
|
|
|
|
if(playback_samplerate_ratio_bt<=8)
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+1*(8/playback_samplerate_ratio_bt))
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0,j=0;i<playback_len_bytes/4;i=i+1)
|
|
{
|
|
for(k=0;k<playback_samplerate_ratio_bt/8;k++)
|
|
{
|
|
mid_p_8[j++]=mid_p[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
anc_mc_run_mono((uint8_t *)mid_p_8,mc_len_bytes_8,left_gain,AUD_BITS_24);
|
|
|
|
for(i=0,j=0;i<(mc_len_bytes_8)/4;i=i+1)
|
|
{
|
|
for(k=0;k<8;k++)
|
|
{
|
|
dest_p[j++]=mid_p_8[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// end_time = hal_sys_timer_get();
|
|
|
|
// TRACE_AUD_STREAM_I("[SCO][SPK][MC]:run time: %d", end_time-begin_time);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(LOW_DELAY_SCO)
|
|
int speech_get_frame_size(int fs, int ch, int ms)
|
|
{
|
|
return (fs / 1000 * ch * ms)/2;
|
|
}
|
|
#else
|
|
int speech_get_frame_size(int fs, int ch, int ms)
|
|
{
|
|
return (fs / 1000 * ch * ms);
|
|
}
|
|
#endif
|
|
|
|
|
|
int speech_get_af_buffer_size(int fs, int ch, int ms)
|
|
{
|
|
return speech_get_frame_size(fs, ch, ms) * 2 * 2;
|
|
}
|
|
|
|
enum AUD_SAMPRATE_T speech_sco_get_sample_rate(void)
|
|
{
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
|
|
#if defined(HFP_1_6_ENABLE)
|
|
if (bt_sco_codec_is_msbc())
|
|
{
|
|
sample_rate = AUD_SAMPRATE_16000;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
sample_rate = AUD_SAMPRATE_8000;
|
|
}
|
|
|
|
return sample_rate;
|
|
}
|
|
|
|
enum AUD_SAMPRATE_T speech_codec_get_sample_rate(void)
|
|
{
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
|
|
#if defined(MSBC_8K_SAMPLE_RATE)
|
|
sample_rate = AUD_SAMPRATE_8000;
|
|
#else
|
|
if (bt_sco_codec_is_msbc())
|
|
{
|
|
|
|
sample_rate = AUD_SAMPRATE_16000;
|
|
}
|
|
else
|
|
{
|
|
sample_rate = AUD_SAMPRATE_8000;
|
|
}
|
|
#endif
|
|
|
|
return sample_rate;
|
|
}
|
|
|
|
int app_bt_stream_volumeset(int8_t vol);
|
|
|
|
enum AUD_SAMPRATE_T sco_sample_rate;
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
void bt_sco_bt_trigger_callback(void)
|
|
{
|
|
TRACE_AUD_STREAM_I("[SCO][IIS] Start...", __func__);
|
|
|
|
hal_i2s_enable(HAL_I2S_ID_0);
|
|
}
|
|
#endif
|
|
|
|
extern void bt_drv_reg_op_pcm_set(uint8_t en);
|
|
extern uint8_t bt_drv_reg_op_pcm_get();
|
|
int bt_sco_player(bool on, enum APP_SYSFREQ_FREQ_T freq)
|
|
{
|
|
struct AF_STREAM_CONFIG_T stream_cfg;
|
|
static bool isRun = false;
|
|
uint8_t * bt_audio_buff = NULL;
|
|
enum AUD_SAMPRATE_T sample_rate;
|
|
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] work:%d op:%d freq:%d", isRun, on, freq);
|
|
|
|
#ifdef CHIP_BEST2000
|
|
btdrv_enable_one_packet_more_head(0);
|
|
#endif
|
|
|
|
bt_set_playback_triggered(false);
|
|
if (isRun==on)
|
|
return 0;
|
|
|
|
if (on)
|
|
{
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
audio_prompt_stop_playing();
|
|
#endif
|
|
|
|
|
|
#ifdef WL_DET
|
|
app_mic_alg_audioloop(false,APP_SYSFREQ_78M);
|
|
#endif
|
|
|
|
#if defined(IBRT)
|
|
app_ibrt_ui_rssi_reset();
|
|
app_ibrt_if_exec_sleep_hook_blocker_set(APP_IBRT_IF_SLEEP_HOOK_BLOCKER_HFP_SCO);
|
|
#endif
|
|
#ifdef __IAG_BLE_INCLUDE__
|
|
app_ble_force_switch_adv(BLE_SWITCH_USER_SCO, false);
|
|
#endif
|
|
#ifdef TX_RX_PCM_MASK
|
|
if (btdrv_is_pcm_mask_enable() ==1 && bt_sco_codec_is_msbc())
|
|
{
|
|
bt_drv_reg_op_pcm_set(1);
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] PCM MASK");
|
|
}
|
|
#endif
|
|
|
|
#if defined(PCM_FAST_MODE)
|
|
btdrv_open_pcm_fast_mode_enable();
|
|
#ifdef PCM_PRIVATE_DATA_FLAG
|
|
bt_drv_reg_op_set_pcm_flag();
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __THIRDPARTY
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_STOP);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO2,THIRDPARTY_MIC_OPEN);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO3,THIRDPARTY_STOP);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_KWS,THIRDPARTY_CALL_START);
|
|
#endif
|
|
//bt_syncerr set to max(0x0a)
|
|
// BTDIGITAL_REG_SET_FIELD(REG_BTCORE_BASE_ADDR, 0x0f, 0, 0x0f);
|
|
// af_set_priority(AF_USER_SCO, osPriorityRealtime);
|
|
af_set_priority(AF_USER_SCO, osPriorityHigh);
|
|
bt_media_volume_ptr_update_by_mediatype(BT_STREAM_VOICE);
|
|
stream_local_volume = btdevice_volume_p->hfp_vol;
|
|
app_audio_manager_sco_status_checker();
|
|
|
|
#if defined(HFP_1_6_ENABLE)
|
|
bt_sco_player_code_type = app_audio_manager_get_scocodecid();
|
|
#endif
|
|
|
|
if (freq < APP_SYSFREQ_104M)
|
|
{
|
|
freq = APP_SYSFREQ_104M;
|
|
}
|
|
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
if (freq < APP_SYSFREQ_208M) {
|
|
freq = APP_SYSFREQ_208M;
|
|
}
|
|
#endif
|
|
|
|
#if defined(SCO_CP_ACCEL)
|
|
freq = APP_SYSFREQ_52M;
|
|
#endif
|
|
|
|
app_sysfreq_req(APP_SYSFREQ_USER_BT_SCO, freq);
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] sysfreq:%d", freq);
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] sysfreq calc : %d\n", hal_sys_timer_calc_cpu_freq(5, 0));
|
|
|
|
#ifndef FPGA
|
|
app_overlay_select(APP_OVERLAY_HFP);
|
|
#ifdef BT_XTAL_SYNC
|
|
bt_init_xtal_sync(BT_XTAL_SYNC_MODE_VOICE, BT_INIT_XTAL_SYNC_MIN, BT_INIT_XTAL_SYNC_MAX, BT_INIT_XTAL_SYNC_FCAP_RANGE);
|
|
#endif
|
|
#endif
|
|
btdrv_rf_bit_offset_track_enable(true);
|
|
|
|
#if !defined(SCO_DMA_SNAPSHOT)
|
|
int aec_frame_len = speech_get_frame_size(speech_codec_get_sample_rate(), 1, SPEECH_SCO_FRAME_MS);
|
|
speech_tx_aec_set_frame_len(aec_frame_len);
|
|
#endif
|
|
|
|
bt_sco_player_forcemute(false, false);
|
|
|
|
bt_sco_mode = 1;
|
|
|
|
app_audio_mempool_init();
|
|
|
|
#ifndef _SCO_BTPCM_CHANNEL_
|
|
memset(&hf_sendbuff_ctrl, 0, sizeof(hf_sendbuff_ctrl));
|
|
#endif
|
|
|
|
sample_rate = speech_codec_get_sample_rate();
|
|
|
|
sco_cap_chan_num = (enum AUD_CHANNEL_NUM_T)SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
|
|
|
#if defined(FPGA)
|
|
sco_cap_chan_num = AUD_CHANNEL_NUM_2;
|
|
#endif
|
|
|
|
#if defined(SPEECH_TX_AEC_CODEC_REF)
|
|
sco_cap_chan_num = (enum AUD_CHANNEL_NUM_T)(sco_cap_chan_num + 1);
|
|
#endif
|
|
|
|
#if defined(ANC_NOISE_TRACKER)
|
|
sco_cap_chan_num = (enum AUD_CHANNEL_NUM_T)(sco_cap_chan_num + ANC_NOISE_TRACKER_CHANNEL_NUM);
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_USE_I2S
|
|
hal_cmu_audio_resample_disable();
|
|
#endif
|
|
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
|
|
// codec:mic
|
|
stream_cfg.channel_num = sco_cap_chan_num;
|
|
stream_cfg.data_size = speech_get_af_buffer_size(sample_rate, sco_cap_chan_num, SPEECH_SCO_FRAME_MS);
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(NO_SCO_RESAMPLE)
|
|
// When __AUDIO_RESAMPLE__ is defined,
|
|
// resample is off by default on best1000, and on by default on other platforms
|
|
#ifndef CHIP_BEST1000
|
|
hal_cmu_audio_resample_disable();
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
if (sample_rate == AUD_SAMPRATE_8000)
|
|
{
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_8463;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_16000)
|
|
{
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_16927;
|
|
}
|
|
#ifdef RESAMPLE_ANY_SAMPLE_RATE
|
|
sco_capture_resample = app_capture_resample_any_open( stream_cfg.channel_num,
|
|
bt_sco_capture_resample_iter, stream_cfg.data_size / 2,
|
|
(float)CODEC_FREQ_26M / CODEC_FREQ_24P576M);
|
|
#else
|
|
sco_capture_resample = app_capture_resample_open(sample_rate, stream_cfg.channel_num,
|
|
bt_sco_capture_resample_iter, stream_cfg.data_size / 2);
|
|
#endif
|
|
uint32_t mono_cap_samp_cnt = stream_cfg.data_size / 2 / 2 / stream_cfg.channel_num;
|
|
uint32_t cap_irq_cnt_per_frm = ((mono_cap_samp_cnt * stream_cfg.sample_rate + (sample_rate - 1)) / sample_rate +
|
|
(aec_frame_len - 1)) / aec_frame_len;
|
|
if (cap_irq_cnt_per_frm == 0) {
|
|
cap_irq_cnt_per_frm = 1;
|
|
}
|
|
#else
|
|
stream_cfg.sample_rate = sample_rate;
|
|
#endif
|
|
|
|
#if defined(SPEECH_TX_24BIT)
|
|
stream_cfg.bits = AUD_BITS_24;
|
|
stream_cfg.data_size *= 2;
|
|
#else
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
#endif
|
|
stream_cfg.vol = stream_local_volume;
|
|
|
|
#ifdef FPGA
|
|
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
|
#else
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
#endif
|
|
stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC;
|
|
stream_cfg.handler = bt_sco_codec_capture_data;
|
|
app_audio_mempool_get_buff(&bt_audio_buff, stream_cfg.data_size);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
capture_buf_codecpcm=stream_cfg.data_ptr;
|
|
capture_size_codecpcm=stream_cfg.data_size;
|
|
#endif
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] capture sample_rate:%d, data_size:%d",stream_cfg.sample_rate,stream_cfg.data_size);
|
|
|
|
#if defined(ANC_WNR_ENABLED)
|
|
if(app_anc_work_status())
|
|
{
|
|
anc_wnr_close();
|
|
anc_wnr_ctrl(stream_cfg.sample_rate, speech_get_frame_size(stream_cfg.sample_rate, 1, SPEECH_SCO_FRAME_MS));
|
|
anc_release_gain();
|
|
anc_wnr_open(ANC_WNR_OPEN_MODE_CONFIGURE);
|
|
}
|
|
else
|
|
{
|
|
anc_wnr_ctrl(stream_cfg.sample_rate, speech_get_frame_size(stream_cfg.sample_rate, 1, SPEECH_SCO_FRAME_MS));
|
|
}
|
|
#endif
|
|
|
|
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
|
|
#if defined(HW_DC_FILTER_WITH_IIR)
|
|
hw_filter_codec_iir_st = hw_filter_codec_iir_create(stream_cfg.sample_rate, stream_cfg.channel_num, stream_cfg.bits, &adc_iir_cfg);
|
|
#endif
|
|
|
|
#if defined(CHIP_BEST2300)
|
|
btdrv_set_bt_pcm_triggler_delay(60);
|
|
#elif defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2001)
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
btdrv_set_bt_pcm_triggler_delay(2);
|
|
#else
|
|
btdrv_set_bt_pcm_triggler_delay(60);
|
|
#endif
|
|
|
|
#elif defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
btdrv_set_bt_pcm_triggler_delay(2);
|
|
#else
|
|
btdrv_set_bt_pcm_triggler_delay(59);
|
|
#endif
|
|
|
|
#else
|
|
btdrv_set_bt_pcm_triggler_delay(55);
|
|
#endif
|
|
// codec:spk
|
|
sample_rate = speech_codec_get_sample_rate();
|
|
#if defined(CHIP_BEST1000)
|
|
sco_play_chan_num = AUD_CHANNEL_NUM_2;
|
|
#else
|
|
#ifdef PLAYBACK_USE_I2S
|
|
sco_play_chan_num = AUD_CHANNEL_NUM_2;
|
|
#else
|
|
sco_play_chan_num = AUD_CHANNEL_NUM_1;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
codec_capture_cnt = 0;
|
|
codec_playback_cnt = 0;
|
|
#endif
|
|
lis25ba_init();
|
|
tdm_stream_register(tdm_callback_func);
|
|
#endif
|
|
|
|
stream_cfg.channel_num = sco_play_chan_num;
|
|
// stream_cfg.data_size = BT_AUDIO_SCO_BUFF_SIZE * stream_cfg.channel_num;
|
|
stream_cfg.data_size = speech_get_af_buffer_size(sample_rate, sco_play_chan_num, SPEECH_SCO_FRAME_MS);
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
if (sample_rate == AUD_SAMPRATE_8000)
|
|
{
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_8463;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_16000)
|
|
{
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_16927;
|
|
}
|
|
#ifdef RESAMPLE_ANY_SAMPLE_RATE
|
|
sco_playback_resample = app_playback_resample_any_open( AUD_CHANNEL_NUM_1,
|
|
bt_sco_playback_resample_iter, stream_cfg.data_size / stream_cfg.channel_num / 2,
|
|
(float)CODEC_FREQ_24P576M / CODEC_FREQ_26M);
|
|
#else
|
|
sco_playback_resample = app_playback_resample_open(sample_rate, AUD_CHANNEL_NUM_1,
|
|
bt_sco_playback_resample_iter, stream_cfg.data_size / stream_cfg.channel_num / 2);
|
|
#endif
|
|
sco_play_irq_cnt = 0;
|
|
sco_dma_buf_err = false;
|
|
|
|
uint32_t mono_play_samp_cnt = stream_cfg.data_size / 2 / 2 / stream_cfg.channel_num;
|
|
uint32_t play_irq_cnt_per_frm = ((mono_play_samp_cnt * stream_cfg.sample_rate + (sample_rate - 1)) / sample_rate +
|
|
(aec_frame_len - 1)) / aec_frame_len;
|
|
if (play_irq_cnt_per_frm == 0) {
|
|
play_irq_cnt_per_frm = 1;
|
|
}
|
|
uint32_t play_samp_cnt_per_frm = mono_play_samp_cnt * play_irq_cnt_per_frm;
|
|
uint32_t cap_samp_cnt_per_frm = mono_cap_samp_cnt * cap_irq_cnt_per_frm;
|
|
uint32_t max_samp_cnt_per_frm = (play_samp_cnt_per_frm >= cap_samp_cnt_per_frm) ? play_samp_cnt_per_frm : cap_samp_cnt_per_frm;
|
|
uint32_t echo_q_samp_cnt = (((max_samp_cnt_per_frm + mono_play_samp_cnt * SCO_PLAY_RESAMPLE_ALIGN_CNT) *
|
|
// convert to 8K/16K sample cnt
|
|
sample_rate +(stream_cfg.sample_rate - 1)) / stream_cfg.sample_rate +
|
|
// aligned with aec_frame_len
|
|
(aec_frame_len - 1)) / aec_frame_len * aec_frame_len;
|
|
if (echo_q_samp_cnt == 0) {
|
|
echo_q_samp_cnt = aec_frame_len;
|
|
}
|
|
voicebtpcm_pcm_echo_buf_queue_init(echo_q_samp_cnt * 2);
|
|
#else
|
|
stream_cfg.sample_rate = sample_rate;
|
|
#endif
|
|
|
|
#ifdef __BT_ANC__
|
|
// Mono channel decoder buffer (8K or 16K sample rate)
|
|
app_audio_mempool_get_buff(&bt_anc_sco_dec_buf, stream_cfg.data_size / 2 / sco_play_chan_num);
|
|
// The playback size for the actual sample rate
|
|
bt_sco_samplerate_ratio = 6/(sample_rate/AUD_SAMPRATE_8000);
|
|
stream_cfg.data_size *= bt_sco_samplerate_ratio;
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_50781;
|
|
#else
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_48000;
|
|
#endif
|
|
//damic_init();
|
|
//init_amic_dc_bt();
|
|
//ds_fir_init();
|
|
us_fir_init();
|
|
#endif
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
#ifdef PLAYBACK_USE_I2S
|
|
stream_cfg.device = AUD_STREAM_USE_I2S0_MASTER;
|
|
stream_cfg.io_path = AUD_IO_PATH_NULL;
|
|
#else
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
#endif
|
|
stream_cfg.handler = bt_sco_codec_playback_data;
|
|
|
|
#if defined(SPEECH_RX_24BIT)
|
|
stream_cfg.bits = AUD_BITS_24;
|
|
stream_cfg.data_size *= 2;
|
|
#endif
|
|
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
uint8_t* promptTmpSourcePcmDataBuf;
|
|
uint8_t* promptTmpTargetPcmDataBuf;
|
|
uint8_t* promptPcmDataBuf;
|
|
uint8_t* promptResamplerBuf;
|
|
|
|
sco_sample_rate = stream_cfg.sample_rate;
|
|
app_audio_mempool_get_buff(&promptTmpSourcePcmDataBuf, AUDIO_PROMPT_SOURCE_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptTmpTargetPcmDataBuf, AUDIO_PROMPT_TARGET_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptPcmDataBuf, AUDIO_PROMPT_PCM_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&promptResamplerBuf, AUDIO_PROMPT_BUF_SIZE_FOR_RESAMPLER);
|
|
|
|
audio_prompt_buffer_config(MIX_WITH_SCO_STREAMING,
|
|
stream_cfg.channel_num,
|
|
stream_cfg.bits,
|
|
promptTmpSourcePcmDataBuf,
|
|
promptTmpTargetPcmDataBuf,
|
|
promptPcmDataBuf,
|
|
AUDIO_PROMPT_PCM_BUFFER_SIZE,
|
|
promptResamplerBuf,
|
|
AUDIO_PROMPT_BUF_SIZE_FOR_RESAMPLER);
|
|
#endif
|
|
|
|
app_audio_mempool_get_buff(&bt_audio_buff, stream_cfg.data_size);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] playback sample_rate:%d, data_size:%d",stream_cfg.sample_rate,stream_cfg.data_size);
|
|
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
sample_size_play_bt=stream_cfg.bits;
|
|
sample_rate_play_bt=stream_cfg.sample_rate;
|
|
data_size_play_bt=stream_cfg.data_size;
|
|
playback_buf_bt=stream_cfg.data_ptr;
|
|
playback_size_bt=stream_cfg.data_size;
|
|
|
|
#ifdef __BT_ANC__
|
|
playback_samplerate_ratio_bt=8;
|
|
#else
|
|
if (sample_rate_play_bt == AUD_SAMPRATE_8000)
|
|
{
|
|
playback_samplerate_ratio_bt=8*3*2;
|
|
}
|
|
else if (sample_rate_play_bt == AUD_SAMPRATE_16000)
|
|
{
|
|
playback_samplerate_ratio_bt=8*3;
|
|
}
|
|
#endif
|
|
|
|
playback_ch_num_bt=stream_cfg.channel_num;
|
|
#endif
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
playback_buf_codecpcm=stream_cfg.data_ptr;
|
|
playback_size_codecpcm=stream_cfg.data_size;
|
|
playback_samplerate_codecpcm=stream_cfg.sample_rate;
|
|
#endif
|
|
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
|
|
af_stream_dma_tc_irq_enable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
af_codec_set_playback_post_handler(bt_sco_codec_playback_data_post_handler);
|
|
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
stream_cfg.bits = sample_size_play_bt;
|
|
stream_cfg.channel_num = playback_ch_num_bt;
|
|
stream_cfg.sample_rate = sample_rate_play_bt;
|
|
stream_cfg.device = AUD_STREAM_USE_MC;
|
|
stream_cfg.vol = 0;
|
|
stream_cfg.handler = audio_mc_data_playback_sco;
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
|
|
app_audio_mempool_get_buff(&bt_audio_buff, data_size_play_bt*playback_samplerate_ratio_bt);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
stream_cfg.data_size = data_size_play_bt*playback_samplerate_ratio_bt;
|
|
|
|
playback_buf_mc=stream_cfg.data_ptr;
|
|
playback_size_mc=stream_cfg.data_size;
|
|
|
|
anc_mc_run_init(hal_codec_anc_convert_rate(sample_rate_play_bt));
|
|
|
|
memset(delay_buf_bt,0,sizeof(delay_buf_bt));
|
|
|
|
af_stream_open(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
tdm_stream_open();
|
|
|
|
#if defined(AF_ADC_I2S_SYNC)
|
|
af_codec_bt_trigger_config(true, bt_sco_bt_trigger_callback);
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(ANC_NOISE_TRACKER)
|
|
app_audio_mempool_get_buff(
|
|
(uint8_t **)&anc_buf,
|
|
speech_get_frame_size(
|
|
speech_codec_get_sample_rate(),
|
|
ANC_NOISE_TRACKER_CHANNEL_NUM,
|
|
SPEECH_SCO_FRAME_MS) * sizeof(int16_t));
|
|
noise_tracker_init(nt_demo_words_cb, ANC_NOISE_TRACKER_CHANNEL_NUM, -20);
|
|
#endif
|
|
|
|
// Must call this function before af_stream_start
|
|
// Get all free app audio buffer except SCO_BTPCM used(2k)
|
|
voicebtpcm_pcm_audio_init(speech_sco_get_sample_rate(), speech_codec_get_sample_rate());
|
|
|
|
/*
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] start codec %d", FAST_TICKS_TO_US(hal_fast_sys_timer_get()));
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_start(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
*/
|
|
|
|
#ifdef SPEECH_SIDETONE
|
|
hal_codec_sidetone_enable();
|
|
#endif
|
|
|
|
#ifdef _SCO_BTPCM_CHANNEL_
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
stream_cfg.sample_rate = speech_sco_get_sample_rate();
|
|
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
|
// stream_cfg.data_size = BT_AUDIO_SCO_BUFF_SIZE * stream_cfg.channel_num;
|
|
|
|
if (bt_sco_codec_is_msbc())
|
|
{
|
|
stream_cfg.data_size = speech_get_af_buffer_size(stream_cfg.sample_rate, stream_cfg.channel_num, SPEECH_SCO_FRAME_MS)/2;
|
|
}
|
|
else
|
|
{
|
|
stream_cfg.data_size = speech_get_af_buffer_size(stream_cfg.sample_rate, stream_cfg.channel_num, SPEECH_SCO_FRAME_MS);
|
|
}
|
|
|
|
// btpcm:rx
|
|
stream_cfg.device = AUD_STREAM_USE_BT_PCM;
|
|
stream_cfg.handler = bt_sco_btpcm_capture_data;
|
|
app_audio_mempool_get_buff(&bt_audio_buff, stream_cfg.data_size);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] sco btpcm sample_rate:%d, data_size:%d",stream_cfg.sample_rate,stream_cfg.data_size);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
sco_btpcm_mute_flag=0;
|
|
sco_disconnect_mute_flag=0;
|
|
|
|
capture_buf_btpcm=stream_cfg.data_ptr;
|
|
capture_size_btpcm=stream_cfg.data_size;
|
|
#ifdef TX_RX_PCM_MASK
|
|
capture_size_btpcm_copy=stream_cfg.data_size/4;//only need ping or pang;
|
|
app_audio_mempool_get_buff(&capture_buf_btpcm_copy, capture_size_btpcm_copy);
|
|
#endif
|
|
#endif
|
|
af_stream_open(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
|
|
// btpcm:tx
|
|
stream_cfg.device = AUD_STREAM_USE_BT_PCM;
|
|
stream_cfg.handler = bt_sco_btpcm_playback_data;
|
|
app_audio_mempool_get_buff(&bt_audio_buff, stream_cfg.data_size);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
playback_buf_btpcm=stream_cfg.data_ptr;
|
|
playback_size_btpcm=stream_cfg.data_size;
|
|
#ifdef TX_RX_PCM_MASK
|
|
playback_size_btpcm_copy=stream_cfg.data_size/4; //only need ping or pang;
|
|
app_audio_mempool_get_buff(&playback_buf_btpcm_copy, playback_size_btpcm_copy);
|
|
#endif
|
|
//only need ping or pang;
|
|
app_audio_mempool_get_buff(&playback_buf_btpcm_cache, stream_cfg.data_size/2);
|
|
#endif
|
|
|
|
af_stream_open(AUD_STREAM_ID_1, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
|
|
#if !(defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE))
|
|
af_codec_tune(AUD_STREAM_NUM, 0);
|
|
#endif
|
|
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] start btpcm %d", FAST_TICKS_TO_US(hal_fast_sys_timer_get()));
|
|
af_stream_start(AUD_STREAM_ID_1, AUD_STREAM_PLAYBACK);
|
|
af_stream_start(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
af_stream_dma_tc_irq_enable(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
|
|
#ifdef PLAYBACK_USE_I2S
|
|
af_i2s_sync_config(AUD_STREAM_PLAYBACK, AF_I2S_SYNC_TYPE_BT, true);
|
|
#else
|
|
af_codec_sync_config(AUD_STREAM_PLAYBACK, AF_CODEC_SYNC_TYPE_BT, true);
|
|
#endif
|
|
af_codec_sync_config(AUD_STREAM_CAPTURE, AF_CODEC_SYNC_TYPE_BT, true);
|
|
|
|
btdrv_disable_playback_triggler();
|
|
app_bt_stream_sco_trigger_btpcm_start();
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
#endif
|
|
|
|
is_codec_stream_started = false;
|
|
|
|
#if defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) || defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2001)
|
|
#if defined(CVSD_BYPASS)
|
|
btdrv_cvsd_bypass_enable(bt_sco_codec_is_msbc());
|
|
#endif
|
|
#if !defined(SCO_DMA_SNAPSHOT)
|
|
btdrv_pcm_enable();
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef FPGA
|
|
app_bt_stream_volumeset(stream_local_volume);
|
|
//btdrv_set_bt_pcm_en(1);
|
|
#endif
|
|
app_bt_stream_trigger_checker_start();
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] on");
|
|
}
|
|
else
|
|
{
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
bool isToClearActiveMedia= audio_prompt_clear_pending_stream(PENDING_TO_STOP_SCO_STREAMING);
|
|
if (isToClearActiveMedia)
|
|
{
|
|
bt_media_clear_media_type(BT_STREAM_VOICE, BT_DEVICE_ID_1);
|
|
}
|
|
#endif
|
|
app_bt_stream_trigger_checker_stop();
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
#ifdef TX_RX_PCM_MASK
|
|
playback_buf_btpcm_copy=NULL;
|
|
capture_buf_btpcm_copy=NULL;
|
|
playback_size_btpcm_copy=0;
|
|
capture_size_btpcm_copy=0;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __THIRDPARTY
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO2,THIRDPARTY_MIC_CLOSE);
|
|
#endif
|
|
#if defined(SCO_DMA_SNAPSHOT)
|
|
app_bt_stream_sco_trigger_codecpcm_stop();
|
|
#endif
|
|
af_stream_dma_tc_irq_disable(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
af_codec_set_playback_post_handler(NULL);
|
|
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_stop(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
is_codec_stream_started = false;
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
tdm_stream_stop();
|
|
#endif
|
|
|
|
#if !(defined(__AUDIO_RESAMPLE__) && defined(SW_PLAYBACK_RESAMPLE))
|
|
af_codec_tune(AUD_STREAM_NUM, 0);
|
|
#endif
|
|
|
|
#ifdef _SCO_BTPCM_CHANNEL_
|
|
af_stream_stop(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
af_stream_stop(AUD_STREAM_ID_1, AUD_STREAM_PLAYBACK);
|
|
|
|
af_stream_close(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE);
|
|
af_stream_close(AUD_STREAM_ID_1, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
#ifdef TX_RX_PCM_MASK
|
|
if (btdrv_is_pcm_mask_enable()==1 && bt_drv_reg_op_pcm_get())
|
|
{
|
|
bt_drv_reg_op_pcm_set(0);
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] PCM UNMASK");
|
|
}
|
|
#endif
|
|
#if defined(PCM_FAST_MODE)
|
|
btdrv_open_pcm_fast_mode_disable();
|
|
#endif
|
|
|
|
#if defined(HW_DC_FILTER_WITH_IIR)
|
|
hw_filter_codec_iir_destroy(hw_filter_codec_iir_st);
|
|
#endif
|
|
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
#if defined(AUDIO_ANC_FB_MC_SCO) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_close(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
tdm_stream_close();
|
|
#endif
|
|
|
|
#ifdef SPEECH_SIDETONE
|
|
hal_codec_sidetone_disable();
|
|
#endif
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(SW_SCO_RESAMPLE)
|
|
app_capture_resample_close(sco_capture_resample);
|
|
sco_capture_resample = NULL;
|
|
app_capture_resample_close(sco_playback_resample);
|
|
sco_playback_resample = NULL;
|
|
#endif
|
|
|
|
#if defined(__AUDIO_RESAMPLE__) && defined(NO_SCO_RESAMPLE)
|
|
#ifndef CHIP_BEST1000
|
|
// When __AUDIO_RESAMPLE__ is defined,
|
|
// resample is off by default on best1000, and on by default on other platforms
|
|
hal_cmu_audio_resample_enable();
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef PLAYBACK_USE_I2S
|
|
hal_cmu_audio_resample_enable();
|
|
#endif
|
|
|
|
bt_sco_mode = 0;
|
|
|
|
#ifdef __BT_ANC__
|
|
bt_anc_sco_dec_buf = NULL;
|
|
//damic_deinit();
|
|
//app_cap_thread_stop();
|
|
#endif
|
|
voicebtpcm_pcm_audio_deinit();
|
|
|
|
#if defined(BONE_SENSOR_TDM)
|
|
lis25ba_deinit();
|
|
#endif
|
|
|
|
#ifndef FPGA
|
|
#ifdef BT_XTAL_SYNC
|
|
bt_term_xtal_sync(false);
|
|
#ifndef BT_XTAL_SYNC_NO_RESET
|
|
bt_term_xtal_sync_default();
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if defined(HFP_1_6_ENABLE)
|
|
TRACE(1,"clear sco tx fifo codec:%d",bt_sco_player_code_type);
|
|
bt_drv_reg_op_sco_txfifo_reset(bt_sco_player_code_type);
|
|
bt_sco_player_code_type = BTIF_HF_SCO_CODEC_NONE;
|
|
#else
|
|
bt_drv_reg_op_sco_txfifo_reset(1);
|
|
#endif
|
|
|
|
#if defined(ANC_WNR_ENABLED)
|
|
if (app_anc_work_status()) {
|
|
anc_wnr_close();
|
|
anc_release_gain();
|
|
anc_wnr_open(ANC_WNR_OPEN_MODE_STANDALONE);
|
|
}
|
|
#endif
|
|
|
|
#ifdef __IAG_BLE_INCLUDE__
|
|
app_ble_force_switch_adv(BLE_SWITCH_USER_SCO, true);
|
|
#endif
|
|
|
|
TRACE_AUD_STREAM_I("[SCO_PLAYER] off");
|
|
app_overlay_unloadall();
|
|
app_sysfreq_req(APP_SYSFREQ_USER_BT_SCO, APP_SYSFREQ_32K);
|
|
af_set_priority(AF_USER_SCO, osPriorityAboveNormal);
|
|
|
|
//bt_syncerr set to default(0x07)
|
|
// BTDIGITAL_REG_SET_FIELD(REG_BTCORE_BASE_ADDR, 0x0f, 0, 0x07);
|
|
#ifdef __THIRDPARTY
|
|
//app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO1,THIRDPARTY_START);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_NO3,THIRDPARTY_START);
|
|
app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_KWS,THIRDPARTY_CALL_STOP);
|
|
#endif
|
|
#if defined(IBRT)
|
|
app_ibrt_if_exec_sleep_hook_blocker_clr(APP_IBRT_IF_SLEEP_HOOK_BLOCKER_HFP_SCO);
|
|
app_ibrt_ui_rssi_reset();
|
|
#endif
|
|
|
|
#ifdef WL_DET
|
|
app_mic_alg_audioloop(true,APP_SYSFREQ_78M);
|
|
#endif
|
|
|
|
}
|
|
|
|
isRun=on;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef AUDIO_LINEIN
|
|
#include "app_status_ind.h"
|
|
//player channel should <= capture channel number
|
|
//player must be 2 channel
|
|
#define LINEIN_PLAYER_CHANNEL (2)
|
|
#ifdef __AUDIO_OUTPUT_MONO_MODE__
|
|
#define LINEIN_CAPTURE_CHANNEL (1)
|
|
#else
|
|
#define LINEIN_CAPTURE_CHANNEL (2)
|
|
#endif
|
|
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
#define LINEIN_PLAYER_BUFFER_SIZE (1024*LINEIN_PLAYER_CHANNEL)
|
|
#define LINEIN_CAPTURE_BUFFER_SIZE (LINEIN_PLAYER_BUFFER_SIZE/2)
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
#define LINEIN_PLAYER_BUFFER_SIZE (1024*LINEIN_PLAYER_CHANNEL)
|
|
#define LINEIN_CAPTURE_BUFFER_SIZE (LINEIN_PLAYER_BUFFER_SIZE)
|
|
#endif
|
|
|
|
int8_t app_linein_buffer_is_empty(void)
|
|
{
|
|
if (app_audio_pcmbuff_length()){
|
|
return 0;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
uint32_t app_linein_pcm_come(uint8_t * pcm_buf, uint32_t len)
|
|
{
|
|
app_audio_pcmbuff_put(pcm_buf, len);
|
|
|
|
return len;
|
|
}
|
|
|
|
uint32_t app_linein_need_pcm_data(uint8_t* pcm_buf, uint32_t len)
|
|
{
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
app_audio_pcmbuff_get((uint8_t *)app_linein_play_cache, len/2);
|
|
app_play_audio_lineinmode_more_data((uint8_t *)app_linein_play_cache,len/2);
|
|
app_bt_stream_copy_track_one_to_two_16bits((int16_t *)pcm_buf, app_linein_play_cache, len/2/2);
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
app_audio_pcmbuff_get((uint8_t *)pcm_buf, len);
|
|
app_play_audio_lineinmode_more_data((uint8_t *)pcm_buf, len);
|
|
#endif
|
|
|
|
#if defined(__AUDIO_OUTPUT_MONO_MODE__)
|
|
merge_stereo_to_mono_16bits((int16_t *)buf, (int16_t *)pcm_buf, len/2);
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
bt_audio_updata_eq_for_anc(app_anc_work_status());
|
|
#else
|
|
bt_audio_updata_eq(app_audio_get_eq());
|
|
#endif
|
|
|
|
audio_process_run(pcm_buf, len);
|
|
|
|
return len;
|
|
}
|
|
|
|
int app_play_linein_onoff(bool onoff)
|
|
{
|
|
static bool isRun = false;
|
|
uint8_t *linein_audio_cap_buff = 0;
|
|
uint8_t *linein_audio_play_buff = 0;
|
|
uint8_t *linein_audio_loop_buf = NULL;
|
|
struct AF_STREAM_CONFIG_T stream_cfg;
|
|
|
|
uint8_t POSSIBLY_UNUSED *bt_eq_buff = NULL;
|
|
uint32_t POSSIBLY_UNUSED eq_buff_size;
|
|
uint8_t POSSIBLY_UNUSED play_samp_size;
|
|
|
|
TRACE_AUD_STREAM_I("[LINEIN_PLAYER] work:%d op:%d", isRun, onoff);
|
|
|
|
if (isRun == onoff)
|
|
return 0;
|
|
|
|
if (onoff){
|
|
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_104M);
|
|
app_overlay_select(APP_OVERLAY_A2DP);
|
|
app_audio_mempool_init();
|
|
app_audio_mempool_get_buff(&linein_audio_cap_buff, LINEIN_CAPTURE_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&linein_audio_play_buff, LINEIN_PLAYER_BUFFER_SIZE);
|
|
app_audio_mempool_get_buff(&linein_audio_loop_buf, LINEIN_PLAYER_BUFFER_SIZE<<2);
|
|
app_audio_pcmbuff_init(linein_audio_loop_buf, LINEIN_PLAYER_BUFFER_SIZE<<2);
|
|
|
|
#if (LINEIN_CAPTURE_CHANNEL == 1)
|
|
app_audio_mempool_get_buff((uint8_t **)&app_linein_play_cache, LINEIN_PLAYER_BUFFER_SIZE/2/2);
|
|
app_play_audio_lineinmode_init(LINEIN_CAPTURE_CHANNEL, LINEIN_PLAYER_BUFFER_SIZE/2/2);
|
|
#elif (LINEIN_CAPTURE_CHANNEL == 2)
|
|
app_play_audio_lineinmode_init(LINEIN_CAPTURE_CHANNEL, LINEIN_PLAYER_BUFFER_SIZE/2);
|
|
#endif
|
|
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)LINEIN_PLAYER_CHANNEL;
|
|
#if defined(__AUDIO_RESAMPLE__)
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_50781;
|
|
#else
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_44100;
|
|
#endif
|
|
#if FPGA==0
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
#else
|
|
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
|
#endif
|
|
stream_cfg.vol = stream_linein_volume;
|
|
TRACE_AUD_STREAM_I("[LINEIN_PLAYER] vol = %d",stream_linein_volume);
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
stream_cfg.handler = app_linein_need_pcm_data;
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(linein_audio_play_buff);
|
|
stream_cfg.data_size = LINEIN_PLAYER_BUFFER_SIZE;
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
sample_size_play_bt=stream_cfg.bits;
|
|
sample_rate_play_bt=stream_cfg.sample_rate;
|
|
data_size_play_bt=stream_cfg.data_size;
|
|
playback_buf_bt=stream_cfg.data_ptr;
|
|
playback_size_bt=stream_cfg.data_size;
|
|
if(sample_rate_play_bt==AUD_SAMPRATE_96000)
|
|
{
|
|
playback_samplerate_ratio_bt=4;
|
|
}
|
|
else
|
|
{
|
|
playback_samplerate_ratio_bt=8;
|
|
}
|
|
playback_ch_num_bt=stream_cfg.channel_num;
|
|
mid_p_8_old_l=0;
|
|
mid_p_8_old_r=0;
|
|
#endif
|
|
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
|
|
#if defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
|
|
eq_buff_size = stream_cfg.data_size*2;
|
|
#elif defined(__HW_FIR_EQ_PROCESS__) && !defined(__HW_IIR_EQ_PROCESS__)
|
|
|
|
play_samp_size = (stream_cfg.bits <= AUD_BITS_16) ? 2 : 4;
|
|
#if defined(CHIP_BEST2000)
|
|
eq_buff_size = stream_cfg.data_size * sizeof(int32_t) / play_samp_size;
|
|
#elif defined(CHIP_BEST1000)
|
|
eq_buff_size = stream_cfg.data_size * sizeof(int16_t) / play_samp_size;
|
|
#elif defined(CHIP_BEST2300) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)
|
|
eq_buff_size = stream_cfg.data_size;
|
|
#endif
|
|
|
|
#elif !defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
|
|
eq_buff_size = stream_cfg.data_size;
|
|
#else
|
|
eq_buff_size = 0;
|
|
bt_eq_buff = NULL;
|
|
#endif
|
|
|
|
if(eq_buff_size>0)
|
|
{
|
|
app_audio_mempool_get_buff(&bt_eq_buff, eq_buff_size);
|
|
}
|
|
|
|
#if defined(IBRT)
|
|
enum AUD_CHANNEL_NUM_T sw_ch_num = AUD_CHANNEL_NUM_1;
|
|
#else
|
|
enum AUD_CHANNEL_NUM_T sw_ch_num = stream_cfg.channel_num;
|
|
#endif
|
|
|
|
audio_process_open(stream_cfg.sample_rate, stream_cfg.bits, sw_ch_num, stream_cfg.channel_num, stream_cfg.data_size/stream_cfg.channel_num/(stream_cfg.bits <= AUD_BITS_16 ? 2 : 4)/2, bt_eq_buff, eq_buff_size);
|
|
|
|
#ifdef __SW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_SW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_SW_IIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_FIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_FIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_FIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_DAC_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_DAC_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_DAC_IIR,0));
|
|
#endif
|
|
|
|
#ifdef __HW_IIR_EQ_PROCESS__
|
|
bt_audio_set_eq(AUDIO_EQ_TYPE_HW_IIR,bt_audio_get_eq_index(AUDIO_EQ_TYPE_HW_IIR,0));
|
|
#endif
|
|
|
|
#ifdef ANC_APP
|
|
anc_status_record = 0xff;
|
|
#endif
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
uint8_t *bt_audio_buff = NULL;
|
|
stream_cfg.bits = sample_size_play_bt;
|
|
stream_cfg.channel_num = playback_ch_num_bt;
|
|
stream_cfg.sample_rate = sample_rate_play_bt;
|
|
stream_cfg.device = AUD_STREAM_USE_MC;
|
|
stream_cfg.vol = 0;
|
|
stream_cfg.handler = audio_mc_data_playback_a2dp;
|
|
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
|
|
|
app_audio_mempool_get_buff(&bt_audio_buff, data_size_play_bt*playback_samplerate_ratio_bt);
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(bt_audio_buff);
|
|
stream_cfg.data_size = data_size_play_bt*playback_samplerate_ratio_bt;
|
|
|
|
playback_buf_mc=stream_cfg.data_ptr;
|
|
playback_size_mc=stream_cfg.data_size;
|
|
|
|
anc_mc_run_init(hal_codec_anc_convert_rate(sample_rate_play_bt));
|
|
|
|
memset(delay_buf_bt,0,sizeof(delay_buf_bt));
|
|
|
|
af_stream_open(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg);
|
|
//ASSERT(ret == 0, "af_stream_open playback failed: %d", ret);
|
|
#endif
|
|
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
af_stream_start(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK);
|
|
#endif
|
|
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
#if defined(__AUDIO_RESAMPLE__)
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_50781;
|
|
#else
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_44100;
|
|
#endif
|
|
#if FPGA==0
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
#else
|
|
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
|
#endif
|
|
stream_cfg.io_path = AUD_INPUT_PATH_LINEIN;
|
|
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)LINEIN_CAPTURE_CHANNEL;
|
|
stream_cfg.channel_map = (enum AUD_CHANNEL_MAP_T)hal_codec_get_input_path_cfg(stream_cfg.io_path);
|
|
stream_cfg.handler = app_linein_pcm_come;
|
|
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(linein_audio_cap_buff);
|
|
stream_cfg.data_size = LINEIN_CAPTURE_BUFFER_SIZE;
|
|
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
}else {
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
audio_process_close();
|
|
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
|
|
|
app_overlay_unloadall();
|
|
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
|
}
|
|
|
|
isRun = onoff;
|
|
TRACE_AUD_STREAM_I("[LINEIN_PLAYER] end!\n");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int app_bt_stream_open(APP_AUDIO_STATUS* status)
|
|
{
|
|
int nRet = -1;
|
|
uint16_t player = status->id;
|
|
APP_AUDIO_STATUS next_status;
|
|
enum APP_SYSFREQ_FREQ_T freq = (enum APP_SYSFREQ_FREQ_T)status->freq;
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] prev:0x%x%s freq:%d", gStreamplayer, player2str(gStreamplayer), freq);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] cur:0x%x%s freq:%d", player, player2str(player), freq);
|
|
|
|
APP_AUDIO_STATUS streamToClose;
|
|
|
|
if (gStreamplayer != APP_BT_STREAM_INVALID)
|
|
{
|
|
#if !ISOLATED_AUDIO_STREAM_ENABLED
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] close 0x%x%s prev opening", gStreamplayer, player2str(gStreamplayer));
|
|
nRet = app_bt_stream_close(gStreamplayer);
|
|
if (nRet)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
streamToClose.id = gStreamplayer;
|
|
app_audio_list_rmv_callback(&streamToClose, &next_status, APP_BT_SETTING_Q_POS_TAIL, false);
|
|
}
|
|
#else
|
|
if (gStreamplayer & player)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] 0x%x%s has opened", player, player2str(player));
|
|
return -1;
|
|
}
|
|
|
|
if (player >= APP_BT_STREAM_BORDER_INDEX)
|
|
{
|
|
if (APP_BT_INPUT_STREAM_INDEX(gStreamplayer) > 0)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] close 0x%x%s prev opening", gStreamplayer, player2str(gStreamplayer));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (APP_BT_OUTPUT_STREAM_INDEX(gStreamplayer) > 0)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] close 0x%x%s prev opening", gStreamplayer, player2str(gStreamplayer));
|
|
uint16_t player2close = APP_BT_OUTPUT_STREAM_INDEX(gStreamplayer);
|
|
nRet = app_bt_stream_close(player2close);
|
|
if (nRet)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
streamToClose.id = player2close;
|
|
app_audio_list_rmv_callback(&streamToClose, &next_status, APP_BT_SETTING_Q_POS_TAIL, false);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
switch (player)
|
|
{
|
|
case APP_BT_STREAM_HFP_PCM:
|
|
case APP_BT_STREAM_HFP_CVSD:
|
|
case APP_BT_STREAM_HFP_VENDOR:
|
|
nRet = bt_sco_player(true, freq);
|
|
break;
|
|
case APP_BT_STREAM_A2DP_SBC:
|
|
case APP_BT_STREAM_A2DP_AAC:
|
|
case APP_BT_STREAM_A2DP_VENDOR:
|
|
nRet = bt_sbc_player(PLAYER_OPER_START, freq);
|
|
break;
|
|
#ifdef __FACTORY_MODE_SUPPORT__
|
|
case APP_FACTORYMODE_AUDIO_LOOP:
|
|
nRet = app_factorymode_audioloop(true, freq);
|
|
break;
|
|
#endif
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
case APP_PLAY_BACK_AUDIO:
|
|
nRet = app_play_audio_onoff(true, status);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef RB_CODEC
|
|
case APP_BT_STREAM_RBCODEC:
|
|
nRet = app_rbplay_audio_onoff(true, 0);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef AUDIO_LINEIN
|
|
case APP_PLAY_LINEIN_AUDIO:
|
|
nRet = app_play_linein_onoff(true);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(APP_LINEIN_A2DP_SOURCE)
|
|
case APP_A2DP_SOURCE_LINEIN_AUDIO:
|
|
nRet = app_a2dp_source_linein_on(true);
|
|
break;
|
|
#endif
|
|
#if defined(APP_I2S_A2DP_SOURCE)
|
|
case APP_A2DP_SOURCE_I2S_AUDIO:
|
|
nRet = app_a2dp_source_I2S_onoff(true);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
case APP_BT_STREAM_VOICEPATH:
|
|
nRet = app_voicepath_start_audio_stream();
|
|
break;
|
|
#endif
|
|
#ifdef __AI_VOICE__
|
|
case APP_BT_STREAM_AI_VOICE:
|
|
nRet = app_ai_voice_start_mic_stream();
|
|
break;
|
|
#endif
|
|
#ifdef __THIRDPARTY
|
|
case APP_BT_STREAM_THIRDPARTY_VOICE:
|
|
nRet = app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_KWS, THIRDPARTY_MIC_OPEN);
|
|
break;
|
|
#endif
|
|
default:
|
|
nRet = -1;
|
|
break;
|
|
}
|
|
|
|
if (!nRet)
|
|
{
|
|
gStreamplayer |= player;
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][OPEN] updated to 0x%x%s", gStreamplayer, player2str(gStreamplayer));
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
int app_bt_stream_close(uint16_t player)
|
|
{
|
|
int nRet = -1;
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][CLOSE] gStreamplayer: 0x%x%s", gStreamplayer, player2str(gStreamplayer));
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][CLOSE] player:0x%x%s", gStreamplayer, player2str(gStreamplayer));
|
|
|
|
if ((gStreamplayer & player) != player)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
switch (player)
|
|
{
|
|
case APP_BT_STREAM_HFP_PCM:
|
|
case APP_BT_STREAM_HFP_CVSD:
|
|
case APP_BT_STREAM_HFP_VENDOR:
|
|
nRet = bt_sco_player(false, APP_SYSFREQ_32K);
|
|
break;
|
|
case APP_BT_STREAM_A2DP_SBC:
|
|
case APP_BT_STREAM_A2DP_AAC:
|
|
case APP_BT_STREAM_A2DP_VENDOR:
|
|
nRet = bt_sbc_player(PLAYER_OPER_STOP, APP_SYSFREQ_32K);
|
|
break;
|
|
#ifdef __FACTORY_MODE_SUPPORT__
|
|
case APP_FACTORYMODE_AUDIO_LOOP:
|
|
nRet = app_factorymode_audioloop(false, APP_SYSFREQ_32K);
|
|
break;
|
|
#endif
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
case APP_PLAY_BACK_AUDIO:
|
|
nRet = app_play_audio_onoff(false, NULL);
|
|
break;
|
|
#endif
|
|
#ifdef RB_CODEC
|
|
case APP_BT_STREAM_RBCODEC:
|
|
nRet = app_rbplay_audio_onoff(false, 0);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef AUDIO_LINEIN
|
|
case APP_PLAY_LINEIN_AUDIO:
|
|
nRet = app_play_linein_onoff(false);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(APP_LINEIN_A2DP_SOURCE)
|
|
case APP_A2DP_SOURCE_LINEIN_AUDIO:
|
|
nRet = app_a2dp_source_linein_on(false);
|
|
break;
|
|
#endif
|
|
#if defined(APP_I2S_A2DP_SOURCE)
|
|
case APP_A2DP_SOURCE_I2S_AUDIO:
|
|
nRet = app_a2dp_source_I2S_onoff(false);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
case APP_BT_STREAM_VOICEPATH:
|
|
nRet = app_voicepath_stop_audio_stream();
|
|
break;
|
|
#endif
|
|
#ifdef __AI_VOICE__
|
|
case APP_BT_STREAM_AI_VOICE:
|
|
nRet = app_ai_voice_stop_mic_stream();
|
|
break;
|
|
#endif
|
|
#ifdef __THIRDPARTY
|
|
case APP_BT_STREAM_THIRDPARTY_VOICE:
|
|
nRet = app_thirdparty_specific_lib_event_handle(THIRDPARTY_FUNC_KWS, THIRDPARTY_MIC_CLOSE);
|
|
break;
|
|
#endif
|
|
default:
|
|
nRet = -1;
|
|
break;
|
|
}
|
|
if (!nRet)
|
|
{
|
|
gStreamplayer &= (~player);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][CLOSE] updated to 0x%x%s", gStreamplayer, player2str(gStreamplayer));
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
int app_bt_stream_setup(uint16_t player, uint8_t status)
|
|
{
|
|
int nRet = -1;
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][SETUP] prev:%d%s sample:%d", gStreamplayer, player2str(gStreamplayer), status);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][SETUP] cur:%d%s sample:%d", player, player2str(player), status);
|
|
|
|
switch (player)
|
|
{
|
|
case APP_BT_STREAM_HFP_PCM:
|
|
case APP_BT_STREAM_HFP_CVSD:
|
|
case APP_BT_STREAM_HFP_VENDOR:
|
|
break;
|
|
case APP_BT_STREAM_A2DP_SBC:
|
|
case APP_BT_STREAM_A2DP_AAC:
|
|
case APP_BT_STREAM_A2DP_VENDOR:
|
|
bt_sbc_player_setup(status);
|
|
break;
|
|
default:
|
|
nRet = -1;
|
|
break;
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
int app_bt_stream_restart(APP_AUDIO_STATUS* status)
|
|
{
|
|
int nRet = -1;
|
|
uint16_t player = status->id;
|
|
enum APP_SYSFREQ_FREQ_T freq = (enum APP_SYSFREQ_FREQ_T)status->freq;
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESTART] prev:%d%s freq:%d", gStreamplayer, player2str(gStreamplayer), freq);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESTART] cur:%d%s freq:%d", player, player2str(player), freq);
|
|
|
|
if ((gStreamplayer & player) != player)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
switch (player)
|
|
{
|
|
case APP_BT_STREAM_HFP_PCM:
|
|
case APP_BT_STREAM_HFP_CVSD:
|
|
case APP_BT_STREAM_HFP_VENDOR:
|
|
nRet = bt_sco_player(false, freq);
|
|
nRet = bt_sco_player(true, freq);
|
|
break;
|
|
case APP_BT_STREAM_A2DP_SBC:
|
|
case APP_BT_STREAM_A2DP_AAC:
|
|
case APP_BT_STREAM_A2DP_VENDOR:
|
|
#if defined(IBRT)
|
|
ibrt_a2dp_status_t a2dp_status;
|
|
a2dp_ibrt_sync_get_status(&a2dp_status);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESTART] state:%d", a2dp_status.state);
|
|
if (a2dp_status.state == BTIF_AVDTP_STRM_STATE_STREAMING){
|
|
if (app_audio_manager_a2dp_is_active(BT_DEVICE_ID_1)){
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESTART] resume");
|
|
nRet = bt_sbc_player(PLAYER_OPER_STOP, freq);
|
|
nRet = bt_sbc_player(PLAYER_OPER_START, freq);
|
|
}else{
|
|
if (app_ibrt_ui_is_profile_exchanged()){
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESTART] force_audio_retrigger");
|
|
app_audio_manager_sendrequest(APP_BT_STREAM_MANAGER_START,BT_STREAM_SBC, BT_DEVICE_ID_1,MAX_RECORD_NUM);
|
|
app_ibrt_if_force_audio_retrigger();
|
|
}
|
|
}
|
|
}
|
|
#elif defined(__BT_ONE_BRING_TWO__)
|
|
if (btif_me_get_activeCons()>1)
|
|
{
|
|
enum APP_SYSFREQ_FREQ_T sysfreq;
|
|
|
|
#ifdef A2DP_CP_ACCEL
|
|
sysfreq = APP_SYSFREQ_26M;
|
|
#else
|
|
sysfreq = APP_SYSFREQ_104M;
|
|
#endif
|
|
app_sysfreq_req(APP_SYSFREQ_USER_BT_A2DP, sysfreq);
|
|
bt_media_volume_ptr_update_by_mediatype(BT_STREAM_SBC);
|
|
app_bt_stream_volumeset(btdevice_volume_p->a2dp_vol);
|
|
}
|
|
#endif
|
|
break;
|
|
#ifdef __FACTORY_MODE_SUPPORT__
|
|
case APP_FACTORYMODE_AUDIO_LOOP:
|
|
break;
|
|
#endif
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
case APP_PLAY_BACK_AUDIO:
|
|
break;
|
|
#endif
|
|
default:
|
|
nRet = -1;
|
|
break;
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
void app_bt_stream_volumeup(void)
|
|
{
|
|
#if defined AUDIO_LINEIN
|
|
if(app_bt_stream_isrun(APP_PLAY_LINEIN_AUDIO))
|
|
{
|
|
stream_linein_volume ++;
|
|
if (stream_linein_volume > TGT_VOLUME_LEVEL_15)
|
|
stream_linein_volume = TGT_VOLUME_LEVEL_15;
|
|
app_bt_stream_volumeset(stream_linein_volume);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UP] set linein volume %d\n", stream_linein_volume);
|
|
}else
|
|
#endif
|
|
{
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM))
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UP] hfp volume");
|
|
|
|
int8_t updatedVol = btdevice_volume_p->hfp_vol;
|
|
updatedVol++;
|
|
if (updatedVol > TGT_VOLUME_LEVEL_15)
|
|
{
|
|
updatedVol = TGT_VOLUME_LEVEL_15;
|
|
}
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->hfp_vol = updatedVol;
|
|
nv_record_post_write_operation(lock);
|
|
current_btdevice_volume.hfp_vol=updatedVol;
|
|
if (updatedVol < TGT_VOLUME_LEVEL_15)
|
|
{
|
|
app_bt_stream_volumeset(updatedVol);
|
|
}
|
|
if (btdevice_volume_p->hfp_vol == TGT_VOLUME_LEVEL_15)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
else if ((app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)) ||
|
|
(app_bt_stream_isrun(APP_BT_STREAM_INVALID)))
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UP] a2dp volume");
|
|
int8_t updatedVol = btdevice_volume_p->a2dp_vol;
|
|
updatedVol++;
|
|
if (updatedVol > TGT_VOLUME_LEVEL_15)
|
|
{
|
|
updatedVol = TGT_VOLUME_LEVEL_15;
|
|
}
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->a2dp_vol = updatedVol;
|
|
nv_record_post_write_operation(lock);
|
|
current_btdevice_volume.a2dp_vol=updatedVol;
|
|
if (updatedVol < TGT_VOLUME_LEVEL_15)
|
|
{
|
|
app_bt_stream_volumeset(updatedVol);
|
|
}
|
|
if (btdevice_volume_p->a2dp_vol == TGT_VOLUME_LEVEL_15)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UP] a2dp: %d", btdevice_volume_p->a2dp_vol);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UP] hfp: %d", btdevice_volume_p->hfp_vol);
|
|
}
|
|
#ifndef FPGA
|
|
nv_record_touch_cause_flush();
|
|
#endif
|
|
}
|
|
|
|
void app_bt_set_volume(uint16_t type,uint8_t level)
|
|
{
|
|
if ((type&APP_BT_STREAM_HFP_PCM) && app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM)) {
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL] set hfp volume");
|
|
if (level >= TGT_VOLUME_LEVEL_MUTE && level <= TGT_VOLUME_LEVEL_15)
|
|
{
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->hfp_vol = level;
|
|
nv_record_post_write_operation(lock);
|
|
app_bt_stream_volumeset(btdevice_volume_p->hfp_vol);
|
|
}
|
|
if (btdevice_volume_p->hfp_vol == TGT_VOLUME_LEVEL_0)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
}
|
|
if ((type&APP_BT_STREAM_A2DP_SBC) && ((app_bt_stream_isrun(APP_BT_STREAM_INVALID)) ||
|
|
(app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)))) {
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL] set a2dp volume");
|
|
if (level >= TGT_VOLUME_LEVEL_MUTE && level <= TGT_VOLUME_LEVEL_15)
|
|
{
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->a2dp_vol = level;
|
|
nv_record_post_write_operation(lock);
|
|
app_bt_stream_volumeset(btdevice_volume_p->a2dp_vol);
|
|
}
|
|
if (btdevice_volume_p->a2dp_vol == TGT_VOLUME_LEVEL_MUTE)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL] a2dp: %d", btdevice_volume_p->a2dp_vol);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL] hfp: %d", btdevice_volume_p->hfp_vol);
|
|
#ifndef FPGA
|
|
nv_record_touch_cause_flush();
|
|
#endif
|
|
}
|
|
|
|
void app_bt_stream_volumedown(void)
|
|
{
|
|
#if defined AUDIO_LINEIN
|
|
if(app_bt_stream_isrun(APP_PLAY_LINEIN_AUDIO))
|
|
{
|
|
stream_linein_volume --;
|
|
if (stream_linein_volume < TGT_VOLUME_LEVEL_MUTE)
|
|
stream_linein_volume = TGT_VOLUME_LEVEL_MUTE;
|
|
app_bt_stream_volumeset(stream_linein_volume);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][DONW] set linein volume %d\n", stream_linein_volume);
|
|
}else
|
|
#endif
|
|
{
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_HFP_PCM)) {
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][DONW] set hfp volume");
|
|
|
|
int8_t updatedVol = btdevice_volume_p->hfp_vol;
|
|
updatedVol--;
|
|
if (updatedVol < TGT_VOLUME_LEVEL_0)
|
|
{
|
|
updatedVol = TGT_VOLUME_LEVEL_0;
|
|
}
|
|
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->hfp_vol = updatedVol;
|
|
nv_record_post_write_operation(lock);
|
|
current_btdevice_volume.hfp_vol=updatedVol;
|
|
app_bt_stream_volumeset(updatedVol);
|
|
if (btdevice_volume_p->hfp_vol == TGT_VOLUME_LEVEL_0)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
} else if ((app_bt_stream_isrun(APP_BT_STREAM_INVALID)) ||
|
|
(app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC))) {
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][DONW] set a2dp volume");
|
|
int8_t updatedVol = btdevice_volume_p->a2dp_vol;
|
|
updatedVol--;
|
|
if (updatedVol < TGT_VOLUME_LEVEL_MUTE)
|
|
{
|
|
updatedVol = TGT_VOLUME_LEVEL_MUTE;
|
|
}
|
|
|
|
uint32_t lock = nv_record_pre_write_operation();
|
|
btdevice_volume_p->a2dp_vol = updatedVol;
|
|
nv_record_post_write_operation(lock);
|
|
current_btdevice_volume.a2dp_vol=updatedVol;
|
|
app_bt_stream_volumeset(updatedVol);
|
|
if (btdevice_volume_p->a2dp_vol == TGT_VOLUME_LEVEL_MUTE)
|
|
{
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
media_PlayAudio(AUD_ID_BT_WARNING,0);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][DONW] a2dp: %d", btdevice_volume_p->a2dp_vol);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][DONW] hfp: %d", btdevice_volume_p->hfp_vol);
|
|
}
|
|
#ifndef FPGA
|
|
nv_record_touch_cause_flush();
|
|
#endif
|
|
}
|
|
|
|
void app_bt_stream_volumeset_handler(int8_t vol)
|
|
{
|
|
uint32_t ret;
|
|
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
|
ret = af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, false);
|
|
if (ret == 0) {
|
|
stream_cfg->vol = vol;
|
|
af_stream_setup(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, stream_cfg);
|
|
}
|
|
#if (defined(AUDIO_ANC_FB_MC)||defined(AUDIO_ANC_FB_MC_SCO)) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
|
ret = af_stream_get_cfg(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg, false);
|
|
if (ret == 0) {
|
|
stream_cfg->vol = vol;
|
|
af_stream_setup(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, stream_cfg);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int app_bt_stream_volumeset(int8_t vol)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][SET] vol=%d", vol);
|
|
|
|
if (vol > TGT_VOLUME_LEVEL_15)
|
|
vol = TGT_VOLUME_LEVEL_15;
|
|
if (vol < TGT_VOLUME_LEVEL_MUTE)
|
|
vol = TGT_VOLUME_LEVEL_MUTE;
|
|
|
|
stream_local_volume = vol;
|
|
#ifdef MIX_AUDIO_PROMPT_WITH_A2DP_MEDIA_ENABLED
|
|
if ((!app_bt_stream_isrun(APP_PLAY_BACK_AUDIO)) &&
|
|
(audio_prompt_is_allow_update_volume()))
|
|
#else
|
|
if (!app_bt_stream_isrun(APP_PLAY_BACK_AUDIO))
|
|
#endif
|
|
{
|
|
app_bt_stream_volumeset_handler(vol);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int app_bt_stream_local_volume_get(void)
|
|
{
|
|
return stream_local_volume;
|
|
}
|
|
|
|
uint8_t app_bt_stream_a2dpvolume_get(void)
|
|
{
|
|
// return btdevice_volume_p->a2dp_vol;
|
|
return current_btdevice_volume.a2dp_vol;
|
|
}
|
|
|
|
uint8_t app_bt_stream_hfpvolume_get(void)
|
|
{
|
|
//return btdevice_volume_p->hfp_vol;
|
|
return current_btdevice_volume.hfp_vol;
|
|
|
|
}
|
|
|
|
void app_bt_stream_a2dpvolume_reset(void)
|
|
{
|
|
btdevice_volume_p->a2dp_vol = NVRAM_ENV_STREAM_VOLUME_A2DP_VOL_DEFAULT ;
|
|
current_btdevice_volume.a2dp_vol=NVRAM_ENV_STREAM_VOLUME_A2DP_VOL_DEFAULT;
|
|
}
|
|
|
|
void app_bt_stream_hfpvolume_reset(void)
|
|
{
|
|
btdevice_volume_p->hfp_vol = NVRAM_ENV_STREAM_VOLUME_HFP_VOL_DEFAULT;
|
|
current_btdevice_volume.hfp_vol=NVRAM_ENV_STREAM_VOLUME_HFP_VOL_DEFAULT;
|
|
}
|
|
|
|
void app_bt_stream_volume_ptr_update(uint8_t *bdAddr)
|
|
{
|
|
static struct btdevice_volume stream_volume = {NVRAM_ENV_STREAM_VOLUME_A2DP_VOL_DEFAULT,NVRAM_ENV_STREAM_VOLUME_HFP_VOL_DEFAULT};
|
|
|
|
#ifndef FPGA
|
|
nvrec_btdevicerecord *record = NULL;
|
|
|
|
memset(¤t_btdevice_volume, 0, sizeof(btdevice_volume));
|
|
|
|
if (bdAddr && !nv_record_btdevicerecord_find((bt_bdaddr_t*)bdAddr,&record))
|
|
{
|
|
btdevice_volume_p = &(record->device_vol);
|
|
DUMP8("0x%02x ", bdAddr, BTIF_BD_ADDR_SIZE);
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UPDATE] a2dp_vol:%d hfp_vol:%d ptr:%p", btdevice_volume_p->a2dp_vol, btdevice_volume_p->hfp_vol,btdevice_volume_p);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
btdevice_volume_p = &stream_volume;
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][VOL][UPDATE] default");
|
|
if (bdAddr){
|
|
DUMP8("0x%02x ", bdAddr, BTIF_BD_ADDR_SIZE);
|
|
}
|
|
}
|
|
current_btdevice_volume.a2dp_vol=btdevice_volume_p->a2dp_vol;
|
|
current_btdevice_volume.hfp_vol=btdevice_volume_p->hfp_vol;
|
|
|
|
}
|
|
|
|
struct btdevice_volume * app_bt_stream_volume_get_ptr(void)
|
|
{
|
|
return btdevice_volume_p;
|
|
}
|
|
|
|
bool app_bt_stream_isrun(uint16_t player)
|
|
{
|
|
if ((gStreamplayer & player) == player)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int app_bt_stream_closeall()
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][CLOSEALL]");
|
|
|
|
bt_sco_player(false, APP_SYSFREQ_32K);
|
|
bt_sbc_player(PLAYER_OPER_STOP, APP_SYSFREQ_32K);
|
|
|
|
#ifdef MEDIA_PLAYER_SUPPORT
|
|
app_play_audio_onoff(false, 0);
|
|
#endif
|
|
#ifdef RB_CODEC
|
|
app_rbplay_audio_onoff(false, 0);
|
|
#endif
|
|
|
|
#ifdef VOICE_DATAPATH
|
|
app_voicepath_stop_audio_stream();
|
|
#endif
|
|
|
|
gStreamplayer = APP_BT_STREAM_INVALID;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void app_bt_stream_copy_track_one_to_two_24bits(int32_t *dst_buf, int32_t *src_buf, uint32_t src_len)
|
|
{
|
|
// Copy from tail so that it works even if dst_buf == src_buf
|
|
for (int i = (int)(src_len - 1); i >= 0; i--)
|
|
{
|
|
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_copy_track_one_to_two_16bits(int16_t *dst_buf, int16_t *src_buf, uint32_t src_len)
|
|
{
|
|
// Copy from tail so that it works even if dst_buf == src_buf
|
|
for (int i = (int)(src_len - 1); i >= 0; i--)
|
|
{
|
|
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_copy_track_two_to_one_16bits(int16_t *dst_buf, int16_t *src_buf, uint32_t dst_len)
|
|
{
|
|
for (uint32_t i = 0; i < dst_len; i++)
|
|
{
|
|
dst_buf[i] = src_buf[i*2];
|
|
}
|
|
}
|
|
|
|
void app_bt_stream_adaptive_frequency_adjusting(void)
|
|
{
|
|
#if 0//(A2DP_DECODER_VER == 2)
|
|
if (app_bt_stream_isrun(APP_BT_STREAM_A2DP_SBC)){
|
|
if (!a2dp_audio_sysfreq_boost_running()){
|
|
a2dp_audio_sysfreq_boost_start(1);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef PLAYBACK_FORCE_48K
|
|
static int app_force48k_resample_iter(uint8_t *buf, uint32_t len)
|
|
{
|
|
uint8_t codec_type = bt_sbc_player_get_codec_type();
|
|
uint32_t overlay_id = 0;
|
|
if(0){
|
|
#if defined(A2DP_LHDC_ON)
|
|
}else if(codec_type == BTIF_AVDTP_CODEC_TYPE_LHDC){
|
|
overlay_id = APP_OVERLAY_A2DP_LHDC;
|
|
#endif
|
|
#if defined(A2DP_AAC_ON)
|
|
}else if(codec_type == BTIF_AVDTP_CODEC_TYPE_MPEG2_4_AAC){
|
|
overlay_id = APP_OVERLAY_A2DP_AAC;
|
|
#endif
|
|
}else if(codec_type == BTIF_AVDTP_CODEC_TYPE_SBC){
|
|
overlay_id = APP_OVERLAY_A2DP;
|
|
}
|
|
a2dp_audio_more_data(overlay_id, buf, len);
|
|
return 0;
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_force48k_resample_any_open(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step)
|
|
{
|
|
return app_playback_resample_any_open(chans, cb, iter_len, ratio_step);
|
|
}
|
|
#endif
|
|
|
|
// =======================================================
|
|
// APP RESAMPLE
|
|
// =======================================================
|
|
|
|
#ifndef MIX_MIC_DURING_MUSIC
|
|
#include "resample_coef.h"
|
|
#endif
|
|
|
|
static APP_RESAMPLE_BUF_ALLOC_CALLBACK resamp_buf_alloc = app_audio_mempool_get_buff;
|
|
|
|
static void memzero_int16(void *dst, uint32_t len)
|
|
{
|
|
if (dst)
|
|
{
|
|
int16_t *dst16 = (int16_t *)dst;
|
|
int16_t *dst16_end = dst16 + len / 2;
|
|
|
|
while (dst16 < dst16_end)
|
|
{
|
|
*dst16++ = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE_AUD_STREAM_I("WRN: receive null pointer");
|
|
}
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_resample_open_with_preallocated_buf(enum AUD_STREAM_T stream, const struct RESAMPLE_COEF_T *coef, enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step, uint8_t* buf, uint32_t bufSize)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][PROMPT_MIXER][OPEN]");
|
|
struct APP_RESAMPLE_T *resamp;
|
|
struct RESAMPLE_CFG_T cfg;
|
|
enum RESAMPLE_STATUS_T status;
|
|
uint32_t size, resamp_size;
|
|
|
|
resamp_size = audio_resample_ex_get_buffer_size(chans, AUD_BITS_16, coef->phase_coef_num);
|
|
|
|
size = sizeof(struct APP_RESAMPLE_T);
|
|
size += ALIGN(iter_len, 4);
|
|
size += resamp_size;
|
|
|
|
ASSERT(size < bufSize, "Pre-allocated buffer size %d is smaller than the needed size %d",
|
|
bufSize, size);
|
|
|
|
resamp = (struct APP_RESAMPLE_T *)buf;
|
|
buf += sizeof(*resamp);
|
|
resamp->stream = stream;
|
|
resamp->cb = cb;
|
|
resamp->iter_buf = buf;
|
|
buf += ALIGN(iter_len, 4);
|
|
resamp->iter_len = iter_len;
|
|
resamp->offset = iter_len;
|
|
resamp->ratio_step = ratio_step;
|
|
|
|
memset(&cfg, 0, sizeof(cfg));
|
|
cfg.chans = chans;
|
|
cfg.bits = AUD_BITS_16;
|
|
cfg.ratio_step = ratio_step;
|
|
cfg.coef = coef;
|
|
cfg.buf = buf;
|
|
cfg.size = resamp_size;
|
|
|
|
status = audio_resample_ex_open(&cfg, (RESAMPLE_ID *)&resamp->id);
|
|
ASSERT(status == RESAMPLE_STATUS_OK, "%s: Failed to open resample: %d", __func__, status);
|
|
|
|
#ifdef CHIP_BEST1000
|
|
hal_cmu_audio_resample_enable();
|
|
#endif
|
|
|
|
return resamp;
|
|
}
|
|
|
|
|
|
static struct APP_RESAMPLE_T *app_resample_open(enum AUD_STREAM_T stream, const struct RESAMPLE_COEF_T *coef, enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step)
|
|
{
|
|
TRACE_AUD_STREAM_I("[STRM_PLAYER][RESAMPLE][OPEN] ratio: %d/1000", uint32_t(ratio_step * 1000));
|
|
struct APP_RESAMPLE_T *resamp;
|
|
struct RESAMPLE_CFG_T cfg;
|
|
enum RESAMPLE_STATUS_T status;
|
|
uint32_t size, resamp_size;
|
|
uint8_t *buf;
|
|
|
|
resamp_size = audio_resample_ex_get_buffer_size(chans, AUD_BITS_16, coef->phase_coef_num);
|
|
|
|
size = sizeof(struct APP_RESAMPLE_T);
|
|
size += ALIGN(iter_len, 4);
|
|
size += resamp_size;
|
|
|
|
resamp_buf_alloc(&buf, size);
|
|
|
|
resamp = (struct APP_RESAMPLE_T *)buf;
|
|
buf += sizeof(*resamp);
|
|
resamp->stream = stream;
|
|
resamp->cb = cb;
|
|
resamp->iter_buf = buf;
|
|
buf += ALIGN(iter_len, 4);
|
|
resamp->iter_len = iter_len;
|
|
resamp->offset = iter_len;
|
|
resamp->ratio_step = ratio_step;
|
|
|
|
memset(&cfg, 0, sizeof(cfg));
|
|
cfg.chans = chans;
|
|
cfg.bits = AUD_BITS_16;
|
|
cfg.ratio_step = ratio_step;
|
|
cfg.coef = coef;
|
|
cfg.buf = buf;
|
|
cfg.size = resamp_size;
|
|
|
|
status = audio_resample_ex_open(&cfg, (RESAMPLE_ID *)&resamp->id);
|
|
ASSERT(status == RESAMPLE_STATUS_OK, "%s: Failed to open resample: %d", __func__, status);
|
|
|
|
#ifdef CHIP_BEST1000
|
|
hal_cmu_audio_resample_enable();
|
|
#endif
|
|
|
|
return resamp;
|
|
}
|
|
|
|
static int app_resample_close(struct APP_RESAMPLE_T *resamp)
|
|
{
|
|
#ifdef CHIP_BEST1000
|
|
hal_cmu_audio_resample_disable();
|
|
#endif
|
|
|
|
if (resamp)
|
|
{
|
|
audio_resample_ex_close((RESAMPLE_ID *)resamp->id);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_playback_resample_open(enum AUD_SAMPRATE_T sample_rate, enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = NULL;
|
|
|
|
if (sample_rate == AUD_SAMPRATE_8000)
|
|
{
|
|
coef = &resample_coef_8k_to_8p4k;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_16000)
|
|
{
|
|
coef = &resample_coef_8k_to_8p4k;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_32000)
|
|
{
|
|
coef = &resample_coef_32k_to_50p7k;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_44100)
|
|
{
|
|
coef = &resample_coef_44p1k_to_50p7k;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_48000)
|
|
{
|
|
coef = &resample_coef_48k_to_50p7k;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false, "%s: Bad sample rate: %u", __func__, sample_rate);
|
|
}
|
|
|
|
return app_resample_open(AUD_STREAM_PLAYBACK, coef, chans, cb, iter_len, 0);
|
|
}
|
|
|
|
#ifdef RESAMPLE_ANY_SAMPLE_RATE
|
|
struct APP_RESAMPLE_T *app_playback_resample_any_open(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = &resample_coef_any_up256;
|
|
|
|
return app_resample_open(AUD_STREAM_PLAYBACK, coef, chans, cb, iter_len, ratio_step);
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_playback_resample_any_open_with_pre_allocated_buffer(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step, uint8_t* ptrBuf, uint32_t bufSize)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = &resample_coef_any_up256;
|
|
|
|
return app_resample_open_with_preallocated_buf(
|
|
AUD_STREAM_PLAYBACK, coef, chans, cb, iter_len, ratio_step, ptrBuf, bufSize);
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_capture_resample_14k7_to_16k(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step, uint8_t* ptrBuf, uint32_t bufSize)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = &resample_coef_44p1k_to_48k;
|
|
|
|
return app_resample_open_with_preallocated_buf(
|
|
AUD_STREAM_PLAYBACK, coef, chans, cb, iter_len, ratio_step, ptrBuf, bufSize);
|
|
}
|
|
|
|
#endif
|
|
|
|
int app_playback_resample_close(struct APP_RESAMPLE_T *resamp)
|
|
{
|
|
return app_resample_close(resamp);
|
|
}
|
|
|
|
int app_playback_resample_run(struct APP_RESAMPLE_T *resamp, uint8_t *buf, uint32_t len)
|
|
{
|
|
uint32_t in_size, out_size;
|
|
struct RESAMPLE_IO_BUF_T io;
|
|
enum RESAMPLE_STATUS_T status;
|
|
int ret;
|
|
//uint32_t lock;
|
|
|
|
if (resamp == NULL)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
io.out_cyclic_start = NULL;
|
|
io.out_cyclic_end = NULL;
|
|
|
|
if (resamp->offset < resamp->iter_len)
|
|
{
|
|
io.in = resamp->iter_buf + resamp->offset;
|
|
io.in_size = resamp->iter_len - resamp->offset;
|
|
io.out = buf;
|
|
io.out_size = len;
|
|
|
|
//lock = int_lock();
|
|
status = audio_resample_ex_run((RESAMPLE_ID *)resamp->id, &io, &in_size, &out_size);
|
|
//int_unlock(lock);
|
|
if (status != RESAMPLE_STATUS_OUT_FULL && status != RESAMPLE_STATUS_IN_EMPTY &&
|
|
status != RESAMPLE_STATUS_DONE)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
buf += out_size;
|
|
len -= out_size;
|
|
resamp->offset += in_size;
|
|
|
|
ASSERT(len == 0 || resamp->offset == resamp->iter_len,
|
|
"%s: Bad resample offset: len=%d offset=%u iter_len=%u",
|
|
__func__, len, resamp->offset, resamp->iter_len);
|
|
}
|
|
|
|
while (len)
|
|
{
|
|
ret = resamp->cb(resamp->iter_buf, resamp->iter_len);
|
|
if (ret)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
io.in = resamp->iter_buf;
|
|
io.in_size = resamp->iter_len;
|
|
io.out = buf;
|
|
io.out_size = len;
|
|
|
|
//lock = int_lock();
|
|
status = audio_resample_ex_run((RESAMPLE_ID *)resamp->id, &io, &in_size, &out_size);
|
|
//int_unlock(lock);
|
|
if (status != RESAMPLE_STATUS_OUT_FULL && status != RESAMPLE_STATUS_IN_EMPTY &&
|
|
status != RESAMPLE_STATUS_DONE)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
ASSERT(out_size <= len, "%s: Bad resample out_size: out_size=%u len=%d", __func__, out_size, len);
|
|
ASSERT(in_size <= resamp->iter_len, "%s: Bad resample in_size: in_size=%u iter_len=%u", __func__, in_size, resamp->iter_len);
|
|
|
|
buf += out_size;
|
|
len -= out_size;
|
|
if (in_size != resamp->iter_len)
|
|
{
|
|
resamp->offset = in_size;
|
|
|
|
ASSERT(len == 0, "%s: Bad resample len: len=%d out_size=%u", __func__, len, out_size);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
_err_exit:
|
|
if (resamp)
|
|
{
|
|
app_resample_reset(resamp);
|
|
}
|
|
|
|
memzero_int16(buf, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
struct APP_RESAMPLE_T *app_capture_resample_open(enum AUD_SAMPRATE_T sample_rate, enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = NULL;
|
|
|
|
if (sample_rate == AUD_SAMPRATE_8000)
|
|
{
|
|
coef = &resample_coef_8p4k_to_8k;
|
|
}
|
|
else if (sample_rate == AUD_SAMPRATE_16000)
|
|
{
|
|
// Same coef as 8K sample rate
|
|
coef = &resample_coef_8p4k_to_8k;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false, "%s: Bad sample rate: %u", __func__, sample_rate);
|
|
}
|
|
|
|
return app_resample_open(AUD_STREAM_CAPTURE, coef, chans, cb, iter_len, 0);
|
|
|
|
}
|
|
|
|
#ifdef RESAMPLE_ANY_SAMPLE_RATE
|
|
struct APP_RESAMPLE_T *app_capture_resample_any_open(enum AUD_CHANNEL_NUM_T chans,
|
|
APP_RESAMPLE_ITER_CALLBACK cb, uint32_t iter_len,
|
|
float ratio_step)
|
|
{
|
|
const struct RESAMPLE_COEF_T *coef = &resample_coef_any_up256;
|
|
return app_resample_open(AUD_STREAM_CAPTURE, coef, chans, cb, iter_len, ratio_step);
|
|
}
|
|
#endif
|
|
|
|
int app_capture_resample_close(struct APP_RESAMPLE_T *resamp)
|
|
{
|
|
return app_resample_close(resamp);
|
|
}
|
|
|
|
int app_capture_resample_run(struct APP_RESAMPLE_T *resamp, uint8_t *buf, uint32_t len)
|
|
{
|
|
uint32_t in_size, out_size;
|
|
struct RESAMPLE_IO_BUF_T io;
|
|
enum RESAMPLE_STATUS_T status;
|
|
int ret;
|
|
|
|
if (resamp == NULL)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
io.out_cyclic_start = NULL;
|
|
io.out_cyclic_end = NULL;
|
|
|
|
if (resamp->offset < resamp->iter_len)
|
|
{
|
|
io.in = buf;
|
|
io.in_size = len;
|
|
io.out = resamp->iter_buf + resamp->offset;
|
|
io.out_size = resamp->iter_len - resamp->offset;
|
|
|
|
status = audio_resample_ex_run((RESAMPLE_ID *)resamp->id, &io, &in_size, &out_size);
|
|
if (status != RESAMPLE_STATUS_OUT_FULL && status != RESAMPLE_STATUS_IN_EMPTY &&
|
|
status != RESAMPLE_STATUS_DONE)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
buf += in_size;
|
|
len -= in_size;
|
|
resamp->offset += out_size;
|
|
|
|
ASSERT(len == 0 || resamp->offset == resamp->iter_len,
|
|
"%s: Bad resample offset: len=%d offset=%u iter_len=%u",
|
|
__func__, len, resamp->offset, resamp->iter_len);
|
|
|
|
if (resamp->offset == resamp->iter_len)
|
|
{
|
|
ret = resamp->cb(resamp->iter_buf, resamp->iter_len);
|
|
if (ret)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
while (len)
|
|
{
|
|
io.in = buf;
|
|
io.in_size = len;
|
|
io.out = resamp->iter_buf;
|
|
io.out_size = resamp->iter_len;
|
|
|
|
status = audio_resample_ex_run((RESAMPLE_ID *)resamp->id, &io, &in_size, &out_size);
|
|
if (status != RESAMPLE_STATUS_OUT_FULL && status != RESAMPLE_STATUS_IN_EMPTY &&
|
|
status != RESAMPLE_STATUS_DONE)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
|
|
ASSERT(in_size <= len, "%s: Bad resample in_size: in_size=%u len=%u", __func__, in_size, len);
|
|
ASSERT(out_size <= resamp->iter_len, "%s: Bad resample out_size: out_size=%u iter_len=%u", __func__, out_size, resamp->iter_len);
|
|
|
|
buf += in_size;
|
|
len -= in_size;
|
|
if (out_size == resamp->iter_len)
|
|
{
|
|
ret = resamp->cb(resamp->iter_buf, resamp->iter_len);
|
|
if (ret)
|
|
{
|
|
goto _err_exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resamp->offset = out_size;
|
|
|
|
ASSERT(len == 0, "%s: Bad resample len: len=%u in_size=%u", __func__, len, in_size);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
_err_exit:
|
|
if (resamp)
|
|
{
|
|
app_resample_reset(resamp);
|
|
}
|
|
|
|
memzero_int16(buf, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void app_resample_reset(struct APP_RESAMPLE_T *resamp)
|
|
{
|
|
audio_resample_ex_flush((RESAMPLE_ID *)resamp->id);
|
|
resamp->offset = resamp->iter_len;
|
|
}
|
|
|
|
void app_resample_tune(struct APP_RESAMPLE_T *resamp, float ratio)
|
|
{
|
|
float new_step;
|
|
|
|
if (resamp == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TRACE_AUD_STREAM_I("%s: stream=%d ratio=%d", __FUNCTION__, resamp->stream, FLOAT_TO_PPB_INT(ratio));
|
|
|
|
if (resamp->stream == AUD_STREAM_PLAYBACK) {
|
|
new_step = resamp->ratio_step + resamp->ratio_step * ratio;
|
|
} else {
|
|
new_step = resamp->ratio_step - resamp->ratio_step * ratio;
|
|
}
|
|
audio_resample_ex_set_ratio_step(resamp->id, new_step);
|
|
}
|
|
|
|
APP_RESAMPLE_BUF_ALLOC_CALLBACK app_resample_set_buf_alloc_callback(APP_RESAMPLE_BUF_ALLOC_CALLBACK cb)
|
|
{
|
|
APP_RESAMPLE_BUF_ALLOC_CALLBACK old_cb;
|
|
|
|
old_cb = resamp_buf_alloc;
|
|
resamp_buf_alloc = cb;
|
|
|
|
return old_cb;
|
|
}
|
|
|
|
#ifdef TX_RX_PCM_MASK
|
|
|
|
#ifdef SCO_DMA_SNAPSHOT
|
|
|
|
#define MSBC_LEN 60
|
|
|
|
void store_encode_frame2buff()
|
|
{
|
|
if(bt_sco_codec_is_msbc())
|
|
{
|
|
uint32_t len;
|
|
//processing uplink msbc data.
|
|
if(playback_buf_btpcm_copy!=NULL)
|
|
{
|
|
len=playback_size_btpcm_copy-MSBC_LEN;
|
|
memcpy((uint8_t *)(*(volatile uint32_t *)(MIC_BUFF_ADRR_REG)),playback_buf_btpcm_copy,MSBC_LEN);
|
|
memcpy(playback_buf_btpcm_copy,playback_buf_btpcm_copy+MSBC_LEN,len);
|
|
}
|
|
//processing downlink msbc data.
|
|
if(capture_buf_btpcm_copy!=NULL)
|
|
{
|
|
len=capture_size_btpcm_copy-MSBC_LEN;
|
|
memcpy(capture_buf_btpcm_copy,capture_buf_btpcm_copy+MSBC_LEN,len);
|
|
memcpy(capture_buf_btpcm_copy+len,(uint8_t *)(*(volatile uint32_t *)(RX_BUFF_ADRR)),MSBC_LEN);
|
|
}
|
|
#if defined(CHIP_BEST2300A)
|
|
uint8_t sco_toggle = *(volatile uint8_t *)(RX_BUFF_ADRR+8);
|
|
pcm_data_param[sco_toggle].curr_time = *(volatile uint32_t *)(RX_BUFF_ADRR+4);
|
|
pcm_data_param[sco_toggle].toggle = sco_toggle;
|
|
pcm_data_param[sco_toggle].flag = *(volatile uint8_t *)(RX_BUFF_ADRR+9);
|
|
pcm_data_param[sco_toggle].counter = *(volatile uint16_t *)(RX_BUFF_ADRR+10);
|
|
#endif
|
|
}
|
|
return;
|
|
}
|
|
#else
|
|
extern CQueue* get_tx_esco_queue_ptr();
|
|
extern CQueue* get_rx_esco_queue_ptr();
|
|
void store_encode_frame2buff()
|
|
{
|
|
CQueue* Tx_esco_queue_temp = NULL;
|
|
CQueue* Rx_esco_queue_temp = NULL;
|
|
Tx_esco_queue_temp = get_tx_esco_queue_ptr();
|
|
Rx_esco_queue_temp = get_rx_esco_queue_ptr();
|
|
unsigned int len;
|
|
len= 60;
|
|
int status = 0;
|
|
if(bt_sco_codec_is_msbc())
|
|
{
|
|
status = DeCQueue(Tx_esco_queue_temp,(uint8_t *)(*(volatile uint32_t *)(MIC_BUFF_ADRR_REG)),len);
|
|
if(status){
|
|
//TRACE_AUD_STREAM_I("TX DeC Fail");
|
|
}
|
|
status =EnCQueue(Rx_esco_queue_temp, (uint8_t *)(*(volatile uint32_t *)(RX_BUFF_ADRR)), len);
|
|
if(status){
|
|
//TRACE_AUD_STREAM_I("RX EnC Fail");
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
int app_bt_stream_init(void)
|
|
{
|
|
app_bt_stream_trigger_checker_init();
|
|
return 0;
|
|
}
|
|
|