SBC协议_蓝牙耳机sbc怎么改

2022-10-01 13:16:42 浏览数 (2)

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

sbcenc.c

main(int argc, char *argv[])

首先设定 option 的默认值,然后根据用户命令设定 option 相关参数。

对指定文件进行编码(执行encode函数)

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)

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; void *priv; void *priv_alloc_base; }; typedef struct sbc_struct sbc_t;

定义ssize_t类型的变量encodedlen,实际是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。

代码语言:javascript复制
if (sizeof(au_hdr) != 24) { 
     
		/* Sanity check just in case */
		fprintf(stderr, "FIXME: sizeof(au_hdr) != 24n");
		return;
}

确定指定文件合法性并打开文件。

代码语言:javascript复制
if (strcmp(filename, "-")) { 
     
		fd = open(filename, O_RDONLY);
		if (fd < 0) { 
     
			fprintf(stderr, "Can't open file %s: %sn",
						filename, strerror(errno));
			return;
		}
} else
		fd = fileno(stdin);

将文件中头部数据读入au_hdr,并确定是否读取成功。

代码语言:javascript复制
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: %sn",
				filename, strerror(errno));
	else
		perror("Can't read audio header");
	goto done;
}

确定文件的格式是否符合Sun/NeXT audio S16_BE格式。

代码语言:javascript复制
if (au_hdr.magic != AU_MAGIC ||
			BE_INT(au_hdr.hdr_size) > 128 ||
			BE_INT(au_hdr.hdr_size) < sizeof(au_hdr) ||
			BE_INT(au_hdr.encoding) != AU_FMT_LIN16) { 
     
		fprintf(stderr, "Not in Sun/NeXT audio S16_BE formatn");
		goto done;
}

判断使用sbc编码还是msbc编码。

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 SBC_ALIGN_MASK) & ~((uintptr_t) SBC_ALIGN_MASK)); memset(sbc->priv, 0, sizeof(struct sbc_priv)); sbc_set_defaults(sbc, flags); return 0; } // 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 }

  1. 设置采样率、子带数量等参数。
代码语言:javascript复制
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;
}
srate = BE_INT(au_hdr.sample_rate);
sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
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 specifiedn");
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 specifiedn");
goto done;
}
sbc.endian = SBC_BE;
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->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; return 0; }

读入文件数据,并显示详细信息

代码语言:javascript复制
/* 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 %sn",
filename, srate, blocks, subbands, bitpool,
sbc.allocation == SBC_AM_SNR ? "SNR" : "LOUDNESS",
sbc.mode == SBC_MODE_MONO ? "MONO" :
sbc.mode == SBC_MODE_STEREO ?
"STEREO" : "JOINTSTEREO");
}

获取编码长度codesize及帧数nframes

代码语言:javascript复制
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; }

编码。

代码语言:javascript复制
while (1) { 

unsigned char *inp, *outp;
/* read data for up to 'nframes' frames of input data */
size = read(fd, input, codesize * nframes);
if (size < 0) { 

/* Something really bad happened */
perror("Can't read audio data");
break;
}
if (size < codesize) { 

/* Not enough data for encoding even a single frame */
break;
}
/* encode all the data from the input buffer in a loop */
inp = input;
outp = output;
while (size >= codesize) { 

len = sbc_encode(&sbc, inp, codesize,
outp, sizeof(output) - (outp - output),
&encoded);
if (len != codesize || encoded <= 0) { 

fprintf(stderr,
"sbc_encode fail, len=%zd, encoded=%lun",
len, (unsigned long) encoded);
break;
}
size -= len;
inp  = len;
outp  = encoded;
}
len = write(fileno(stdout), output, outp - output);
if (len != outp - output) { 

perror("Can't write SBC output");
break;
}
if (size != 0) { 

/* * sbc_encode failure has been detected earlier or end * of file reached (have trailing partial data which is * insufficient to encode SBC frame) */
break;
}
}

// sbc.c SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len, void *output, size_t output_len, ssize_t *written) { struct sbc_priv *priv; int samples; ssize_t framelen; int (*sbc_enc_process_input)(int position, const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE], int nsamples, int nchannels); if (!sbc || !input) return -EIO; priv = sbc->priv; if (written) *written = 0; if (!priv->init) { priv->frame.frequency = sbc->frequency; priv->frame.mode = sbc->mode; priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; priv->frame.allocation = sbc->allocation; priv->frame.subband_mode = sbc->subbands; priv->frame.subbands = sbc->subbands ? 8 : 4; priv->frame.block_mode = sbc->blocks; if (priv->msbc) priv->frame.blocks = MSBC_BLOCKS; else priv->frame.blocks = 4 (sbc->blocks * 4); priv->frame.bitpool = sbc->bitpool; priv->frame.codesize = sbc_get_codesize(sbc); priv->frame.length = sbc_get_frame_length(sbc); sbc_encoder_init(priv->msbc, &priv->enc_state, &priv->frame); priv->init = true; } else if (priv->frame.bitpool != sbc->bitpool) { priv->frame.length = sbc_get_frame_length(sbc); priv->frame.bitpool = sbc->bitpool; } /* input must be large enough to encode a complete frame */ if (input_len < priv->frame.codesize) return 0; /* output must be large enough to receive the encoded frame */ if (!output || output_len < priv->frame.length) return -ENOSPC; /* Select the needed input data processing function and call it */ if (priv->frame.subbands == 8) { if (sbc->endian == SBC_BE) sbc_enc_process_input = priv->enc_state.sbc_enc_process_input_8s_be; else sbc_enc_process_input = priv->enc_state.sbc_enc_process_input_8s_le; } else { if (sbc->endian == SBC_BE) sbc_enc_process_input = priv->enc_state.sbc_enc_process_input_4s_be; else sbc_enc_process_input = priv->enc_state.sbc_enc_process_input_4s_le; } priv->enc_state.position = sbc_enc_process_input( priv->enc_state.position, (const uint8_t *) input, priv->enc_state.X, priv->frame.subbands * priv->frame.blocks, priv->frame.channels); samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); if (priv->frame.mode == JOINT_STEREO) { int j = priv->enc_state.sbc_calc_scalefactors_j( priv->frame.sb_sample_f, priv->frame.scale_factor, priv->frame.blocks, priv->frame.subbands); framelen = priv->pack_frame(output, &priv->frame, output_len, j); } else { priv->enc_state.sbc_calc_scalefactors( priv->frame.sb_sample_f, priv->frame.scale_factor, priv->frame.blocks, priv->frame.channels, priv->frame.subbands); framelen = priv->pack_frame(output, &priv->frame, output_len, 0); } if (written) *written = framelen; return samples * priv->frame.channels * 2; } SBC_EXPORT void sbc_finish(sbc_t *sbc) { if (!sbc) return; free(sbc->priv_alloc_base); memset(sbc, 0, sizeof(sbc_t)); }

关闭文件。

代码语言:javascript复制
done:
if (fd > fileno(stderr))
close(fd);
}

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

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

0 人点赞