KT24-1110_65E-HA-651B/cpu/br25/audio_enc/audio_sbc_codec.c
2024-11-10 18:44:17 +08:00

921 lines
25 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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