ectracting sbc encoder

This commit is contained in:
Milanka Ringwald 2016-07-22 17:32:44 +02:00
parent 2ec72fbbcd
commit 4f0d422d95
8 changed files with 420 additions and 111 deletions

View File

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

View File

@ -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)

View File

@ -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
View 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

View 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

View 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);
}

View File

@ -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

View File

@ -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);