前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【蓝牙sbc协议】sbc源码阅读笔记(二)——sbc_struct详解(上)[通俗易懂]

【蓝牙sbc协议】sbc源码阅读笔记(二)——sbc_struct详解(上)[通俗易懂]

作者头像
全栈程序员站长
发布2022-10-01 12:01:10
9370
发布2022-10-01 12:01:10
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

sbc_struct结构详解

sbc_struct结构的定义:
代码语言:javascript
复制
// sbc.h
struct sbc_struct { 
   
	unsigned long flags;

	uint8_t frequency;
	uint8_t blocks;
	uint8_t subbands;
	uint8_t mode;
	uint8_t allocation;
	uint8_t bitpool;
	uint8_t endian;

	void *priv;
	void *priv_alloc_base;
};
typedef struct sbc_struct sbc_t;

flags

unsigned long类型。在调用sbc_init(&sbc, 0L);sbc_init_msbc(&sbc, 0);的时候作为第二个参数传入,并在函数中,继续传递给sbc_set_defaults函数,在sbc_set_defaults中赋值给sbc->flags

待补充:作用

代码语言:javascript
复制
/* sbcenc.c */
// !msbc
sbc_init(&sbc, 0L);
// msbc
sbc_init_msbc(&sbc, 0);

/* sbc.c */
// sbc_init()与sbc_init_msbc()均调用此方法
sbc_set_defaults(sbc, flags);	
// sbc_set_defaults()
static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
{ 
     
	···
	sbc->flags = flags;
	···
}

frequency

uint8_t类型,用来表示采样率,取值有16k,32k,44.1k,48k。

代码语言:javascript
复制
/* sbc.h */
/* sampling frequency */
#define SBC_FREQ_16000 0x00
#define SBC_FREQ_32000 0x01
#define SBC_FREQ_44100 0x02
#define SBC_FREQ_48000 0x03

sbc_init()中默认值为44.1k,在sbc_init_msbc()中默认值为16k。

代码语言:javascript
复制
/* sbc.c */
// sbc
static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
{ 
     
	···
	sbc->frequency = SBC_FREQ_44100;
	···
}
// msbc
···
sbc_set_defaults(sbc, flags);		// 先调用了sbc_set_defaults
sbc->frequency = SBC_FREQ_16000;// 随后修改默认值为16k
···

encode()中,sbc编码可以根据文件采样率对frequency赋值,msbc只能使用16k。

代码语言:javascript
复制
/* sbcenc.c */
// msbc必须为16k
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
switch (BE_INT(au_hdr.sample_rate)) { 

case 16000:
sbc.frequency = SBC_FREQ_16000;
break;
case 32000:
sbc.frequency = SBC_FREQ_32000;
break;
case 44100:
sbc.frequency = SBC_FREQ_44100;
break;
case 48000:
sbc.frequency = SBC_FREQ_48000;
break;
}
···
} else { 

if (BE_INT(au_hdr.sample_rate) != 16000 ||
BE_INT(au_hdr.channels) != 1 ||
BE_INT(au_hdr.channels) != 1) { 

fprintf(stderr, "mSBC requires 16 bits, 16kHz, mono "
"input\n");
goto done;
}
···
}
···
}

blocks

类型为uint8_t,sbc编码的取值有4,8,12,16,msbc为15。

待补充:作用

代码语言:javascript
复制
/* sbc.h */
/* blocks */
#define SBC_BLK_4 0x00
#define SBC_BLK_8 0x01
#define SBC_BLK_12 0x02
#define SBC_BLK_16 0x03
/* sbc.c */
#define MSBC_BLOCKS 15

sbc_set_defaults()中默认设置为16,msbc则修改为15。

代码语言:javascript
复制
/* sbc.c */
// sbc
static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
{ 

···
sbc->blocks = SBC_BLK_16;
···
}
// msbc
···
sbc_set_defaults(sbc, flags);		// 先调用了sbc_set_defaults
sbc->blocks = MSBC_BLOCKS;			// 随后修改为15
···

encode()中进行赋值。

代码语言:javascript
复制
/* sbcenc.c */
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
···
sbc.blocks = blocks == 4 ? SBC_BLK_4 :
blocks == 8 ? SBC_BLK_8 :
blocks == 12 ? SBC_BLK_12 : SBC_BLK_16;
} else { 

···
sbc_init_msbc(&sbc, 0);		// 设置为15
···
}
···
}

