mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 01:27:41 +00:00
sbc plc: detect zero frames
This commit is contained in:
parent
743c1aead2
commit
611ca09fac
@ -62,6 +62,11 @@ typedef struct {
|
||||
void * decoder_state;
|
||||
sbc_plc_state_t plc_state;
|
||||
sbc_mode_t mode;
|
||||
|
||||
// summary of processed good, bad and zero frames
|
||||
int good_frames_nr;
|
||||
int bad_frames_nr;
|
||||
int zero_frames_nr;
|
||||
} sbc_decoder_state_t;
|
||||
|
||||
void sbc_decoder_init(sbc_decoder_state_t * state, sbc_mode_t mode, void (*callback)(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context), void * context);
|
||||
|
@ -64,6 +64,7 @@
|
||||
#define mSBC_SYNCWORD 0xad
|
||||
#define SBC_SYNCWORD 0x9c
|
||||
|
||||
// #define LOG_FRAME_STATUS
|
||||
|
||||
// Testing only - START
|
||||
static int plc_enabled = 1;
|
||||
@ -79,10 +80,10 @@ 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 h2_sequence_nr;
|
||||
int search_new_sync_word;
|
||||
int sync_word_found;
|
||||
int first_good_frame_found;
|
||||
} bludroid_decoder_state_t;
|
||||
|
||||
|
||||
@ -97,19 +98,33 @@ 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){
|
||||
static int find_sequence_of_zeros(const OI_BYTE *frame_data, OI_UINT32 frame_bytes, int seq_length){
|
||||
int zero_seq_count = 0;
|
||||
int i;
|
||||
for (i=0; i<frame_bytes; i++){
|
||||
if (frame_data[i] == 0) {
|
||||
zero_seq_count++;
|
||||
if (zero_seq_count >= seq_length) return zero_seq_count;
|
||||
} else {
|
||||
zero_seq_count = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_h2_syncword(const OI_BYTE *frame_data, OI_UINT32 frame_bytes, 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) {
|
||||
for (i=0; i<frame_bytes; i++){
|
||||
if (frame_data[i] == syncword) {
|
||||
break;
|
||||
}
|
||||
h2_first_byte = h2_second_byte;
|
||||
h2_second_byte = frameData[i];
|
||||
h2_second_byte = frame_data[i];
|
||||
}
|
||||
if (h2_first_byte != 1) return -1;
|
||||
|
||||
@ -163,20 +178,22 @@ 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.h2_sequence_nr = -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;
|
||||
}
|
||||
bd_state.first_good_frame_found = 0;
|
||||
|
||||
memset(state, 0, sizeof(sbc_decoder_state_t));
|
||||
state->handle_pcm_data = callback;
|
||||
state->mode = mode;
|
||||
state->context = context;
|
||||
state->decoder_state = &bd_state;
|
||||
|
||||
sbc_plc_init(&state->plc_state);
|
||||
}
|
||||
|
||||
@ -195,10 +212,9 @@ 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; // 57 for mSBC frame, 2 for header H2
|
||||
int msbc_frame_size = 57;
|
||||
|
||||
// printf("<<-- enter -->>\n");
|
||||
|
||||
// printf("Process data: in buffer %u, new %u\n", bd_decoder_state->bytes_in_frame_buffer, size);
|
||||
|
||||
while (bytes_to_process > 0){
|
||||
@ -233,41 +249,53 @@ void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int
|
||||
}
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
int zero_seq_found = 0;
|
||||
|
||||
OI_STATUS status = OI_CODEC_SBC_DecodeFrame(&(bd_decoder_state->decoder_context),
|
||||
&frame_data,
|
||||
&(bd_decoder_state->bytes_in_frame_buffer),
|
||||
bd_decoder_state->pcm_plc_data,
|
||||
&(bd_decoder_state->pcm_bytes));
|
||||
if (bd_decoder_state->first_good_frame_found){
|
||||
zero_seq_found = find_sequence_of_zeros(frame_data, bd_decoder_state->bytes_in_frame_buffer, 20);
|
||||
}
|
||||
|
||||
if (zero_seq_found){
|
||||
status = OI_CODEC_SBC_CHECKSUM_MISMATCH;
|
||||
bd_decoder_state->bytes_in_frame_buffer = 0;
|
||||
} else {
|
||||
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_sequence_nr = h2_syncword;
|
||||
}
|
||||
}
|
||||
status = OI_CODEC_SBC_DecodeFrame(&(bd_decoder_state->decoder_context),
|
||||
&frame_data,
|
||||
&(bd_decoder_state->bytes_in_frame_buffer),
|
||||
bd_decoder_state->pcm_plc_data,
|
||||
&(bd_decoder_state->pcm_bytes));
|
||||
}
|
||||
|
||||
bytes_processed = bytes_in_buffer_before - bd_decoder_state->bytes_in_frame_buffer;
|
||||
|
||||
switch(status){
|
||||
case 0:
|
||||
#ifdef LOG_FRAME_STATUS
|
||||
printf("%d : OK\n", bd_decoder_state->h2_sequence_nr);
|
||||
if (bd_decoder_state->h2_sequence_nr == 3) printf("\n");
|
||||
#endif
|
||||
bd_decoder_state->first_good_frame_found = 1;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
state->good_frames_nr++;
|
||||
continue;
|
||||
case OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA:
|
||||
case OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA:
|
||||
@ -275,22 +303,35 @@ void sbc_decoder_process_data(sbc_decoder_state_t * state, uint8_t * buffer, int
|
||||
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 (!bd_decoder_state->first_good_frame_found) break;
|
||||
|
||||
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");
|
||||
if (!bd_decoder_state->sync_word_found){
|
||||
bd_decoder_state->h2_sequence_nr = (bd_decoder_state->h2_sequence_nr + 1)%4;
|
||||
}
|
||||
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 (zero_seq_found){
|
||||
state->zero_frames_nr++;
|
||||
} else {
|
||||
state->bad_frames_nr++;
|
||||
}
|
||||
|
||||
#ifdef LOG_FRAME_STATUS
|
||||
if (zero_seq_found){
|
||||
printf("%d : ZERO FRAME\n", bd_decoder_state->h2_sequence_nr);
|
||||
} else {
|
||||
printf("%d : BAD FRAME\n", bd_decoder_state->h2_sequence_nr);
|
||||
}
|
||||
if (bd_decoder_state->h2_sequence_nr == 3) printf("\n");
|
||||
#endif
|
||||
if (!plc_enabled) break;
|
||||
|
||||
frame_data = sbc_plc_zero_signal_frame();
|
||||
|
@ -64,7 +64,7 @@ typedef struct wav_writer_state {
|
||||
} wav_writer_state_t;
|
||||
|
||||
static void show_usage(void){
|
||||
printf("\n\nUsage: ./sbc_decoder_test input.sbc output.wav msbc|sbc\n\n");
|
||||
printf("\n\nUsage: ./sbc_decoder_test input_file msbc|sbc plc_enabled(0|1) corrupt_frame_period\n\n");
|
||||
}
|
||||
|
||||
static ssize_t __read(int fd, void *buf, size_t count){
|
||||
@ -154,13 +154,23 @@ int main (int argc, const char * argv[]){
|
||||
const int plc_enabled = atoi(argv[3]);
|
||||
const int corrupt_frame_period = atoi(argv[4]);
|
||||
|
||||
printf("\n");
|
||||
if (strncmp(argv[2], "msbc", 4) == 0 ){
|
||||
mode = SBC_MODE_mSBC;
|
||||
printf("Using SBC_MODE_mSBC mode, plc enabled = %d\n", plc_enabled);
|
||||
printf("Using SBC_MODE_mSBC mode.\n");
|
||||
} else {
|
||||
printf("Using SBC_MODE_STANDARD mode, plc enabled = %d\n", plc_enabled);
|
||||
printf("Using SBC_MODE_STANDARD mode.\n");
|
||||
}
|
||||
|
||||
if (plc_enabled){
|
||||
printf("PLC enabled.\n");
|
||||
} else {
|
||||
printf("PLC disbled.\n");
|
||||
}
|
||||
|
||||
if (corrupt_frame_period > 0){
|
||||
printf("Corrupt frame period: every %d frames.\n", corrupt_frame_period);
|
||||
}
|
||||
if (mode == SBC_MODE_mSBC){
|
||||
strcat(sbc_filename, ".msbc");
|
||||
} else {
|
||||
@ -209,7 +219,9 @@ int main (int argc, const char * argv[]){
|
||||
|
||||
fclose(wav_file);
|
||||
close(fd);
|
||||
int total_frames_nr = state.good_frames_nr + state.bad_frames_nr + state.zero_frames_nr;
|
||||
|
||||
printf("Write %d frames to wav file: %s\n", wav_writer_state.frame_count, wav_filename);
|
||||
printf("\nDecoding done. Processed totaly %d frames:\n - %d good\n - %d bad\n - %d zero frames\n", total_frames_nr, state.good_frames_nr, state.bad_frames_nr, state.zero_frames_nr);
|
||||
printf("Write %d frames to wav file: %s\n\n", wav_writer_state.frame_count, wav_filename);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user