921 lines
25 KiB
C
921 lines
25 KiB
C
#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
|
||
|
||
|