【蓝⽛sbc协议】sbc源码阅读笔记(⼀)——编码过程sbcenc.c
1. main(int argc, char *argv[])
⾸先设定 option 的默认值,然后根据⽤户命令设定 option 相关参数。
对指定⽂件进⾏编码(执⾏encode函数)
2. usage(void)
打印相关option:
Option Option打印帮助信息
h help打印帮助信息
v verbose详细模式
m msbc mSBC编解码器
s subbands⼦带数量(4/8)
b bitpool Bitpool value
j joint联合⽴体声
d dualchannel双声道
S snr信噪⽐模式(default/loudness)
B blocks block数量(4/8/12/16)
3. encode(char *filename, int subbands, int bitpool, int joint, int dualchannel, int snr, int blocks, bool msbc)
定义⼀个 au_header类型的变量au_hdr
// formats.h
struct au_header {
uint32_t magic;  /* '.snd' */
uint32_t hdr_size; /* size of header (min 24) */
uint32_t data_size; /* size of data */
uint32_t encoding; /* see to AU_FMT_XXXX */
uint32_t sample_rate; /* sample rate */
uint32_t channels; /* number of channels (voices) */
};
定义⼀个sbc_t类型的变量sbc
// 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;
uint8_t endian;
void*priv;
void*priv_alloc_base;
};
typedef struct sbc_struct sbc_t;
定义ssize_t类型的变量encoded和len,实际是ssize_t就是long类型。
/
/ _types.h
typedef long __darwin_ssize_t;/* byte count or error */
// _ssize_t.h
typedef __darwin_ssize_t ssize_t;
检测au_hdr的长度是否是24。
if(sizeof(au_hdr)!=24){
/* Sanity check just in case */
fprintf(stderr,"FIXME: sizeof(au_hdr) != 24\n");
return;
}
确定指定⽂件合法性并打开⽂件。
if(strcmp(filename,"-")){
fd =open(filename, O_RDONLY);
if(fd <0){
fprintf(stderr,"Can't open file %s: %s\n",
filename,strerror(errno));
return;
}
}else
fd =fileno(stdin);
将⽂件中头部数据读⼊au_hdr,并确定是否读取成功。
len =read(fd,&au_hdr,sizeof(au_hdr));
if(len <(ssize_t)sizeof(au_hdr)){
if(fd >fileno(stderr))
fprintf(stderr,"Can't read header from file %s: %s\n",
filename,strerror(errno));
else
perror("Can't read audio header");
goto done;
}
确定⽂件的格式是否符合Sun/NeXT audio S16_BE格式。
if(au_hdr.magic != AU_MAGIC ||
BE_INT(au_hdr.hdr_size)>128||
BE_INT(au_hdr.hdr_size)<sizeof(au_hdr)||
BE_INT(ding)!= AU_FMT_LIN16){
fprintf(stderr,"Not in Sun/NeXT audio S16_BE format\n");
goto done;
}
判断使⽤sbc编码还是msbc编码。
sbc
1. 初始化sbc。
1. 初始化sbc。
// sbc.c
// sbc_init()
SBC_EXPORT int sbc_init(sbc_t *sbc,unsigned long flags)
{
if(!sbc)
return-EIO;
memset(sbc,0,sizeof(sbc_t));
sbc->priv_alloc_base =malloc(sizeof(struct sbc_priv)+ SBC_ALIGN_MASK);
if(!sbc->priv_alloc_base)
return-ENOMEM;
sbc->priv =(void*)(((uintptr_t) sbc->priv_alloc_base +
fprintf格式
SBC_ALIGN_MASK)&~((uintptr_t) SBC_ALIGN_MASK));
memset(sbc->priv,0,sizeof(struct sbc_priv));
sbc_set_defaults(sbc, flags);
return0;
}
// sbc_set_defaults()
static void sbc_set_defaults(sbc_t *sbc,unsigned long flags)
{
struct sbc_priv *priv = sbc->priv;
if(priv->msbc){
priv->pack_frame = msbc_pack_frame;
priv->unpack_frame = msbc_unpack_frame;
}else{
priv->pack_frame = sbc_pack_frame;
priv->unpack_frame = sbc_unpack_frame;
}
sbc->flags = flags;
sbc->frequency = SBC_FREQ_44100;
sbc->mode = SBC_MODE_STEREO;
sbc->subbands = SBC_SB_8;
sbc->blocks = SBC_BLK_16;
sbc->bitpool =32;
#if __BYTE_ORDER == __LITTLE_ENDIAN
sbc->endian = SBC_LE;
#elif __BYTE_ORDER == __BIG_ENDIAN
sbc->endian = SBC_BE;
#else
#error "Unknown byte order"
#endif
}
2. 设置采样率、⼦带数量等参数。
switch(BE_INT(au_hdr.sample_rate)){
case16000:
sbc.frequency = SBC_FREQ_16000;
break;
case32000:
sbc.frequency = SBC_FREQ_32000;
break;
case44100:
case44100:
sbc.frequency = SBC_FREQ_44100;
break;
case48000:
sbc.frequency = SBC_FREQ_48000;
break;
}
srate =BE_INT(au_hdr.sample_rate);
sbc.subbands = subbands ==4? SBC_SB_4 : SBC_SB_8;
if(BE_INT(au_hdr.channels)==1){
if(joint || dualchannel){
fprintf(stderr,"Audio is mono but joint or "
"dualchannel mode has been specified\n");
goto done;
}
}else if(joint &&!dualchannel)
else if(!joint && dualchannel)
else if(!joint &&!dualchannel)
else{
fprintf(stderr,"Both joint and dualchannel "
"mode have been specified\n");
goto done;
}
sbc.bitpool = bitpool;
sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
sbc.blocks = blocks ==4? SBC_BLK_4 :
blocks ==8? SBC_BLK_8 :
blocks ==12? SBC_BLK_12 : SBC_BLK_16;
mSBC
1. 初始化sbc。
// sbc.c
SBC_EXPORT int sbc_init_msbc(sbc_t *sbc,unsigned long flags)
{
struct sbc_priv *priv;
if(!sbc)
return-EIO;
memset(sbc,0,sizeof(sbc_t));
sbc->priv_alloc_base =malloc(sizeof(struct sbc_priv)+ SBC_ALIGN_MASK);
if(!sbc->priv_alloc_base)
return-ENOMEM;
sbc->priv =(void*)(((uintptr_t) sbc->priv_alloc_base +
SBC_ALIGN_MASK)&~((uintptr_t) SBC_ALIGN_MASK));
memset(sbc->priv,0,sizeof(struct sbc_priv));
priv = sbc->priv;
priv->msbc = true;
sbc_set_defaults(sbc, flags);
sbc_set_defaults(sbc, flags);
sbc->frequency = SBC_FREQ_16000;
sbc->blocks = MSBC_BLOCKS;
sbc->subbands = SBC_SB_8;
sbc->mode = SBC_MODE_MONO;
sbc->allocation = SBC_AM_LOUDNESS;
sbc->bitpool =26;
return0;
}
读⼊⽂件数据,并显⽰详细信息
/* Skip extra bytes of the header if any */
if(read(fd, input,BE_INT(au_hdr.hdr_size)- len)<0)
goto done;
if(verbose){
fprintf(stderr,"encoding %s with rate %d, %d blocks, " "%d subbands, %d bits, allocation method %s, "
"and mode %s\n",
filename, srate, blocks, subbands, bitpool,
sbc.allocation == SBC_AM_SNR ?"SNR":"LOUDNESS",  de == SBC_MODE_MONO ?"MONO":
"STEREO":"JOINTSTEREO");
}
获取编码长度codesize及帧数nframes。
codesize =sbc_get_codesize(&sbc);
nframes =sizeof(input)/ codesize;
// sbc.c
SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
{
uint16_t subbands, channels, blocks;
struct sbc_priv *priv;
priv = sbc->priv;
if(!priv->init){
subbands = sbc->subbands ?8:4;
if(priv->msbc)
blocks = MSBC_BLOCKS;
else
blocks =4+(sbc->blocks *4);
channels = sbc->mode == SBC_MODE_MONO ?1:2;
}else{
subbands = priv->frame.subbands;
blocks = priv->frame.blocks;
channels = priv->frame.channels;
}
return subbands * blocks * channels *2;
}
编码。
while(1){
unsigned char*inp,*outp;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。