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;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。

    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;}
    } elsefd = 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));elseperror("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(au_hdr.encoding) != AU_FMT_LIN16) {fprintf(stderr, "Not in Sun/NeXT audio S16_BE format\n");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_ENDIANsbc->endian = SBC_LE;
    #elif __BYTE_ORDER == __BIG_ENDIANsbc->endian = SBC_BE;
    #else
    #error "Unknown byte order"
    #endif
    }
    
    1. 设置采样率、子带数量等参数。
    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 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;}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;
    }
    

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

    /* 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",sbc.mode == SBC_MODE_MONO ? "MONO" :sbc.mode == SBC_MODE_STEREO ?"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;elseblocks = 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;/* 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=%lu\n",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;elsepriv->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;elsesbc_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;elsesbc_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));
    }
    

    关闭文件。

    done:if (fd > fileno(stderr))close(fd);
    }
    

【蓝牙sbc协议】sbc源码阅读笔记(一)——编码过程相关推荐

  1. [Linux] USB-Storage驱动 源码阅读笔记(一)

    USB-Storage驱动 源码阅读笔记--从USB子系统开始 最近在研究U盘的驱动,遇到很多难以理解的问题,虽然之前也参考过一些很不错的书籍如:<USB那些事>,但最终还是觉得下载一份最 ...

  2. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

  3. 源码阅读笔记 BiLSTM+CRF做NER任务 流程图

    源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...

  4. 代码分析:NASM源码阅读笔记

    NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...

  5. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...

  6. Yii源码阅读笔记 - 日志组件

    2015-03-09 一 By youngsterxyf 使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category); Yii: ...

  7. AQS源码阅读笔记(一)

    AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node {//表示当前节点以共享模式等待锁static final Node SHA ...

  8. 【Flink】Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型

    1.概述 转载:Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型 相似文章:[Flink]Flink 基于 MailBox 实现的 StreamTask 线程模型 Fl ...

  9. 【Flink】Flink 源码阅读笔记(18)- Flink SQL 中的流和动态表

    1.概述 转载:Flink 源码阅读笔记(18)- Flink SQL 中的流和动态表

  10. 【Flink】Flink 源码阅读笔记(16)- Flink SQL 的元数据管理

    1.概述 转载:Flink 源码阅读笔记(16)- Flink SQL 的元数据管理 Flink 源码阅读笔记(17)- Flink SQL 中的时间属

最新文章

  1. Overleaf-LaTex表格制作
  2. python编程语言是什么-Python编程语言的特点是什么?老男孩Python学习
  3. 一篇文章教会你使用html+css3制作GIF图
  4. ng-options track by 思考
  5. JAVA里16进制和字节数组互转
  6. asp.net 的web.config文件编写
  7. java定时任务管理_基于SpringBoot+layui秒级定时任务管理:JTimer for JAVA项目
  8. 开发基础框架:mybatis-3.2.8 +hibernate4.0+spring3.0+struts2.3
  9. 记事本写小程序C语言,抖音上用记事本编写爱心小程序教程
  10. 《大学》全文及白话翻译
  11. Matlab实现雷达波位编排
  12. [Frank kelly] 经济学理论对TCP的收敛性和公平性做出分析,从理论上论证了TCP在互联网环境下的稳定性和有效性
  13. ubuntu系统压力测试工具--stress
  14. Android端简单数据库实现
  15. 软件测试的16种测试类型
  16. 解决go数据表查询结构体对应字段null问题(sqlx converting NULL to string is unsupported)
  17. 交换机配置计算机mac地址吗,局域网管理,设置网络核心交换机,局域网电脑IP-MAC地址绑定...
  18. js -- 打开新窗口(window.open)、关闭窗口(window.close)
  19. 用 Python 实现英文单词纠错功能!这样就不担心不会辅导孩子了!
  20. Blockchain for Internet of Energy management: Review, solutions, and challenges

热门文章

  1. java如何通过域名查ip_Java实现通过IP获取域名,通过域名获取IP
  2. java excel checkbox_在Java窗体表格中插入复选框
  3. 关于图片格式的选择,jpg、png、gif、svg
  4. 国稻种芯百团计划行动 丰收节贸促会·黎志康:惠及亚非18国家
  5. 首届IBC“社会影响力奖”表彰行业多元化、可持续发展和伦理领导
  6. 工业和信息化部工业企业问卷调查系统
  7. 高位十字星收盘什么意思?高位十字星缩量是什么?
  8. 计算机二级excel设置宏,Excel2013中为宏指定快捷键的方法
  9. 不是美工,如何使用ps快速更换图标icon的颜色?
  10. cyj等于什么英语单词_英语解题方法指导及例题分析