sbc decoder: get sequence nr from H2 header

This commit is contained in:
Milanka Ringwald 2016-07-15 16:02:22 +02:00
parent a7e6f4dda0
commit 743c1aead2
3 changed files with 144 additions and 17 deletions

View File

@ -71,6 +71,10 @@ int sbc_decoder_num_samples_per_frame(sbc_decoder_state_t * state);
int sbc_decoder_num_channels(sbc_decoder_state_t * state);
int sbc_decoder_sample_rate(sbc_decoder_state_t * state);
// testing only
void sbc_decoder_test_disable_plc(void);
void sbc_decoder_test_simulate_corrupt_frames(int period);
#if defined __cplusplus
}
#endif

View File

@ -61,6 +61,15 @@
#define SBC_MAX_CHANNELS 2
#define DECODER_DATA_SIZE (SBC_MAX_CHANNELS*SBC_MAX_BLOCKS*SBC_MAX_BANDS * 2 + SBC_CODEC_MIN_FILTER_BUFFERS*SBC_MAX_BANDS*SBC_MAX_CHANNELS * 2)
#define mSBC_SYNCWORD 0xad
#define SBC_SYNCWORD 0x9c
// Testing only - START
static int plc_enabled = 1;
static int corrupt_frame_period = -1;
// Testing - STOP
typedef struct {
OI_UINT32 bytes_in_frame_buffer;
OI_CODEC_SBC_DECODER_CONTEXT decoder_context;
@ -70,11 +79,51 @@ typedef struct {
int16_t pcm_data[SBC_MAX_CHANNELS * SBC_MAX_BANDS * SBC_MAX_BLOCKS];
uint32_t pcm_bytes;
OI_UINT32 decoder_data[(DECODER_DATA_SIZE+3)/4];
int corrupt_frame;
int h2_syncword;
int search_new_sync_word;
int sync_word_found;
} bludroid_decoder_state_t;
static sbc_decoder_state_t * sbc_state_singelton = NULL;
static bludroid_decoder_state_t bd_state;
void sbc_decoder_test_disable_plc(void){
plc_enabled = 0;
}
void sbc_decoder_test_simulate_corrupt_frames(int period){
corrupt_frame_period = period;
}
static int find_h2_syncword(const OI_BYTE *frameData, OI_UINT32 frameBytes, sbc_mode_t mode){
if (mode != SBC_MODE_mSBC) return -1;
int syncword = mSBC_SYNCWORD;
uint8_t h2_first_byte = 0;
uint8_t h2_second_byte = 0;
int i;
for (i=0; i<frameBytes; i++){
if (frameData[i] == syncword) {
break;
}
h2_first_byte = h2_second_byte;
h2_second_byte = frameData[i];
}
if (h2_first_byte != 1) return -1;
// check if upper nibble of second byte is 0x08
uint8_t ln = h2_second_byte & 0x0F;
if (ln != 8) return -1;
// check that bits 0+2 == bits 1+3
uint8_t hn = h2_second_byte >> 4;
if ( ((hn>>1) & 0x05) != (hn & 0x05) ) return -1;
return ((hn & 0x04) >> 1) | (hn & 0x01);
}
int sbc_decoder_num_samples_per_frame(sbc_decoder_state_t * state){
bludroid_decoder_state_t * decoder_state = (bludroid_decoder_state_t *) state->decoder_state;
return decoder_state->decoder_context.common.frameInfo.nrof_blocks * decoder_state->decoder_context.common.frameInfo.nrof_subbands;
@ -116,11 +165,18 @@ void sbc_decoder_init(sbc_decoder_state_t * state, sbc_mode_t mode, void (*callb
sbc_state_singelton = state;
bd_state.bytes_in_frame_buffer = 0;
bd_state.pcm_bytes = sizeof(bd_state.pcm_data);
bd_state.h2_syncword = -1;
bd_state.sync_word_found = 0;
bd_state.search_new_sync_word = 0;
if (mode == SBC_MODE_mSBC){
bd_state.search_new_sync_word = 1;
}
state->handle_pcm_data = callback;
state->mode = mode;
state->context = context;
state->decoder_state = &bd_state;
sbc_plc_init(&state->plc_state);
}
@ -139,7 +195,7 @@ static void append_received_sbc_data(bludroid_decoder_state_t * state, uint8_t *
void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int size){
bludroid_decoder_state_t * bd_decoder_state = (bludroid_decoder_state_t*)state->decoder_state;
int bytes_to_process = size;
int msbc_frame_size = 57;
int msbc_frame_size = 57; // 57 for mSBC frame, 2 for header H2
// printf("<<-- enter -->>\n");
@ -167,6 +223,25 @@ void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int
uint16_t bytes_processed = 0;
const OI_BYTE *frame_data = bd_decoder_state->frame_buffer;
static int frame_count = 0;
if (corrupt_frame_period > 0){
frame_count++;
if (frame_count % corrupt_frame_period == 0){
*(uint8_t*)&frame_data[5] = 0;
frame_count = 0;
}
}
if (bd_decoder_state->search_new_sync_word && !bd_decoder_state->sync_word_found){
int h2_syncword = find_h2_syncword(frame_data, bd_decoder_state->bytes_in_frame_buffer, state->mode);
if (h2_syncword != -1){
bd_decoder_state->sync_word_found = 1;
bd_decoder_state->h2_syncword = h2_syncword;
}
}
// printf("Sync1: %d\n", bd_decoder_state->h2_syncword);
OI_STATUS status = OI_CODEC_SBC_DecodeFrame(&(bd_decoder_state->decoder_context),
&frame_data,
&(bd_decoder_state->bytes_in_frame_buffer),
@ -175,31 +250,49 @@ void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int
bytes_processed = bytes_in_buffer_before - bd_decoder_state->bytes_in_frame_buffer;
// printf("Decode status %u, processed %u, left %u\n", status, bytes_processed, bd_decoder_state->bytes_in_frame_buffer);
memmove(bd_decoder_state->frame_buffer, bd_decoder_state->frame_buffer + bytes_processed, bd_decoder_state->bytes_in_frame_buffer);
//printf("frame_count %d, expected frame len %d, bytes in frame %d \n", frame_count, OI_CODEC_SBC_CalculateFramelen(&bd_decoder_state->decoder_context.common.frameInfo), bytes_in_buffer_before);
switch(status){
case 0:
// printf("OK: \n");
if (state->mode == SBC_MODE_mSBC){
printf("%d : OK\n", bd_decoder_state->h2_syncword);
bd_decoder_state->search_new_sync_word = 1;
bd_decoder_state->sync_word_found = 0;
} else {
printf("OK\n");
}
if (bd_decoder_state->h2_syncword == 3) printf("\n");
sbc_plc_good_frame(&state->plc_state, bd_decoder_state->pcm_plc_data, bd_decoder_state->pcm_data);
state->handle_pcm_data(bd_decoder_state->pcm_data,
sbc_decoder_num_samples_per_frame(state),
sbc_decoder_num_channels(state),
sbc_decoder_sample_rate(state), state->context);
continue;
case OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA:
case OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA:
// printf("NOT_ENOUGH_DATA: \n");
// printf(" NOT_ENOUGH_DATA\n");
if (bd_decoder_state->sync_word_found){
bd_decoder_state->search_new_sync_word = 0;
}
// do nothing
break;
case OI_CODEC_SBC_NO_SYNCWORD:
case OI_CODEC_SBC_CHECKSUM_MISMATCH:
// printf("NO_SYNCWORD or CHECKSUM_MISMATCH\n");
bd_decoder_state->bytes_in_frame_buffer = 0;
if (state->mode == SBC_MODE_mSBC){
bd_decoder_state->h2_syncword = (bd_decoder_state->h2_syncword +1)%4;
printf("%d : BAD FRAME\n", bd_decoder_state->h2_syncword);
if (bd_decoder_state->h2_syncword == 3) printf("\n");
bd_decoder_state->search_new_sync_word = 1;
bd_decoder_state->sync_word_found = 0;
} else {
printf("BAD FRAME\n");
}
bd_decoder_state->bytes_in_frame_buffer = 0;
if (!plc_enabled) break;
frame_data = sbc_plc_zero_signal_frame();
OI_UINT32 bytes_in_frame_buffer = msbc_frame_size;
@ -216,12 +309,15 @@ void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int
sbc_decoder_num_samples_per_frame(state),
sbc_decoder_num_channels(state),
sbc_decoder_sample_rate(state), state->context);
break;
default:
printf("Frame decode error: %d\n", status);
break;
}
memmove(bd_decoder_state->frame_buffer, bd_decoder_state->frame_buffer + bytes_processed, bd_decoder_state->bytes_in_frame_buffer);
}
// printf ("<<-- exit -->>\n");
}

View File

@ -143,16 +143,36 @@ int main (int argc, const char * argv[]){
sbc_mode_t mode = SBC_MODE_STANDARD;
const char * sbc_filename = argv[1];
const char * wav_filename = argv[2];
const char * filename = argv[1];
char sbc_filename[30];
char wav_filename[30];
strcpy(sbc_filename, filename);
strcpy(wav_filename, filename);
const int plc_enabled = atoi(argv[3]);
const int corrupt_frame_period = atoi(argv[4]);
if (strncmp(argv[3], "msbc", 4) == 0 ){
if (strncmp(argv[2], "msbc", 4) == 0 ){
mode = SBC_MODE_mSBC;
printf("Using SBC_MODE_mSBC mode\n");
printf("Using SBC_MODE_mSBC mode, plc enabled = %d\n", plc_enabled);
} else {
printf("Using SBC_MODE_STANDARD mode\n");
printf("Using SBC_MODE_STANDARD mode, plc enabled = %d\n", plc_enabled);
}
if (mode == SBC_MODE_mSBC){
strcat(sbc_filename, ".msbc");
} else {
strcat(sbc_filename, ".sbc");
}
if (plc_enabled){
strcat(wav_filename, "_plc.wav");
} else {
strcat(wav_filename, ".wav");
}
int fd = open(sbc_filename, O_RDONLY);
if (fd < 0) {
printf("Can't open file %s", sbc_filename);
@ -167,8 +187,15 @@ int main (int argc, const char * argv[]){
sbc_decoder_state_t state;
sbc_decoder_init(&state, mode, &handle_pcm_data, (void*)&wav_writer_state);
write_wav_header(wav_writer_state.wav_file, 0, 0, 0);
if (!plc_enabled){
sbc_decoder_test_disable_plc();
}
if (corrupt_frame_period > 0){
sbc_decoder_test_simulate_corrupt_frames(corrupt_frame_period);
}
write_wav_header(wav_writer_state.wav_file, 0, 0, 0);
while (1){
// get next chunk
int bytes_read = __read(fd, read_buffer, sizeof(read_buffer));