#include "asm/includes.h" #include "media/includes.h" #include "system/includes.h" #include "aec_user.h" #include "asm/audio_src.h" #include "audio_enc.h" #include "app_main.h" #include "btstack/avctp_user.h" #include "audio_digital_vol.h" #include "audio_sbc_codec.h" #include "clock_cfg.h" #include "media/pcm_decoder.h" #include "audio_dec.h" #define SBC_AUDIO_OVERLAY 0 // sbc发射和audio空间互用 #define BT_USE_PCM_DEC 0 //多加一个解码,会多耗资源,时钟也会增加,用来解决完全切歌的时候出现杂音的问题 #define SBC_RESERVED_LAST_PCM 1 //淡入淡出功能,耗资源很小,可以解决正常速度切歌杂音,但是快速连续切歌会有杂音 enum { SBC_RUN_STEP_NOR = 0, SBC_RUN_STEP_WAIT_STOP, SBC_RUN_STEP_STOP, SBC_RUN_STEP_WAIT_NOR, }; extern struct audio_encoder_task *encode_task; //static struct audio_encoder_task *encode_task = NULL; #define SBC_ENC_WRITING BIT(1) #define SBC_ENC_START BIT(2) #define SBC_ENC_WAKEUP_SEND BIT(3) /*减少唤醒问题*/ #define SBC_ENC_PCM_MUTE_DATA BIT(4) /*发一包静音数据*/ static u8 sbc_buf_flag = 0; #define ESCO_ADC_BUF_NUM 2 #define ESCO_ADC_IRQ_POINTS 256 #define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS) #define SBC_USE_MIC_CHANNEL 0 #define SBC_ENC_PACK_ENABLE 0 /*sbc数据包封装*/ #define SBC_ENC_IN_SIZE 512 #define SBC_ENC_OUT_SIZE 256 #define SBC_ENC_IN_CBUF_SIZE (SBC_ENC_IN_SIZE * 8) #define SBC_ENC_OUT_CBUF_SIZE (SBC_ENC_OUT_SIZE * 8) struct sbc_enc_hdl { struct audio_encoder encoder; OS_SEM pcm_frame_sem; u8 output_frame[SBC_ENC_OUT_SIZE]; u8 pcm_frame[SBC_ENC_IN_SIZE]; u8 frame_size; u8 backup_digital_vol; u8 overlay; #if SBC_RESERVED_LAST_PCM u8 run_step; u8 run_cnt; u8 in_cnt; OS_SEM run_sem; #endif cbuffer_t output_cbuf; u8 *p_out_cbuf_buf; cbuffer_t pcm_in_cbuf;/*要注意要跟DAC的buf大小一致*/ u8 *p_in_cbuf_buf; #if SBC_ENC_PACK_ENABLE u16 cp_type; u16 packet_head_sn; #endif int mute_data_send_timer; #if SBC_USE_MIC_CHANNEL struct audio_adc_output_hdl adc_output; struct adc_mic_ch mic_ch; s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes #endif #if BT_USE_PCM_DEC struct audio_mixer_ch mix_ch; struct audio_res_wait wait; struct pcm_decoder pcm_dec; // pcm解码句柄 struct audio_stream *audio_stream; // 音频流 #endif /* dvol_handle *dvol; */ }; static struct sbc_enc_hdl *sbc_enc = NULL; __attribute__((weak)) void audio_sbc_enc_inbuf_resume(void) { ; } __attribute__((weak)) void audio_sbc_enc_open_exit(void) { ; } __attribute__((weak)) void audio_sbc_enc_close_enter(void) { ; } #if BT_USE_PCM_DEC static int pcm_fread(void *hdl, void *buf, int len) { len = len / 2; memset(buf, 0, len); return len; } static int pcm_dec_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out) { struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); struct sbc_enc_hdl *dec = container_of(pcm_dec, struct sbc_enc_hdl, pcm_dec); audio_stream_run(&decoder->entry, in); /* audio_mixer_ch_pause(&dec->mix_ch, 0); */ return decoder->process_len; } static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) { } static void dec_out_stream_resume(void *p) { struct sbc_enc_hdl *dec = (struct sbc_enc_hdl *)p; audio_decoder_resume(&dec->pcm_dec.decoder); } static int pcm_dec_start(struct sbc_enc_hdl *stream) { int err = 0; if (stream == NULL) { return -EINVAL; } err = pcm_decoder_open(&stream->pcm_dec, &decode_task); if (err) { return err; } pcm_decoder_set_event_handler(&stream->pcm_dec, pcm_dec_event_handler, 0); pcm_decoder_set_read_data(&stream->pcm_dec, pcm_fread, stream); pcm_decoder_set_data_handler(&stream->pcm_dec, pcm_dec_data_handler); audio_mixer_ch_open(&stream->mix_ch, &mixer); audio_mixer_ch_set_src(&stream->mix_ch, 0, 0); struct audio_stream_entry *entries[8] = {NULL}; u8 entry_cnt = 0; entries[entry_cnt++] = &stream->pcm_dec.decoder.entry; entries[entry_cnt++] = &stream->mix_ch.entry; stream->audio_stream = audio_stream_open(stream, dec_out_stream_resume); audio_stream_add_list(stream->audio_stream, entries, entry_cnt); audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); err = audio_decoder_start(&stream->pcm_dec.decoder); if (err == 0) { printf("pcm_dec_start ok\n"); } return err; } static void pcm_dec_stop(struct sbc_enc_hdl *stream) { printf("mic stream dec stop \n\n"); if (stream) { pcm_decoder_close(&stream->pcm_dec); audio_mixer_ch_close(&stream->mix_ch); if (stream->audio_stream) { audio_stream_close(stream->audio_stream); stream->audio_stream = NULL; } } } static int pcmdec_wait_res_handler(struct audio_res_wait *wait, int event) { int err = 0; struct sbc_enc_hdl *stream = container_of(wait, struct sbc_enc_hdl, wait); if (event == AUDIO_RES_GET) { err = pcm_dec_start(stream); } else if (event == AUDIO_RES_PUT) { /* pcm_dec_stop(stream); */ } return err; } static int pcm_dec_open(struct sbc_enc_hdl *stream, struct audio_fmt *pfmt) { stream->pcm_dec.output_ch_num = stream->pcm_dec.ch_num = pfmt->channel; stream->pcm_dec.sample_rate = pfmt->sample_rate; if (stream->pcm_dec.output_ch_num == 2) { stream->pcm_dec.output_ch_type = AUDIO_CH_LR; } else { stream->pcm_dec.output_ch_type = AUDIO_CH_DIFF; } stream->wait.priority = 0; stream->wait.preemption = 0; stream->wait.protect = 1; stream->wait.handler = pcmdec_wait_res_handler; return audio_decoder_task_add_wait(&decode_task, &stream->wait); } static void pcm_dec_close(struct sbc_enc_hdl *stream) { pcm_dec_stop(stream); audio_decoder_task_del_wait(&decode_task, &stream->wait); } #endif /*BT_USE_PCM_DEC*/ #if SBC_RESERVED_LAST_PCM static void sbc_enc_pcm_data_fade_out(s16 *data, int len) { u16 samples = len >> 1; int down_step = (32767 + samples - 1) / samples + 1; int value = 32767; for (int i = 0; i < samples; i++) { if (value > down_step) { value -= down_step; } else { value = 0; } s32 tmp = *data; *data++ = tmp * value / 32767; } } static void sbc_enc_pcm_data_fade_in(s16 *data, int len) { u16 samples = len >> 1; int down_step = (32767 + samples - 1) / samples + 1; int value = 0; for (int i = 0; i < samples; i++) { if (value + down_step < 32767) { value += down_step; } else { value = 32767; } s32 tmp = *data; *data++ = tmp * value / 32767; } } #endif /* SBC_RESERVED_LAST_PCM */ static void sbc_send_mute_data() { sbc_buf_flag |= SBC_ENC_PCM_MUTE_DATA; audio_encoder_resume(&sbc_enc->encoder); } static int sbc_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len) { u8 read_flag = 1; int pcm_len = 0; if (encoder == NULL) { r_printf("encoder NULL"); } struct sbc_enc_hdl *enc = container_of(encoder, struct sbc_enc_hdl, encoder); if (enc == NULL) { r_printf("enc NULL"); } int limit_size = SBC_ENC_IN_SIZE; #if SBC_RESERVED_LAST_PCM if (enc->run_step == SBC_RUN_STEP_NOR) { limit_size += SBC_ENC_IN_SIZE; } #endif if (cbuf_get_data_size(&enc->pcm_in_cbuf) < limit_size) { if (!(sbc_buf_flag & SBC_ENC_PCM_MUTE_DATA)) { #if SBC_RESERVED_LAST_PCM if (enc->run_step == SBC_RUN_STEP_STOP) { if (enc->run_cnt) { enc->run_cnt--; if (enc->run_cnt == 0) { os_sem_post(&enc->run_sem); } memset(enc->pcm_frame, 0, SBC_ENC_IN_SIZE); *frame = enc->pcm_frame; return SBC_ENC_IN_SIZE; } } #endif return 0; } else { read_flag = 0; } } if (read_flag) { pcm_len = cbuf_read(&enc->pcm_in_cbuf, enc->pcm_frame, SBC_ENC_IN_SIZE); #if SBC_RESERVED_LAST_PCM if (pcm_len && enc->run_step) { local_irq_disable(); if (enc->run_step == SBC_RUN_STEP_WAIT_STOP) { enc->run_step = SBC_RUN_STEP_STOP; enc->run_cnt = 200; // 发射每次读取5包,至少保证发射一帧 sbc_enc_pcm_data_fade_out(enc->pcm_frame, pcm_len); } else if (enc->run_step == SBC_RUN_STEP_STOP) { memset(enc->pcm_frame, 0, pcm_len); if (enc->run_cnt) { enc->run_cnt--; if (enc->run_cnt == 0) { os_sem_post(&enc->run_sem); } } } else if (sbc_enc->run_step == SBC_RUN_STEP_WAIT_NOR) { if (sbc_enc->in_cnt > 0) { sbc_enc->in_cnt--; memset(enc->pcm_frame, 0, pcm_len); } else { sbc_enc->run_step = SBC_RUN_STEP_NOR; sbc_enc_pcm_data_fade_in(enc->pcm_frame, pcm_len); } } local_irq_enable(); } else { } #endif #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) audio_stream_resume(&sbc_emitter.entry); #endif } else { memset(enc->pcm_frame, 0, SBC_ENC_IN_SIZE); pcm_len = SBC_ENC_IN_SIZE; } if (pcm_len != SBC_ENC_IN_SIZE) { } *frame = enc->pcm_frame; return pcm_len; } static void sbc_enc_pcm_put(struct audio_encoder *encoder, s16 *frame) { } static const struct audio_enc_input sbc_enc_input = { .fget = sbc_enc_pcm_get, .fput = sbc_enc_pcm_put, }; static int sbc_enc_probe_handler(struct audio_encoder *encoder) { return 0; } #if SBC_ENC_PACK_ENABLE /* struct Media_Playload_Header { u8 Version: 2; u8 Padding: 1; u8 Extension: 1; u8 CSRC_Count: 4; u8 Marker: 1; u8 PayloadType: 7; u16 SequenceNumber; u32 TimeStamp; u32 SSRC; }; SBC_FRAME_SUM defined within sbc_packet_head_buf used for Media Playload parameter:Number of Frames */ #define SBC_PACKET_HEADER_LEN (14) /*包头Max Length*/ #define SBC_FRAME_SUM (4) /*一包多少帧*/ static unsigned char sbc_packet_head_buf[SBC_PACKET_HEADER_LEN] = { 0x80, 0x60, //Version:2 Playload Type:0x60 0x00, 0x64, //Sequencenumber 0x00, 0x00, 0x03, 0x20, //Timestamp 0x00, 0x00, 0x00, 0x00 //Synchronization Source //SBC_FRAME_SUM //defined for Media Payload }; void sbc_enc_packet_pack(struct sbc_enc_hdl *hdl) { unsigned int TS; /*TimeStamp*/ /*SequenceNumber*/ hdl->packet_head_sn++; /*Timestamp*/ TS = hdl->packet_head_sn * (128 * SBC_FRAME_SUM); sbc_packet_head_buf[2] = hdl->packet_head_sn >> 8; sbc_packet_head_buf[3] = hdl->packet_head_sn & 0xff; sbc_packet_head_buf[4] = TS >> 24; sbc_packet_head_buf[5] = (TS >> 16) & 0xff; sbc_packet_head_buf[6] = (TS >> 8) & 0xff; sbc_packet_head_buf[7] = (TS) & 0xff; if (hdl->cp_type == 0x0002) { /* *Content Protection Header *L-bit :bit0 *Cp-bit:bit1 *RFA :bit2 to bit7 */ sbc_packet_head_buf[12] = 0; sbc_packet_head_buf[13] = SBC_FRAME_SUM; } else { sbc_packet_head_buf[12] = SBC_FRAME_SUM; } } #endif/*SBC_ENC_PACK_ENABLE*/ static int sbc_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len) { if (encoder == NULL) { r_printf("encoder NULL"); } struct sbc_enc_hdl *enc = container_of(encoder, struct sbc_enc_hdl, encoder); enc->frame_size = len; u16 wlen = cbuf_write(&enc->output_cbuf, frame, len); if (wlen != len) { return len; } if (cbuf_get_data_size(&sbc_enc->output_cbuf) >= enc->frame_size * 5) { //达到基本的数据量,唤醒蓝牙发数 user_send_cmd_prepare(USER_CTRL_CMD_RESUME_STACK, 0, NULL); } return len; } const static struct audio_enc_handler sbc_enc_handler = { .enc_probe = sbc_enc_probe_handler, .enc_output = sbc_enc_output_handler, }; int a2dp_sbc_encoder_get_data(u8 *packet, u16 buf_len, int *frame_size) { if (sbc_enc == NULL) { return 0; } if (cbuf_get_data_size(&sbc_enc->output_cbuf) < buf_len) { return 0; } int debug_frame_size = sbc_enc->frame_size; int number = buf_len / debug_frame_size; /*取整数包*/ *frame_size = debug_frame_size; u16 rlen = cbuf_read(&sbc_enc->output_cbuf, packet, *frame_size * number); if (rlen == 0) { } #if SBC_RESERVED_LAST_PCM if (sbc_enc->run_step != SBC_RUN_STEP_NOR) { // 非正常状态,sbc数据取走后激活一下编码 audio_encoder_resume(&sbc_enc->encoder); } #endif return rlen; } static void sbc_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv) { printf("sbc_enc_event_handler:0x%x,%d\n", argv[0], argv[0]); switch (argv[0]) { case AUDIO_ENC_EVENT_END: puts("AUDIO_ENC_EVENT_END\n"); break; } } #include "sbc_enc.h" sbc_t sbc_param = { .frequency = SBC_FREQ_44100, .blocks = SBC_BLK_16, .subbands = SBC_SB_8, .mode = SBC_MODE_STEREO, .allocation = 0, .endian = SBC_LE, .bitpool = 53, }; int audio_sbc_enc_config(void *cfg) { sbc_t *p = cfg; if (p) { printf("sbc_enc_param update:\n"); printf("frequency:%d\n", p->frequency); printf("blocks:%d\n", p->blocks); printf("subbands:%d\n", p->subbands); printf("mode:%d\n", p->mode); printf("allocation:%d\n", p->allocation); printf("endian:%d\n", p->endian); printf("bitpool:%d\n", p->bitpool); } return 0; } int audio_sbc_enc_check_empty_len(void) { if (!(sbc_buf_flag & SBC_ENC_START)) { return 0; } if (!sbc_enc) { return 0; } return sbc_enc->pcm_in_cbuf.total_len - sbc_enc->pcm_in_cbuf.data_len; } static int audio_sbc_enc_write_base(s16 *data, int len, u8 ch_i, u8 ch_o) { if (!(sbc_buf_flag & SBC_ENC_START)) { return 0; } if (!sbc_enc) { return 0; } sbc_buf_flag |= SBC_ENC_WRITING; int wlen = 0; int ilen = 0; int remain_len = len; while (remain_len) { wlen = 0; void *obuf = cbuf_write_alloc(&sbc_enc->pcm_in_cbuf, &wlen); if (!wlen) { break; } if (ch_o == ch_i) { ilen = wlen; if (ilen > remain_len) { ilen = remain_len; wlen = ilen; } memcpy(obuf, data, wlen); } else if ((ch_o == 2) && (ch_i == 1)) { ilen = (wlen >> 2) << 1; if (ilen > remain_len) { ilen = remain_len; wlen = ilen << 1; } s16 *outbuf = obuf; s16 *inbuf = data; int run_len = ilen >> 1; while (run_len --) { *outbuf++ = *inbuf; *outbuf++ = *inbuf; inbuf++; } } else if ((ch_o == 1) && (ch_i == 2)) { ilen = wlen << 1; if (ilen > remain_len) { ilen = remain_len; wlen = ilen >> 1; } s16 *outbuf = obuf; s16 *inbuf = data; int run_len = ilen >> 2; while (run_len--) { *outbuf++ = data_sat_s16(inbuf[0] + inbuf[1]); inbuf += 2; } } cbuf_write_updata(&sbc_enc->pcm_in_cbuf, wlen); remain_len -= ilen; data += ilen / 2; }; wlen = len - remain_len; if (cbuf_get_data_size(&sbc_enc->pcm_in_cbuf) >= SBC_ENC_IN_SIZE) { audio_encoder_resume(&sbc_enc->encoder); } sbc_buf_flag &= ~SBC_ENC_WRITING; return wlen; } int audio_sbc_enc_write(s16 *data, int len) { if (!(sbc_buf_flag & SBC_ENC_START)) { return 0; } if (!sbc_enc) { return 0; } sbc_buf_flag |= SBC_ENC_WRITING; #if 0 u16 wlen = cbuf_write(&sbc_enc->pcm_in_cbuf, data, len); if (wlen != len) { } #else int wlen = 0; int remain_len = len; while (remain_len) { wlen = 0; void *obuf = cbuf_write_alloc(&sbc_enc->pcm_in_cbuf, &wlen); if (!wlen) { break; } if (wlen > remain_len) { wlen = remain_len; } memcpy(obuf, data, wlen); /* audio_digital_vol_run(sbc_enc->dvol, obuf, wlen); */ cbuf_write_updata(&sbc_enc->pcm_in_cbuf, wlen); remain_len -= wlen; data += wlen / 2; }; wlen = len - remain_len; #endif if (cbuf_get_data_size(&sbc_enc->pcm_in_cbuf) >= SBC_ENC_IN_SIZE) { audio_encoder_resume(&sbc_enc->encoder); } sbc_buf_flag &= ~SBC_ENC_WRITING; return wlen; } #if SBC_USE_MIC_CHANNEL s16 temp_data[ESCO_ADC_IRQ_POINTS * 2]; extern struct audio_adc_hdl adc_hdl; static void adc_mic_output_handler(void *priv, s16 *data, int len) { u16 points = len >> 1; if (!(sbc_buf_flag & SBC_ENC_START)) { return; } if (sbc_enc) { //单变双 for (int i = 0; i < points ; i++) { temp_data[i * 2] = data[i]; temp_data[i * 2 + 1] = data[i]; } putchar('m'); audio_sbc_enc_write(temp_data, len * 2); } } #endif int audio_sbc_enc_open() { int err; struct audio_fmt fmt; u16 frame_len = 512; if (encode_task) { return -1; } printf("sbc_enc_open,frame_len:%d\n", frame_len); sbc_buf_flag &= ~SBC_ENC_START; fmt.channel = 1; fmt.frame_len = frame_len; fmt.coding_type = AUDIO_CODING_SBC; fmt.priv = &sbc_param; audio_encoder_task_open(); if (!sbc_enc) { sbc_enc = zalloc(sizeof(*sbc_enc)); #if SBC_RESERVED_LAST_PCM os_sem_create(&sbc_enc->run_sem, 0); #endif u8 *cbuf_buf; #if SBC_AUDIO_OVERLAY cbuf_buf = app_audio_alloc_use_buff(SBC_ENC_OUT_CBUF_SIZE + SBC_ENC_IN_CBUF_SIZE); if (cbuf_buf) { sbc_enc->overlay = 1; } else #endif { cbuf_buf = malloc(SBC_ENC_OUT_CBUF_SIZE + SBC_ENC_IN_CBUF_SIZE); } sbc_enc->p_out_cbuf_buf = cbuf_buf; sbc_enc->p_in_cbuf_buf = &cbuf_buf[SBC_ENC_OUT_CBUF_SIZE]; } printf("init vol:%d \n", app_var.music_volume); /* sbc_enc->dvol = audio_digital_vol_open(app_var.music_volume, 30, 7); */ cbuf_init(&sbc_enc->output_cbuf, sbc_enc->p_out_cbuf_buf, SBC_ENC_OUT_CBUF_SIZE); cbuf_init(&sbc_enc->pcm_in_cbuf, sbc_enc->p_in_cbuf_buf, SBC_ENC_IN_CBUF_SIZE); os_sem_create(&sbc_enc->pcm_frame_sem, 0); audio_encoder_open(&sbc_enc->encoder, &sbc_enc_input, encode_task); audio_encoder_set_handler(&sbc_enc->encoder, &sbc_enc_handler); audio_encoder_set_fmt(&sbc_enc->encoder, &fmt); audio_encoder_set_event_handler(&sbc_enc->encoder, sbc_enc_event_handler, 0); audio_encoder_set_output_buffs(&sbc_enc->encoder, sbc_enc->output_frame, sizeof(sbc_enc->output_frame), 1); int start_err = audio_encoder_start(&sbc_enc->encoder); printf("sbc_enc_open ok %d\n", start_err); #if SBC_USE_MIC_CHANNEL fmt.sample_rate = 44100; audio_adc_mic_open(&sbc_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); audio_adc_mic_set_sample_rate(&sbc_enc->mic_ch, fmt.sample_rate); audio_adc_mic_set_gain(&sbc_enc->mic_ch, app_var.aec_mic_gain); audio_adc_mic_set_buffs(&sbc_enc->mic_ch, sbc_enc->adc_buf, ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM); sbc_enc->adc_output.handler = adc_mic_output_handler; audio_adc_add_output_handler(&adc_hdl, &sbc_enc->adc_output); audio_adc_mic_start(&sbc_enc->mic_ch); #endif #if BT_USE_PCM_DEC clock_add(DEC_PCM_CLK); pcm_dec_open(sbc_enc, &fmt); #endif clock_add(ENC_SBC_CLK); clock_set_cur(); sbc_buf_flag |= SBC_ENC_START; audio_sbc_enc_open_exit(); return 0; } int audio_sbc_enc_reset_buf(u8 flag) { if (!sbc_enc) { return -1; } r_printf("audio_sbc_enc_reset_buf %d\n", flag); if (flag) { if (sbc_enc->mute_data_send_timer) { sys_hi_timer_del(sbc_enc->mute_data_send_timer); sbc_enc->mute_data_send_timer = 0; sbc_buf_flag &= ~SBC_ENC_PCM_MUTE_DATA; } } else { if (sbc_enc->mute_data_send_timer == 0) { } } return 0; } int audio_sbc_enc_close() { if (!sbc_enc) { return -1; } printf("audio_sbc_enc_close\n"); audio_sbc_enc_close_enter(); sbc_buf_flag &= ~SBC_ENC_START; #if BT_USE_PCM_DEC pcm_dec_close(sbc_enc); clock_remove(DEC_PCM_CLK); #endif #if SBC_RESERVED_LAST_PCM os_sem_post(&sbc_enc->run_sem); #endif while (sbc_buf_flag & SBC_ENC_WRITING) { os_time_dly(1); } #if SBC_USE_MIC_CHANNEL audio_adc_mic_close(&sbc_enc->mic_ch); audio_adc_del_output_handler(&adc_hdl, &sbc_enc->adc_output); #endif audio_encoder_close(&sbc_enc->encoder); #if SBC_AUDIO_OVERLAY if (sbc_enc->overlay) { app_audio_release_use_buff(sbc_enc->p_out_cbuf_buf); } else #endif { free(sbc_enc->p_out_cbuf_buf); } free(sbc_enc); sbc_enc = NULL; audio_encoder_task_close(); clock_remove(ENC_SBC_CLK); clock_set_cur(); printf("audio_sbc_enc_close end\n"); return 0; } void audio_sbc_enc_init(void) { } int audio_sbc_enc_is_work(void) { if ((sbc_buf_flag & SBC_ENC_START) && sbc_enc) { return true; } return false; } #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) #include "application/audio_dig_vol.h" extern void *bt_digvol_last; #endif void bt_emitter_set_vol(u8 vol) { if (!(sbc_buf_flag & SBC_ENC_START)) { return ; } if (!sbc_enc) { return ; } sbc_enc->backup_digital_vol = vol; r_printf("=======set vol %d\n", vol); #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) if (bt_digvol_last) { audio_dig_vol_set(bt_digvol_last, AUDIO_DIG_VOL_ALL_CH, vol); } #endif } int audio_sbc_enc_get_rate(void) { int sr = 44100; switch (sbc_param.frequency) { case SBC_FREQ_16000: sr = 16000; break; case SBC_FREQ_32000: sr = 32000; break; case SBC_FREQ_44100: sr = 44100; break; case SBC_FREQ_48000: sr = 48000; break; } return sr; } int audio_sbc_enc_get_channel_num(void) { return sbc_param.mode == SBC_MODE_MONO ? 1 : 2; } int a2dp_sbc_encoder_init(void *sbc_struct) { if (sbc_struct) { memcpy(&sbc_param, sbc_struct, sizeof(sbc_t)); extern void audio_mixer_reset_sample_rate(u32 sr); audio_mixer_reset_sample_rate(audio_sbc_enc_get_rate()); //audio_sbc_enc_config(&sbc_param); audio_sbc_enc_open(); } else { #if USER_SUPPORT_DUAL_A2DP_SOURCE if (get_total_connect_dev() == 0) { //当前有一台连接上了 audio_sbc_enc_close(); } #else audio_sbc_enc_close(); #endif } return 0; } #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) struct sbc_emitter_hdl sbc_emitter = {0}; static int audio_stream_sbc_emitter_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out) { local_irq_disable(); if (false == audio_sbc_enc_is_work()) { local_irq_enable(); return in->data_len; } #if SBC_RESERVED_LAST_PCM if (in->stop) { if (sbc_enc->run_step == SBC_RUN_STEP_NOR) { sbc_enc->run_step = SBC_RUN_STEP_WAIT_STOP; } audio_encoder_resume(&sbc_enc->encoder); os_sem_set(&sbc_enc->run_sem, 0); local_irq_enable(); if ((sbc_enc->run_step == SBC_RUN_STEP_WAIT_STOP) || (sbc_enc->run_cnt)) { os_sem_pend(&sbc_enc->run_sem, 3); if ((sbc_enc->run_step == SBC_RUN_STEP_WAIT_STOP) || (sbc_enc->run_cnt)) { log_w("sbc wait stop err, step:%d, cnt:%d \n\n", sbc_enc->run_step, sbc_enc->run_cnt); } } return in->data_len; } else { if (sbc_enc->run_step != SBC_RUN_STEP_NOR && (sbc_enc->run_step != SBC_RUN_STEP_WAIT_NOR)) { cbuf_clear(&sbc_enc->pcm_in_cbuf); sbc_enc->run_step = SBC_RUN_STEP_WAIT_NOR; sbc_enc->in_cnt = 100; //丢掉前面几包 } } #endif local_irq_enable(); if (in->data_len == 0) { return 0; } return audio_sbc_enc_write_base(in->data, in->data_len, in->channel, audio_sbc_enc_get_channel_num()); } void audio_sbc_emitter_init(void) { sbc_emitter.entry.data_handler = audio_stream_sbc_emitter_data_handler; } #endif