【藍牙sbc協議】sbc源碼閱讀筆記(二)——sbc_struct詳解(上)

sbc_struct結構詳解


sbc_struct結構的定義:
// 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;
  1. flags

    unsigned long類型。在調用sbc_init(&sbc, 0L);sbc_init_msbc(&sbc, 0);的時候作爲第二個參數傳入,並在函數中,繼續傳遞給sbc_set_defaults函數,在sbc_set_defaults中賦值給sbc->flags

    待補充:作用

    /* 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;
    	···
    }
    
  2. frequency

    uint8_t類型,用來表示採樣率,取值有16k,32k,44.1k,48k。

    /* 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。

    /* 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。

    /* 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;
    		}
        ···
      }
      ···
    }
    
  3. blocks

    類型爲uint8_t,sbc編碼的取值有4,8,12,16,msbc爲15。

    待補充:作用

    /* 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。

    /* 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()中進行賦值。

    /* 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
        ···
      }
      ···
    }
    
  4. subbands

    uint8_t類型,表示子帶數量,取值範圍爲4,8。

    /* sbc.h */
    /* subbands */
    #define SBC_SB_4		0x00
    #define SBC_SB_8		0x01
    

    sbc_set_defaults()中默認設置爲8。

    encode()中進行賦值。

    /* 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
        ···
      }
      ···
    }
    
  5. mode

    uint8_t類型,表示聲道模式,支持單聲道、雙聲道、立體聲和聯合立體聲。

    /* 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()中進行賦值。

    /* 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默認單聲道
        ···
      }
      ···
    }
    
  6. allocation

    uint8_t類型,表示每個子頻段幅值比特數的分配方法,有響度和信噪比。

    /* sbc.h */
    /* allocation method */
    #define SBC_AM_LOUDNESS		0x00
    #define SBC_AM_SNR		0x01
    

    默認爲SBC_AM_LOUDNESS,在encode()中賦值。

    /* 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
        ···
      }
      ···
    }
    
  7. bitpool

    uint8_t類型,表示幅值的比特數,默認爲32,msbc默認爲26。

    /* 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
        ···
      }
      ···
    }
    
  8. endian

    uint8_t類型,用來表示主機字節序(大端、小端),默認爲大端。

    /* sbc.h */
    /* data endianess */
    #define SBC_LE			0x00
    #define SBC_BE			0x01
    

    sbc_set_defaults()中判斷並賦值。

    /* 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章