mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-26 11:37:10 +00:00
mSBC: extend SBC library for mSBC
This commit is contained in:
parent
f33cc9ef94
commit
435e3c4e0d
@ -170,6 +170,9 @@ typedef struct {
|
||||
OI_BYTE formatByte;
|
||||
OI_UINT8 pcmStride;
|
||||
OI_UINT8 maxChannels;
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
OI_UINT8 mSBCEnabled; // default 0
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
} OI_CODEC_SBC_COMMON_CONTEXT;
|
||||
|
||||
|
||||
@ -237,6 +240,12 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
OI_UINT8 pcmStride,
|
||||
OI_BOOL enhanced);
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
OI_UINT32 *decoderData,
|
||||
OI_UINT32 decoderDataBytes);
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
/**
|
||||
* This function restricts the kind of SBC frames that the Decoder will
|
||||
* process. Its use is optional. If used, it must be called after
|
||||
@ -295,6 +304,7 @@ OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context
|
||||
OI_UINT8 alloc,
|
||||
OI_UINT8 maxBitpool);
|
||||
|
||||
|
||||
/**
|
||||
* Decode one SBC frame. The frame has no header bytes. The context must have been previously
|
||||
* initialized by calling OI_CODEC_SBC_DecoderConfigureRaw().
|
||||
|
@ -66,6 +66,12 @@ Function prototypes and macro definitions used internally by the codec.
|
||||
#include "oi_assert.h"
|
||||
#include "oi_codec_sbc.h"
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
#ifndef OI_mSBC_SYNCWORD
|
||||
#define OI_mSBC_SYNCWORD 0xad
|
||||
#endif
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
#ifndef OI_SBC_SYNCWORD
|
||||
#define OI_SBC_SYNCWORD 0x9c
|
||||
#endif
|
||||
|
@ -90,9 +90,14 @@ INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE
|
||||
OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
|
||||
OI_UINT8 d1;
|
||||
|
||||
|
||||
OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD);
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
if (common->mSBCEnabled){
|
||||
OI_ASSERT(data[0] == OI_mSBC_SYNCWORD);
|
||||
} else {
|
||||
OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD);
|
||||
}
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
/* Avoid filling out all these strucutures if we already remember the values
|
||||
* from last time. Just in case we get a stream corresponding to data[1] ==
|
||||
* 0, DecoderReset is responsible for ensuring the lookup table entries have
|
||||
@ -105,7 +110,14 @@ INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE
|
||||
frame->frequency = freq_values[frame->freqIndex];
|
||||
|
||||
frame->blocks = (d1 & (BIT5 | BIT4)) >> 4;
|
||||
frame->nrof_blocks = block_values[frame->blocks];
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
if (common->mSBCEnabled){
|
||||
frame->nrof_blocks = 15;
|
||||
} else {
|
||||
frame->nrof_blocks = block_values[frame->blocks];
|
||||
}
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
frame->mode = (d1 & (BIT3 | BIT2)) >> 2;
|
||||
frame->nrof_channels = channel_values[frame->mode];
|
||||
|
20
3rd-party/bluedroid/decoder/srce/decoder-sbc.c
vendored
20
3rd-party/bluedroid/decoder/srce/decoder-sbc.c
vendored
@ -76,7 +76,13 @@ PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
return OI_CODEC_SBC_NO_SYNCWORD;
|
||||
}
|
||||
#else // SBC_ENHANCED
|
||||
while (*frameBytes && (**frameData != OI_SBC_SYNCWORD)) {
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
OI_UINT8 syncword = OI_SBC_SYNCWORD;
|
||||
if (context->common.mSBCEnabled){
|
||||
syncword = OI_mSBC_SYNCWORD;
|
||||
}
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
while (*frameBytes && (**frameData != syncword)) {
|
||||
(*frameBytes)--;
|
||||
(*frameData)++;
|
||||
}
|
||||
@ -223,6 +229,7 @@ PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
OI_UINT32 *decoderData,
|
||||
OI_UINT32 decoderDataBytes,
|
||||
@ -233,6 +240,17 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced);
|
||||
}
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
OI_UINT32 *decoderData,
|
||||
OI_UINT32 decoderDataBytes)
|
||||
{
|
||||
OI_STATUS status = OI_CODEC_SBC_DecoderReset(context, decoderData, decoderDataBytes, 1, 1, FALSE);
|
||||
context->common.mSBCEnabled = TRUE;
|
||||
return status;
|
||||
}
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
|
||||
const OI_BYTE **frameData,
|
||||
OI_UINT32 *frameBytes,
|
||||
|
@ -157,7 +157,7 @@ typedef struct SBC_ENC_PARAMS_TAG
|
||||
SINT16 s16ChannelMode; /* mono, dual, streo or joint streo*/
|
||||
SINT16 s16NumOfSubBands; /* 4 or 8 */
|
||||
SINT16 s16NumOfChannels;
|
||||
SINT16 s16NumOfBlocks; /* 4, 8, 12 or 16*/
|
||||
SINT16 s16NumOfBlocks; /* SBC: 4, 8, 12 or 16; mSBC: 15*/
|
||||
SINT16 s16AllocationMethod; /* loudness or SNR*/
|
||||
SINT16 s16BitPool; /* 16*numOfSb for mono & dual;
|
||||
32*numOfSb for stereo & joint stereo */
|
||||
@ -187,7 +187,9 @@ typedef struct SBC_ENC_PARAMS_TAG
|
||||
UINT8 *pu8NextPacket;
|
||||
UINT16 FrameHeader;
|
||||
UINT16 u16PacketLength;
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
UINT8 mSBCEnabled;
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
}SBC_ENC_PARAMS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -371,6 +371,8 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams)
|
||||
HeaderParams = ((pstrEncParams->s16SamplingFreq & 3)<< 6);
|
||||
|
||||
/* number of blocks*/
|
||||
UINT8 num = (((pstrEncParams->s16NumOfBlocks -4) & 12) << 2);
|
||||
printf("number of blocks %d, %d\n", num, pstrEncParams->s16NumOfBlocks);
|
||||
HeaderParams |= (((pstrEncParams->s16NumOfBlocks -4) & 12) << 2);
|
||||
|
||||
/* channel mode: mono, dual...*/
|
||||
|
@ -82,7 +82,8 @@ void EncPacking(SBC_ENC_PARAMS *pstrEncParams)
|
||||
#endif
|
||||
|
||||
pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/
|
||||
*pu8PacketPtr++ = (UINT8)0x9C; /*Sync word*/
|
||||
|
||||
*pu8PacketPtr++ = (UINT8)0xAD; /*Sync word*/
|
||||
*pu8PacketPtr++=(UINT8)(pstrEncParams->FrameHeader);
|
||||
|
||||
*pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF);
|
||||
|
@ -104,6 +104,7 @@ void little_endian_fstore_32(FILE *wav_file, uint32_t value){
|
||||
fwrite(&buf, 1, 4, wav_file);
|
||||
}
|
||||
|
||||
|
||||
static void write_wav_header(FILE * wav_file, int num_samples, int num_channels, int sample_rate, int frame_count){
|
||||
unsigned int bytes_per_sample = 2;
|
||||
|
||||
@ -170,14 +171,13 @@ int main (int argc, const char * argv[]){
|
||||
const OI_BYTE *frameData = data;
|
||||
|
||||
OI_UINT32 pcmBytes = sizeof(pcmData);
|
||||
|
||||
OI_STATUS status = OI_CODEC_SBC_DecoderReset(&context, decoderData, sizeof(decoderData), 1, 1, FALSE);
|
||||
// OI_STATUS status = OI_CODEC_SBC_DecoderReset(&context, decoderData, sizeof(decoderData), 1, 1, FALSE);
|
||||
|
||||
OI_STATUS status = OI_CODEC_mSBC_DecoderReset(&context, decoderData, sizeof(decoderData));
|
||||
if (status != 0){
|
||||
printf("Reset decoder error %d\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int num_samples = 0;
|
||||
int num_channels = 0;
|
||||
int sample_rate = 0;
|
||||
|
@ -80,22 +80,24 @@ static void read_wav_header(FILE * wav_fd, SBC_ENC_PARAMS *context){
|
||||
uint8_t buf[10];
|
||||
fread(&buf, 1, 4, wav_fd);
|
||||
buf[4] = 0;
|
||||
printf("%s\n", buf ); // RIFF
|
||||
// printf("%s\n", buf ); // RIFF
|
||||
|
||||
little_endian_fread_32(wav_fd); // 36 + bytes_per_sample * num_samples * frame_count
|
||||
|
||||
fread(&buf, 1, 4, wav_fd);
|
||||
buf[4] = 0;
|
||||
printf("%s\n", buf ); // WAVE
|
||||
// printf("%s\n", buf ); // WAVE
|
||||
|
||||
fread(&buf, 1, 4, wav_fd);
|
||||
buf[4] = 0;
|
||||
printf("%s\n", buf ); // fmt
|
||||
// printf("%s\n", buf ); // fmt
|
||||
|
||||
int fmt_length = little_endian_fread_32(wav_fd);
|
||||
int fmt_format_tag = little_endian_fread_16(wav_fd);
|
||||
// int fmt_length =
|
||||
little_endian_fread_32(wav_fd);
|
||||
// int fmt_format_tag =
|
||||
little_endian_fread_16(wav_fd);
|
||||
|
||||
printf("fmt_length %d == 16, format %d == 1\n", fmt_length, fmt_format_tag);
|
||||
// printf("fmt_length %d == 16, format %d == 1\n", fmt_length, fmt_format_tag);
|
||||
|
||||
context->s16NumOfChannels = little_endian_fread_16(wav_fd);
|
||||
if (context->s16NumOfChannels == 1){
|
||||
@ -124,7 +126,7 @@ static void read_wav_header(FILE * wav_fd, SBC_ENC_PARAMS *context){
|
||||
little_endian_fread_16(wav_fd);
|
||||
|
||||
fread(&buf, 1, 4, wav_fd);
|
||||
printf("%s\n", buf ); // data
|
||||
// printf("%s\n", buf ); // data
|
||||
|
||||
num_data_bytes = little_endian_fread_32(wav_fd);
|
||||
}
|
||||
@ -145,22 +147,33 @@ static int sbc_num_frames(SBC_ENC_PARAMS * context){
|
||||
}
|
||||
|
||||
static void write_sbc_file(FILE * sbc_fd, SBC_ENC_PARAMS * context){
|
||||
int i;
|
||||
for (i=0;i<context->u16PacketLength;i++){
|
||||
printf("%02x ", context->pu8Packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// int i;
|
||||
// for (i=0;i<context->u16PacketLength;i++){
|
||||
// printf("%02x ", context->pu8Packet[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
printf("write %u bytes\n", context->u16PacketLength);
|
||||
fwrite(context->pu8Packet, 1, context->u16PacketLength, sbc_fd);
|
||||
}
|
||||
|
||||
static void SBC_Encoder_Context_Init(SBC_ENC_PARAMS * context, FILE * fd, int blocks, int subbands, int allmethod, int bitpool){
|
||||
static void SBC_Encoder_Context_Init(SBC_ENC_PARAMS * context, FILE * fd, int blocks, int subbands, int allmethod, int bitpool, int chmode, int mSBCEnabled){
|
||||
|
||||
if (mSBCEnabled){
|
||||
blocks = 15;
|
||||
subbands = 8;
|
||||
allmethod = SBC_LOUDNESS;
|
||||
bitpool = 26;
|
||||
chmode = SBC_MONO;
|
||||
}
|
||||
|
||||
context->s16NumOfSubBands = subbands;
|
||||
context->s16NumOfBlocks = blocks;
|
||||
context->s16AllocationMethod = allmethod;
|
||||
context->s16BitPool = bitpool;
|
||||
context->pu8Packet = sbc_packet;
|
||||
|
||||
context->s16ChannelMode = chmode;
|
||||
context->mSBCEnabled = mSBCEnabled;
|
||||
|
||||
read_wav_header(fd, context);
|
||||
}
|
||||
|
||||
@ -184,19 +197,23 @@ int main (int argc, const char * argv[]){
|
||||
return -1;
|
||||
}
|
||||
|
||||
SBC_Encoder_Context_Init(&context, wav_fd, SBC_BLOCK_3, SUB_BANDS_4, SBC_LOUDNESS, 31);
|
||||
SBC_Encoder_Context_Init(&context, wav_fd, SBC_BLOCK_3, SUB_BANDS_4, SBC_LOUDNESS, 31, SBC_MONO, 1);
|
||||
SBC_Encoder_Init(&context);
|
||||
|
||||
printf("channels %d, subbands %d, blocks %d\n", context.s16NumOfChannels, context.s16NumOfSubBands, context.s16NumOfBlocks);
|
||||
int num_frames = sbc_num_frames(&context);
|
||||
int frame_count = 0;
|
||||
printf("num frames %d\n", num_frames);
|
||||
while (frame_count < num_frames){
|
||||
printf("frame_count %d\n", frame_count);
|
||||
read_audio_frame(wav_fd, &context);
|
||||
SBC_Encoder(&context);
|
||||
if (context.mSBCEnabled){
|
||||
context.pu8Packet[0] = 0xad;
|
||||
}
|
||||
write_sbc_file(sbc_fd, &context);
|
||||
frame_count++;
|
||||
}
|
||||
printf("Done, frame count %d\n", frame_count);
|
||||
fclose(wav_fd);
|
||||
fclose(sbc_fd);
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user