diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2014-01-20 11:26:00 +0200 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2014-01-21 11:03:28 +0200 |
commit | 5cb59902a6fd2c6d4a0f8c6c0ab447602b54c555 (patch) | |
tree | 2f23b3b2a4d5a941d61458b1c58dd7d951834643 | |
parent | c0a74816996faa8fa5fd87a80570936910f1f165 (diff) | |
download | sbc-5cb59902a6fd2c6d4a0f8c6c0ab447602b54c555.tar.gz |
sbc: Add sbc_init_a2dp
This adds sbc_init_a2dp that can be used to convert A2DP configuration to
the internal representation since they are not binary compatible.
-rw-r--r-- | sbc/sbc.c | 144 | ||||
-rw-r--r-- | sbc/sbc.h | 2 |
2 files changed, 146 insertions, 0 deletions
@@ -57,6 +57,55 @@ #define MSBC_SYNCWORD 0xAD #define MSBC_BLOCKS 15 +#define A2DP_SAMPLING_FREQ_16000 (1 << 3) +#define A2DP_SAMPLING_FREQ_32000 (1 << 2) +#define A2DP_SAMPLING_FREQ_44100 (1 << 1) +#define A2DP_SAMPLING_FREQ_48000 (1 << 0) + +#define A2DP_CHANNEL_MODE_MONO (1 << 3) +#define A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2) +#define A2DP_CHANNEL_MODE_STEREO (1 << 1) +#define A2DP_CHANNEL_MODE_JOINT_STEREO (1 << 0) + +#define A2DP_BLOCK_LENGTH_4 (1 << 3) +#define A2DP_BLOCK_LENGTH_8 (1 << 2) +#define A2DP_BLOCK_LENGTH_12 (1 << 1) +#define A2DP_BLOCK_LENGTH_16 (1 << 0) + +#define A2DP_SUBBANDS_4 (1 << 1) +#define A2DP_SUBBANDS_8 (1 << 0) + +#define A2DP_ALLOCATION_SNR (1 << 1) +#define A2DP_ALLOCATION_LOUDNESS (1 << 0) + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +struct a2dp_sbc { + uint8_t channel_mode:4; + uint8_t frequency:4; + uint8_t allocation_method:2; + uint8_t subbands:2; + uint8_t block_length:4; + uint8_t min_bitpool; + uint8_t max_bitpool; +} __attribute__ ((packed)); + +#elif __BYTE_ORDER == __BIG_ENDIAN + +struct a2dp_sbc { + uint8_t frequency:4; + uint8_t channel_mode:4; + uint8_t block_length:4; + uint8_t subbands:2; + uint8_t allocation_method:2; + uint8_t min_bitpool; + uint8_t max_bitpool; +} __attribute__ ((packed)); + +#else +#error "Unknown byte order" +#endif + /* This structure contains an unpacked SBC frame. Yes, there is probably quite some unused space herein */ struct sbc_frame { @@ -1046,6 +1095,101 @@ SBC_EXPORT int sbc_init_msbc(sbc_t *sbc, unsigned long flags) return 0; } +SBC_EXPORT int sbc_init_a2dp(sbc_t *sbc, unsigned long flags, + const void *conf, size_t conf_len) +{ + const struct a2dp_sbc *a2dp; + int err; + + if (conf_len != sizeof(*a2dp)) + return -EINVAL; + + err = sbc_init(sbc, flags); + if (err < 0) + return err; + + a2dp = conf; + + switch (a2dp->frequency) { + case A2DP_SAMPLING_FREQ_16000: + sbc->frequency = SBC_FREQ_16000; + break; + case A2DP_SAMPLING_FREQ_32000: + sbc->frequency = SBC_FREQ_32000; + break; + case A2DP_SAMPLING_FREQ_44100: + sbc->frequency = SBC_FREQ_44100; + break; + case A2DP_SAMPLING_FREQ_48000: + sbc->frequency = SBC_FREQ_48000; + break; + default: + goto failed; + } + + switch (a2dp->channel_mode) { + case A2DP_CHANNEL_MODE_MONO: + sbc->mode = SBC_MODE_MONO; + break; + case A2DP_CHANNEL_MODE_DUAL_CHANNEL: + sbc->mode = SBC_MODE_DUAL_CHANNEL; + break; + case A2DP_CHANNEL_MODE_STEREO: + sbc->mode = SBC_MODE_STEREO; + break; + case A2DP_CHANNEL_MODE_JOINT_STEREO: + sbc->mode = SBC_MODE_JOINT_STEREO; + break; + default: + goto failed; + } + + switch (a2dp->allocation_method) { + case A2DP_ALLOCATION_SNR: + sbc->allocation = SBC_AM_SNR; + break; + case A2DP_ALLOCATION_LOUDNESS: + sbc->allocation = SBC_AM_LOUDNESS; + break; + default: + goto failed; + } + + switch (a2dp->subbands) { + case A2DP_SUBBANDS_4: + sbc->subbands = SBC_SB_4; + break; + case A2DP_SUBBANDS_8: + sbc->subbands = SBC_SB_8; + break; + default: + goto failed; + } + + switch (a2dp->block_length) { + case A2DP_BLOCK_LENGTH_4: + sbc->blocks = SBC_BLK_4; + break; + case A2DP_BLOCK_LENGTH_8: + sbc->blocks = SBC_BLK_8; + break; + case A2DP_BLOCK_LENGTH_12: + sbc->blocks = SBC_BLK_12; + break; + case A2DP_BLOCK_LENGTH_16: + sbc->blocks = SBC_BLK_16; + break; + default: + goto failed; + } + + return 0; + +failed: + sbc_finish(sbc); + return -EINVAL; +} + SBC_EXPORT ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len) { return sbc_decode(sbc, input, input_len, NULL, 0, NULL); @@ -84,6 +84,8 @@ typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); int sbc_reinit(sbc_t *sbc, unsigned long flags); int sbc_init_msbc(sbc_t *sbc, unsigned long flags); +int sbc_init_a2dp(sbc_t *sbc, unsigned long flags, + const void *conf, size_t conf_len); ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len); |