mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-26 11:37:10 +00:00
ectracting sbc encoder
This commit is contained in:
parent
2ec72fbbcd
commit
4f0d422d95
@ -161,7 +161,9 @@ typedef struct SBC_ENC_PARAMS_TAG
|
||||
SINT16 s16AllocationMethod; /* loudness or SNR*/
|
||||
SINT16 s16BitPool; /* 16*numOfSb for mono & dual;
|
||||
32*numOfSb for stereo & joint stereo */
|
||||
UINT16 u16BitRate;
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
// UINT16 u16BitRate;
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
UINT8 u8NumPacketToEncode; /* number of sbc frame to encode. Default is 1 */
|
||||
#if (SBC_JOINT_STE_INCLUDED == TRUE)
|
||||
SINT16 as16Join[SBC_MAX_NUM_OF_SUBBANDS]; /*1 if JS, 0 otherwise*/
|
||||
|
50
3rd-party/bluedroid/encoder/srce/sbc_encoder.c
vendored
50
3rd-party/bluedroid/encoder/srce/sbc_encoder.c
vendored
@ -325,14 +325,16 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams)
|
||||
if ( (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO)
|
||||
|| (pstrEncParams->s16ChannelMode == SBC_STEREO) )
|
||||
{
|
||||
s16Bitpool = (SINT16)( (pstrEncParams->u16BitRate *
|
||||
pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq)
|
||||
-( (32 + (4 * pstrEncParams->s16NumOfSubBands *
|
||||
pstrEncParams->s16NumOfChannels)
|
||||
+ ( (pstrEncParams->s16ChannelMode - 2) *
|
||||
pstrEncParams->s16NumOfSubBands ) )
|
||||
/ pstrEncParams->s16NumOfBlocks) );
|
||||
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
// s16Bitpool = (SINT16)( (pstrEncParams->u16BitRate *
|
||||
// pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq)
|
||||
// -( (32 + (4 * pstrEncParams->s16NumOfSubBands *
|
||||
// pstrEncParams->s16NumOfChannels)
|
||||
// + ( (pstrEncParams->s16ChannelMode - 2) *
|
||||
// pstrEncParams->s16NumOfSubBands ) )
|
||||
// / pstrEncParams->s16NumOfBlocks) );
|
||||
s16Bitpool = pstrEncParams->s16BitPool;
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
s16FrameLen = 4 + (4*pstrEncParams->s16NumOfSubBands*
|
||||
pstrEncParams->s16NumOfChannels)/8
|
||||
+ ( ((pstrEncParams->s16ChannelMode - 2) *
|
||||
@ -343,8 +345,10 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams)
|
||||
/ (pstrEncParams->s16NumOfSubBands *
|
||||
pstrEncParams->s16NumOfBlocks * 1000);
|
||||
|
||||
if (s16BitRate > pstrEncParams->u16BitRate)
|
||||
s16Bitpool--;
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
// if (s16BitRate > pstrEncParams->u16BitRate)
|
||||
// s16Bitpool--;
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
|
||||
if(pstrEncParams->s16NumOfSubBands == 8)
|
||||
pstrEncParams->s16BitPool = (s16Bitpool > 255) ? 255 : s16Bitpool;
|
||||
@ -352,17 +356,21 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams)
|
||||
pstrEncParams->s16BitPool = (s16Bitpool > 128) ? 128 : s16Bitpool;
|
||||
}
|
||||
else
|
||||
{
|
||||
s16Bitpool = (SINT16)( ((pstrEncParams->s16NumOfSubBands *
|
||||
pstrEncParams->u16BitRate * 1000)
|
||||
/ (s16SamplingFreq * pstrEncParams->s16NumOfChannels))
|
||||
-( ( (32 / pstrEncParams->s16NumOfChannels) +
|
||||
(4 * pstrEncParams->s16NumOfSubBands) )
|
||||
/ pstrEncParams->s16NumOfBlocks ) );
|
||||
|
||||
pstrEncParams->s16BitPool = (s16Bitpool >
|
||||
(16 * pstrEncParams->s16NumOfSubBands))
|
||||
? (16*pstrEncParams->s16NumOfSubBands) : s16Bitpool;
|
||||
{
|
||||
if (!pstrEncParams->mSBCEnabled){
|
||||
/* BK4BTSTACK_CHANGE START */
|
||||
// s16Bitpool = (SINT16)( ((pstrEncParams->s16NumOfSubBands *
|
||||
// pstrEncParams->u16BitRate * 1000)
|
||||
// / (s16SamplingFreq * pstrEncParams->s16NumOfChannels))
|
||||
// -( ( (32 / pstrEncParams->s16NumOfChannels) +
|
||||
// (4 * pstrEncParams->s16NumOfSubBands) )
|
||||
// / pstrEncParams->s16NumOfBlocks ) );
|
||||
s16Bitpool = pstrEncParams->s16BitPool;
|
||||
/* BK4BTSTACK_CHANGE END */
|
||||
pstrEncParams->s16BitPool = (s16Bitpool >
|
||||
(16 * pstrEncParams->s16NumOfSubBands))
|
||||
? (16*pstrEncParams->s16NumOfSubBands) : s16Bitpool;
|
||||
}
|
||||
}
|
||||
|
||||
if (pstrEncParams->s16BitPool < 0)
|
||||
|
@ -76,6 +76,9 @@ SBC_DECODER += \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_plc.c \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_decoder_bludroid.c \
|
||||
|
||||
SBC_ENCODER += \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_encoder_bludroid.c \
|
||||
|
||||
EXAMPLES = \
|
||||
ancs_client_demo \
|
||||
gap_dedicated_bonding \
|
||||
@ -204,7 +207,7 @@ hsp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} sco_demo
|
||||
hfp_ag_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} sco_demo_util.o hfp.o hfp_gsm_model.o hfp_ag.o hfp_ag_demo.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
hfp_hf_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} sco_demo_util.o hfp.o hfp_hf.o hfp_hf_demo.c
|
||||
hfp_hf_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} sco_demo_util.o hfp.o hfp_hf.o hfp_hf_demo.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
clean:
|
||||
|
57
src/classic/btstack_sbc.h
Normal file
57
src/classic/btstack_sbc.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_sbc.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTSTACK_SBC_H
|
||||
#define __BTSTACK_SBC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum{
|
||||
SBC_MODE_STANDARD,
|
||||
SBC_MODE_mSBC
|
||||
} sbc_mode_t;
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BTSTACK_SBC_H
|
75
src/classic/btstack_sbc_encoder.h
Normal file
75
src/classic/btstack_sbc_encoder.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack_sbc_encoder.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BTSTACK_SBC_ENCODER_H
|
||||
#define __BTSTACK_SBC_ENCODER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "btstack_sbc.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// private
|
||||
void * encoder_state;
|
||||
sbc_mode_t mode;
|
||||
} btstack_sbc_encoder_state_t;
|
||||
|
||||
void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, sbc_mode_t mode,
|
||||
int blocks, int subbands, int allmethod, int sample_rate, int bitpool);
|
||||
|
||||
void btstack_sbc_encoder_process_data(int16_t * input_buffer);
|
||||
|
||||
|
||||
uint8_t * btstack_sbc_encoder_sbc_buffer(void);
|
||||
uint16_t btstack_sbc_encoder_sbc_buffer_length(void);
|
||||
|
||||
int btstack_sbc_encoder_num_subband_samples(void);
|
||||
void btstack_sbc_encoder_dump_context(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BTSTACK_SBC_ENCODER_H
|
168
src/classic/sbc_encoder_bludroid.c
Normal file
168
src/classic/sbc_encoder_bludroid.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2014 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
// *****************************************************************************
|
||||
//
|
||||
// SBC encoder based on Bludroid library
|
||||
//
|
||||
// *****************************************************************************
|
||||
|
||||
#include "btstack_config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack_sbc_encoder.h"
|
||||
#include "sbc_encoder.h"
|
||||
#include "btstack.h"
|
||||
|
||||
#define SBC_MAX_CHANNELS 2
|
||||
|
||||
#define mSBC_SYNCWORD 0xad
|
||||
#define SBC_SYNCWORD 0x9c
|
||||
|
||||
// #define LOG_FRAME_STATUS
|
||||
|
||||
typedef struct {
|
||||
SBC_ENC_PARAMS context;
|
||||
int num_data_bytes;
|
||||
uint8_t sbc_packet[1000];
|
||||
} bludroid_encoder_state_t;
|
||||
|
||||
|
||||
static btstack_sbc_encoder_state_t * sbc_state_singelton = NULL;
|
||||
static bludroid_encoder_state_t bd_state;
|
||||
|
||||
void btstack_sbc_encoder_dump_context(void){
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
|
||||
printf("Blocks %d\n", context->s16NumOfBlocks);
|
||||
printf("SubBands %d\n", context->s16NumOfSubBands);
|
||||
printf("Allocation Method %d\n", context->s16AllocationMethod);
|
||||
printf("BitPool %d\n", context->s16BitPool);
|
||||
printf("Channel Mode %d\n", context->s16ChannelMode);
|
||||
|
||||
printf("Sample Rate ");
|
||||
switch (context->s16SamplingFreq){
|
||||
case 0: printf("16000\n"); break;
|
||||
case 1: printf("32000\n"); break;
|
||||
case 2: printf("44100\n"); break;
|
||||
case 3: printf("48000\n"); break;
|
||||
default: printf("not defined\n"); break;
|
||||
}
|
||||
printf("mSBC Enabled %d\n", context->mSBCEnabled);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int btstack_sbc_encoder_num_subband_samples(void){
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
return context->s16NumOfSubBands * context->s16NumOfBlocks * context->s16NumOfChannels;
|
||||
}
|
||||
|
||||
uint8_t * btstack_sbc_encoder_sbc_buffer(void){
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
return context->pu8Packet;
|
||||
}
|
||||
|
||||
|
||||
uint16_t btstack_sbc_encoder_sbc_buffer_length(void){
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
return context->u16PacketLength;
|
||||
}
|
||||
|
||||
|
||||
void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, sbc_mode_t mode,
|
||||
int blocks, int subbands, int allmethod, int sample_rate, int bitpool){
|
||||
|
||||
if (sbc_state_singelton && sbc_state_singelton != state ){
|
||||
log_error("SBC encoder: different sbc decoder state is allready registered");
|
||||
}
|
||||
|
||||
sbc_state_singelton = state;
|
||||
sbc_state_singelton->mode = mode;
|
||||
|
||||
switch (sbc_state_singelton->mode){
|
||||
case SBC_MODE_STANDARD:
|
||||
bd_state.context.s16NumOfBlocks = blocks;
|
||||
bd_state.context.s16NumOfSubBands = subbands;
|
||||
bd_state.context.s16AllocationMethod = allmethod;
|
||||
bd_state.context.s16BitPool = 31;
|
||||
bd_state.context.mSBCEnabled = 0;
|
||||
|
||||
switch(sample_rate){
|
||||
case 16000: bd_state.context.s16SamplingFreq = SBC_sf16000; break;
|
||||
case 32000: bd_state.context.s16SamplingFreq = SBC_sf32000; break;
|
||||
case 44100: bd_state.context.s16SamplingFreq = SBC_sf44100; break;
|
||||
case 48000: bd_state.context.s16SamplingFreq = SBC_sf48000; break;
|
||||
default: bd_state.context.s16SamplingFreq = 0; break;
|
||||
}
|
||||
break;
|
||||
case SBC_MODE_mSBC:
|
||||
bd_state.context.s16NumOfBlocks = 15;
|
||||
bd_state.context.s16NumOfSubBands = 8;
|
||||
bd_state.context.s16AllocationMethod = SBC_LOUDNESS;
|
||||
bd_state.context.s16BitPool = 26;
|
||||
bd_state.context.s16ChannelMode = SBC_MONO;
|
||||
bd_state.context.s16NumOfChannels = 1;
|
||||
bd_state.context.mSBCEnabled = 1;
|
||||
bd_state.context.s16SamplingFreq = SBC_sf16000;
|
||||
break;
|
||||
}
|
||||
bd_state.context.pu8Packet = bd_state.sbc_packet;
|
||||
|
||||
sbc_state_singelton->encoder_state = &bd_state;
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
SBC_Encoder_Init(context);
|
||||
}
|
||||
|
||||
|
||||
void btstack_sbc_encoder_process_data(int16_t * input_buffer){
|
||||
if (!sbc_state_singelton){
|
||||
log_error("SBC encoder: sbc state is NULL, call btstack_sbc_encoder_init to initialize it");
|
||||
}
|
||||
SBC_ENC_PARAMS * context = &((bludroid_encoder_state_t *)sbc_state_singelton->encoder_state)->context;
|
||||
context->ps16PcmBuffer = input_buffer;
|
||||
if (context->mSBCEnabled){
|
||||
context->pu8Packet[0] = 0xad;
|
||||
}
|
||||
SBC_Encoder(context);
|
||||
}
|
@ -11,6 +11,9 @@ SBC_DECODER += \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_plc.c \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_decoder_bludroid.c \
|
||||
|
||||
SBC_ENCODER += \
|
||||
${BTSTACK_ROOT}/src/classic/sbc_encoder_bludroid.c \
|
||||
|
||||
SBC_DECODER_OBJ = $(SBC_DECODER:.c=.o)
|
||||
SBC_ENCODER_OBJ = $(SBC_ENCODER:.c=.o)
|
||||
|
||||
@ -37,7 +40,7 @@ all: ${SBC_TESTS}
|
||||
sbc_decoder_test: ${SBC_DECODER_OBJ} ${COMMON_OBJ} sbc_decoder_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sbc_encoder_test: ${SBC_ENCODER_OBJ} sbc_encoder_test.o
|
||||
sbc_encoder_test: ${SBC_ENCODER_OBJ} ${COMMON_OBJ} sbc_encoder_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
test: all
|
||||
|
@ -47,40 +47,82 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sbc_encoder.h"
|
||||
|
||||
static SBC_ENC_PARAMS context;
|
||||
static int16_t data[8*16*2];
|
||||
#include "btstack.h"
|
||||
#include "btstack_sbc_encoder.h"
|
||||
|
||||
static int16_t read_buffer[8*16*2];
|
||||
static int num_data_bytes = 0;
|
||||
static uint8_t sbc_packet[1000];
|
||||
static uint8_t buf[4];
|
||||
|
||||
static uint16_t little_endian_read_16(const uint8_t * buffer, int pos){
|
||||
return ((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8);
|
||||
static int byte_rate = 0;
|
||||
static int sampling_frequency = -1;
|
||||
static int channel_mode = -1;
|
||||
|
||||
|
||||
#define MSBC_FRAME_SIZE 57
|
||||
|
||||
static btstack_sbc_encoder_state_t state;
|
||||
static uint8_t msbc_padding[] = {0,0,0};
|
||||
|
||||
static uint8_t msbc_buffer[2*(MSBC_FRAME_SIZE + sizeof(msbc_padding))];
|
||||
static int msbc_buffer_offset = 0;
|
||||
|
||||
void hfp_msbc_init(void);
|
||||
int hfp_msbc_can_encode_audio(void);
|
||||
void hfp_msbc_encode_audio_frame(int16_t * pcm_samples);
|
||||
void hfp_msbc_read_encoded_stream(uint8_t * buf, int size);
|
||||
|
||||
void hfp_msbc_init(void){
|
||||
btstack_sbc_encoder_init(&state, SBC_MODE_mSBC, 16, 8, 0, 16000, 26);
|
||||
msbc_buffer_offset = 0;
|
||||
}
|
||||
|
||||
static uint32_t little_endian_read_32(const uint8_t * buffer, int pos){
|
||||
return ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16) | (((uint32_t) buffer[(pos)+3]) << 24);
|
||||
int hfp_msbc_can_encode_audio(void){
|
||||
return sizeof(msbc_buffer) - msbc_buffer_offset >= MSBC_FRAME_SIZE + sizeof(msbc_padding);
|
||||
}
|
||||
|
||||
void hfp_msbc_encode_audio_frame(int16_t * pcm_samples){
|
||||
if (!hfp_msbc_can_encode_audio()) return;
|
||||
|
||||
btstack_sbc_encoder_process_data(pcm_samples);
|
||||
|
||||
memcpy(msbc_buffer + msbc_buffer_offset, msbc_padding, sizeof(msbc_padding));
|
||||
msbc_buffer_offset += sizeof(msbc_padding);
|
||||
|
||||
memcpy(msbc_buffer + msbc_buffer_offset, btstack_sbc_encoder_sbc_buffer(), MSBC_FRAME_SIZE);
|
||||
msbc_buffer_offset += MSBC_FRAME_SIZE;
|
||||
msbc_buffer_free_bytes = sizeof(msbc_buffer) - msbc_buffer_offset;
|
||||
}
|
||||
|
||||
void hfp_msbc_read_encoded_stream(uint8_t * buf, int size){
|
||||
int bytes_to_copy = size;
|
||||
if (size > msbc_buffer_offset){
|
||||
bytes_to_copy = msbc_buffer_offset;
|
||||
log_error("sbc frame storage is smaller then the output buffer");
|
||||
}
|
||||
|
||||
memcpy(buf, msbc_buffer, bytes_to_copy);
|
||||
memmv(msbc_buffer, msbc_buffer + bytes_to_copy, bytes_to_copy);
|
||||
msbc_buffer_offset -= bytes_to_copy;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t little_endian_fread_16(FILE * fd){
|
||||
uint8_t buf[2];
|
||||
fread(&buf, 1, 2, fd);
|
||||
return little_endian_read_16(buf, 0);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t little_endian_fread_32(FILE * fd){
|
||||
uint8_t buf[4];
|
||||
fread(&buf, 1, 4, fd);
|
||||
return little_endian_read_32(buf, 0);
|
||||
}
|
||||
|
||||
static void read_wav_header(FILE * wav_fd, SBC_ENC_PARAMS *context){
|
||||
static void read_wav_header(FILE * wav_fd){
|
||||
/* write RIFF header */
|
||||
uint8_t buf[10];
|
||||
fread(&buf, 1, 4, wav_fd);
|
||||
buf[4] = 0;
|
||||
// printf("%s\n", buf ); // RIFF
|
||||
fread(&buf, 1, 4, wav_fd); buf[4] = 0; // RIFF
|
||||
|
||||
little_endian_fread_32(wav_fd); // 36 + bytes_per_sample * num_samples * frame_count
|
||||
|
||||
@ -98,28 +140,13 @@ static void read_wav_header(FILE * wav_fd, SBC_ENC_PARAMS *context){
|
||||
little_endian_fread_16(wav_fd);
|
||||
|
||||
// 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){
|
||||
context->s16ChannelMode = SBC_MONO;
|
||||
} else {
|
||||
context->s16ChannelMode = SBC_STEREO;
|
||||
}
|
||||
|
||||
int sample_rate = little_endian_fread_32(wav_fd);
|
||||
|
||||
if (sample_rate == 16000)
|
||||
context->s16SamplingFreq = SBC_sf16000;
|
||||
else if (sample_rate == 32000)
|
||||
context->s16SamplingFreq = SBC_sf32000;
|
||||
else if (sample_rate == 44100)
|
||||
context->s16SamplingFreq = SBC_sf44100;
|
||||
else
|
||||
context->s16SamplingFreq = SBC_sf48000;
|
||||
|
||||
int byte_rate = little_endian_fread_32(wav_fd);
|
||||
context->u16BitRate = byte_rate * 8;
|
||||
|
||||
// chanel mode:
|
||||
channel_mode = little_endian_fread_16(wav_fd);
|
||||
// sampling frequency:
|
||||
sampling_frequency = little_endian_fread_32(wav_fd);
|
||||
// byte rate:
|
||||
byte_rate = little_endian_fread_32(wav_fd);
|
||||
|
||||
// int block_align =
|
||||
little_endian_fread_16(wav_fd);
|
||||
// int bits_per_sample =
|
||||
@ -131,50 +158,16 @@ static void read_wav_header(FILE * wav_fd, SBC_ENC_PARAMS *context){
|
||||
num_data_bytes = little_endian_fread_32(wav_fd);
|
||||
}
|
||||
|
||||
static void read_audio_frame(FILE * wav_fd, SBC_ENC_PARAMS * context){
|
||||
int num_samples = context->s16NumOfSubBands * context->s16NumOfBlocks * context->s16NumOfChannels;
|
||||
static void read_audio_frame(FILE * wav_fd){
|
||||
int i;
|
||||
for (i=0; i < num_samples; i++){
|
||||
data[i] = little_endian_fread_16(wav_fd);
|
||||
for (i=0; i < btstack_sbc_encoder_num_subband_samples(); i++){
|
||||
read_buffer[i] = little_endian_fread_16(wav_fd);
|
||||
}
|
||||
context->ps16PcmBuffer = data;
|
||||
}
|
||||
|
||||
static int sbc_num_frames(SBC_ENC_PARAMS * context){
|
||||
int num_subband_samples = context->s16NumOfSubBands * context->s16NumOfBlocks * context->s16NumOfChannels;
|
||||
static int sbc_num_frames(){
|
||||
int num_all_samples = num_data_bytes / 2;
|
||||
return num_all_samples / num_subband_samples;
|
||||
}
|
||||
|
||||
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");
|
||||
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, 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);
|
||||
return num_all_samples / btstack_sbc_encoder_num_subband_samples();
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
@ -197,22 +190,22 @@ 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_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);
|
||||
|
||||
read_wav_header(wav_fd);
|
||||
btstack_sbc_encoder_init(&state, SBC_MODE_STANDARD, 16, 4, channel_mode, sampling_frequency, 31);
|
||||
|
||||
int num_frames = sbc_num_frames();
|
||||
int frame_count = 0;
|
||||
printf("num frames %d\n", num_frames);
|
||||
|
||||
while (frame_count < num_frames){
|
||||
read_audio_frame(wav_fd, &context);
|
||||
SBC_Encoder(&context);
|
||||
if (context.mSBCEnabled){
|
||||
context.pu8Packet[0] = 0xad;
|
||||
}
|
||||
write_sbc_file(sbc_fd, &context);
|
||||
read_audio_frame(wav_fd);
|
||||
|
||||
btstack_sbc_encoder_process_data(read_buffer);
|
||||
fwrite(btstack_sbc_encoder_sbc_buffer(), 1, btstack_sbc_encoder_sbc_buffer_length(), sbc_fd);
|
||||
frame_count++;
|
||||
}
|
||||
btstack_sbc_encoder_dump_context();
|
||||
|
||||
printf("Done, frame count %d\n", frame_count);
|
||||
fclose(wav_fd);
|
||||
fclose(sbc_fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user