subbands

uint8_t类型,表示子带数量,取值范围为4,8。

代码语言:javascript
复制
/* sbc.h */
/* subbands */
#define SBC_SB_4 0x00
#define SBC_SB_8 0x01

sbc_set_defaults()中默认设置为8。

encode()中进行赋值。

代码语言:javascript
复制
/* sbcenc.c */
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
···
sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
···
} else { 

···
sbc_init_msbc(&sbc, 0);		// 默认8
···
}
···
}

mode

uint8_t类型,表示声道模式,支持单声道、双声道、立体声和联合立体声。

代码语言:javascript
复制
/* sbc.h */
/* channel mode */
#define SBC_MODE_MONO 0x00
#define SBC_MODE_DUAL_CHANNEL 0x01
#define SBC_MODE_STEREO 0x02
#define SBC_MODE_JOINT_STEREO 0x03

sbc_set_defaults()中默认设置为立体声,msbc编码则默认是单声道。

encode()中进行赋值。

代码语言:javascript
复制
/* sbcenc.c */
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
···
if (BE_INT(au_hdr.channels) == 1) { 

sbc.mode = SBC_MODE_MONO;	// 单声道
// 音频为单声道但指定了联合或双声道模式
if (joint || dualchannel) { 

fprintf(stderr, "Audio is mono but joint or "
"dualchannel mode has been specified\n");
goto done;
}
} else if (joint && !dualchannel)
sbc.mode = SBC_MODE_JOINT_STEREO;	// 立体声
else if (!joint && dualchannel)
sbc.mode = SBC_MODE_DUAL_CHANNEL;	// 双声道
else if (!joint && !dualchannel)
sbc.mode = SBC_MODE_STEREO;				// 联合立体声
else { 

fprintf(stderr, "Both joint and dualchannel "
"mode have been specified\n");
goto done;
}
···
} else { 

···
sbc_init_msbc(&sbc, 0);		// msbc默认单声道
···
}
···
}

allocation

uint8_t类型,表示每个子频段幅值比特数的分配方法,有响度和信噪比。

代码语言:javascript
复制
/* sbc.h */
/* allocation method */
#define SBC_AM_LOUDNESS 0x00
#define SBC_AM_SNR 0x01

默认为SBC_AM_LOUDNESS,在encode()中赋值。

代码语言:javascript
复制
/* sbcenc.c */
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
···
sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
···
} else { 

···
sbc_init_msbc(&sbc, 0);		// msbc默认SBC_AM_LOUDNESS
···
}
···
}

bitpool

uint8_t类型,表示幅值的比特数,默认为32,msbc默认为26。

代码语言:javascript
复制
/* sbcenc.c */
static void encode(char *filename, int subbands, int bitpool, int 								joint, int dualchannel, int snr, int blocks, bool msbc)
{ 

···
if (!msbc) { 

sbc_init(&sbc, 0L);
···
sbc.bitpool = bitpool;		// sbc默认32
···
} else { 

···
sbc_init_msbc(&sbc, 0);		// msbc默认26
···
}
···
}

endian

uint8_t类型,用来表示主机字节序(大端、小端),默认为大端。

代码语言:javascript
复制
/* sbc.h */
/* data endianess */
#define SBC_LE 0x00
#define SBC_BE 0x01

sbc_set_defaults()中判断并赋值。

代码语言:javascript
复制
/* sbc.c */
// sbc_set_defaults()
static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
{ 

···
#if __BYTE_ORDER == __LITTLE_ENDIAN
sbc->endian = SBC_LE;
#elif __BYTE_ORDER == __BIG_ENDIAN
sbc->endian = SBC_BE;
#else
#error "Unknown byte order"
#endif
}

待补充:sbc与msbc执行sbc_set_defaults()后,都又将endian赋值为SBC_BE

待补充内容:
  • flags 的作用
  • blocks 的作用
  • endian 判断赋值后,又重新赋值为 SBC_BE
  • *priv 与 *priv_alloc_base

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/194983.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月11日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sbc_struct结构详解
    • sbc_struct结构的定义:
      • 待补充内容:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档