From 79b02f79ab95d5314fe0ff250a2c8d5727813da9 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Thu, 19 Nov 2020 13:25:14 +0100 Subject: [PATCH] btstack_sbc: introduce btstack_sbc_channel_mode_t and btstack_sbc_allocation_method_t --- example/a2dp_sink_demo.c | 45 ++++++++++++++----- example/a2dp_source_demo.c | 36 ++++++++------- src/classic/btstack_sbc.h | 19 ++++++-- src/classic/btstack_sbc_encoder_bluedroid.c | 7 +-- src/classic/hfp_msbc.c | 2 +- .../sine_encode_decode_performance_test.c | 2 +- .../sine_encode_decode_ring_buffer_test.c | 2 +- test/avdtp/sine_encode_decode_test.c | 2 +- test/pts/avrcp_test.c | 45 ++++++++++++++----- 9 files changed, 112 insertions(+), 48 deletions(-) diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index 9404479f4..a5338672e 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -131,18 +131,18 @@ static char * sbc_filename = "av2dp_sink_demo.sbc"; typedef struct { int reconfigure; + int num_channels; int sampling_frequency; - int channel_mode; int block_length; int subbands; - int allocation_method; int min_bitpool_value; int max_bitpool_value; - int frames_per_buffer; -} avdtp_media_codec_configuration_sbc_t; + btstack_sbc_channel_mode_t channel_mode; + btstack_sbc_allocation_method_t allocation_method; +} media_codec_configuration_sbc_t; -static avdtp_media_codec_configuration_sbc_t sbc_configuration; +static media_codec_configuration_sbc_t sbc_configuration; static int volume_percentage = 0; #ifdef SUPPORT_VOLUME_CHANGE_NOTIFICATION @@ -378,7 +378,7 @@ static void handle_pcm_data(int16_t * data, int num_audio_frames, int num_channe } } -static int media_processing_init(avdtp_media_codec_configuration_sbc_t configuration){ +static int media_processing_init(media_codec_configuration_sbc_t configuration){ if (media_initialized) return 0; btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL); @@ -569,7 +569,7 @@ static int read_media_data_header(uint8_t *packet, int size, int *offset, avdtp_ return 1; } -static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configuration){ +static void dump_sbc_configuration(media_codec_configuration_sbc_t configuration){ printf(" - num_channels: %d\n", configuration.num_channels); printf(" - sampling_frequency: %d\n", configuration.sampling_frequency); printf(" - channel_mode: %d\n", configuration.channel_mode); @@ -857,6 +857,9 @@ static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint bd_addr_t address; uint8_t status; + uint8_t channel_mode; + uint8_t allocation_method; + if (packet_type != HCI_EVENT_PACKET) return; if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; @@ -869,13 +872,35 @@ static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); - sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); - sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); - sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; + + allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); + channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); + + // Adapt Bluetooth spec definition to SBC Encoder expected input + sbc_configuration.allocation_method = (btstack_sbc_allocation_method_t)(allocation_method - 1); + sbc_configuration.num_channels = SBC_CHANNEL_MODE_STEREO; + switch (channel_mode){ + case AVDTP_SBC_JOINT_STEREO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO; + break; + case AVDTP_SBC_STEREO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_STEREO; + break; + case AVDTP_SBC_DUAL_CHANNEL: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL; + break; + case AVDTP_SBC_MONO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_MONO; + sbc_configuration.num_channels = 1; + break; + default: + btstack_assert(false); + break; + } dump_sbc_configuration(sbc_configuration); if (sbc_configuration.reconfigure){ diff --git a/example/a2dp_source_demo.c b/example/a2dp_source_demo.c index 62e90d3c1..3af1feaf9 100644 --- a/example/a2dp_source_demo.c +++ b/example/a2dp_source_demo.c @@ -150,16 +150,16 @@ static const int num_samples_sine_int16_48000 = sizeof(sine_int16_48000) / 2; typedef struct { int reconfigure; + int num_channels; int sampling_frequency; - int channel_mode; int block_length; int subbands; - int allocation_method; int min_bitpool_value; int max_bitpool_value; - int frames_per_buffer; -} avdtp_media_codec_configuration_sbc_t; + btstack_sbc_channel_mode_t channel_mode; + btstack_sbc_allocation_method_t allocation_method; +} media_codec_configuration_sbc_t; static btstack_packet_callback_registration_t hci_event_callback_registration; @@ -184,7 +184,7 @@ static uint8_t sdp_avrcp_target_service_buffer[200]; static uint8_t sdp_avrcp_controller_service_buffer[200]; static uint8_t device_id_sdp_service_buffer[100]; -static avdtp_media_codec_configuration_sbc_t sbc_configuration; +static media_codec_configuration_sbc_t sbc_configuration; static btstack_sbc_encoder_state_t sbc_encoder_state; static uint8_t media_sbc_codec_configuration[4]; @@ -510,7 +510,7 @@ static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ btstack_run_loop_remove_timer(&context->audio_timer); } -static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t * configuration){ +static void dump_sbc_configuration(media_codec_configuration_sbc_t * configuration){ printf("Received media codec configuration:\n"); printf(" - num_channels: %d\n", configuration->num_channels); printf(" - sampling_frequency: %d\n", configuration->sampling_frequency); @@ -554,6 +554,9 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui bd_addr_t address; uint16_t cid; + uint8_t channel_mode; + uint8_t allocation_method; + if (packet_type != HCI_EVENT_PACKET) return; if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; @@ -583,33 +586,34 @@ static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, ui sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); - sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); - sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); - sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; + + channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); + allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); + printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid 0x%02x, remote seid 0x%02x.\n", sbc_configuration.sampling_frequency, cid, a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(packet), a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(packet)); // Adapt Bluetooth spec definition to SBC Encoder expected input - sbc_configuration.allocation_method -= 1; - sbc_configuration.num_channels = 2; - switch (sbc_configuration.channel_mode){ + sbc_configuration.allocation_method = (btstack_sbc_allocation_method_t)(allocation_method - 1); + sbc_configuration.num_channels = SBC_CHANNEL_MODE_STEREO; + switch (channel_mode){ case AVDTP_SBC_JOINT_STEREO: - sbc_configuration.channel_mode = 3; + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO; break; case AVDTP_SBC_STEREO: - sbc_configuration.channel_mode = 2; + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_STEREO; break; case AVDTP_SBC_DUAL_CHANNEL: - sbc_configuration.channel_mode = 1; + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL; break; case AVDTP_SBC_MONO: - sbc_configuration.channel_mode = 0; + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_MONO; sbc_configuration.num_channels = 1; break; default: diff --git a/src/classic/btstack_sbc.h b/src/classic/btstack_sbc.h index 9cd5661aa..95d69c769 100644 --- a/src/classic/btstack_sbc.h +++ b/src/classic/btstack_sbc.h @@ -50,11 +50,23 @@ extern "C" { #endif -typedef enum{ - SBC_MODE_STANDARD, +typedef enum { + SBC_MODE_STANDARD = 0, SBC_MODE_mSBC } btstack_sbc_mode_t; +typedef enum { + SBC_CHANNEL_MODE_MONO = 0, + SBC_CHANNEL_MODE_DUAL_CHANNEL, + SBC_CHANNEL_MODE_STEREO, + SBC_CHANNEL_MODE_JOINT_STEREO +} btstack_sbc_channel_mode_t; + +typedef enum { + SBC_ALLOCATION_METHOD_LOUDNESS = 0, + SBC_ALLOCATION_METHOD_SNR +} btstack_sbc_allocation_method_t; + typedef struct { void * context; void (*handle_pcm_data)(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context); @@ -126,7 +138,8 @@ int btstack_sbc_decoder_sample_rate(btstack_sbc_decoder_state_t * state); * @param channel_mode */ void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, btstack_sbc_mode_t mode, - int blocks, int subbands, int allocation_method, int sample_rate, int bitpool, int channel_mode); + int blocks, int subbands, btstack_sbc_allocation_method_t allocation_method, + int sample_rate, int bitpool, btstack_sbc_channel_mode_t channel_mode); /** * @brief Encode PCM data diff --git a/src/classic/btstack_sbc_encoder_bluedroid.c b/src/classic/btstack_sbc_encoder_bluedroid.c index ad400a83d..a9402ed71 100644 --- a/src/classic/btstack_sbc_encoder_bluedroid.c +++ b/src/classic/btstack_sbc_encoder_bluedroid.c @@ -72,7 +72,8 @@ static bludroid_encoder_state_t bd_encoder_state; void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, btstack_sbc_mode_t mode, - int blocks, int subbands, int allmethod, int sample_rate, int bitpool, int channel_mode){ + int blocks, int subbands, btstack_sbc_allocation_method_t allocation_method, + int sample_rate, int bitpool, btstack_sbc_channel_mode_t channel_mode){ if (sbc_encoder_state_singleton && (sbc_encoder_state_singleton != state) ){ log_error("SBC encoder: different sbc decoder state is allready registered"); @@ -90,10 +91,10 @@ void btstack_sbc_encoder_init(btstack_sbc_encoder_state_t * state, btstack_sbc_m case SBC_MODE_STANDARD: bd_encoder_state.context.s16NumOfBlocks = blocks; bd_encoder_state.context.s16NumOfSubBands = subbands; - bd_encoder_state.context.s16AllocationMethod = allmethod; + bd_encoder_state.context.s16AllocationMethod = (uint8_t)allocation_method; bd_encoder_state.context.s16BitPool = bitpool; bd_encoder_state.context.mSBCEnabled = 0; - bd_encoder_state.context.s16ChannelMode = channel_mode; + bd_encoder_state.context.s16ChannelMode = (uint8_t)channel_mode; bd_encoder_state.context.s16NumOfChannels = 2; if (bd_encoder_state.context.s16ChannelMode == SBC_MONO){ bd_encoder_state.context.s16NumOfChannels = 1; diff --git a/src/classic/hfp_msbc.c b/src/classic/hfp_msbc.c index e237b0ceb..a403568bf 100644 --- a/src/classic/hfp_msbc.c +++ b/src/classic/hfp_msbc.c @@ -66,7 +66,7 @@ static uint8_t msbc_buffer[2*(MSBC_FRAME_SIZE + MSBC_EXTRA_SIZE)]; static int msbc_buffer_offset = 0; void hfp_msbc_init(void){ - btstack_sbc_encoder_init(&state, SBC_MODE_mSBC, 16, 8, 0, 16000, 26, 0); + btstack_sbc_encoder_init(&state, SBC_MODE_mSBC, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 16000, 26, SBC_CHANNEL_MODE_MONO); msbc_buffer_offset = 0; msbc_sequence_number = 0; } diff --git a/test/avdtp/sine_encode_decode_performance_test.c b/test/avdtp/sine_encode_decode_performance_test.c index 00105d7a1..c185cd267 100644 --- a/test/avdtp/sine_encode_decode_performance_test.c +++ b/test/avdtp/sine_encode_decode_performance_test.c @@ -106,7 +106,7 @@ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ (void) argc; (void) argv; - btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53); + btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 44100, 53, SBC_CHANNEL_MODE_STEREO); /* initialise sinusoidal wavetable */ int i; diff --git a/test/avdtp/sine_encode_decode_ring_buffer_test.c b/test/avdtp/sine_encode_decode_ring_buffer_test.c index b3ab508ab..307e97bc0 100644 --- a/test/avdtp/sine_encode_decode_ring_buffer_test.c +++ b/test/avdtp/sine_encode_decode_ring_buffer_test.c @@ -224,7 +224,7 @@ int btstack_main(int argc, const char * argv[]){ (void) argc; (void) argv; local_stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, AVDTP_AUDIO); - btstack_sbc_encoder_init(&(local_stream_endpoint->sbc_encoder_state), SBC_MODE_STANDARD, 16, 8, 2, 44100, 53); + btstack_sbc_encoder_init(&(local_stream_endpoint->sbc_encoder_state), SBC_MODE_STANDARD, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 44100, 53, SBC_CHANNEL_MODE_STEREO); /* initialise sinusoidal wavetable */ int i; diff --git a/test/avdtp/sine_encode_decode_test.c b/test/avdtp/sine_encode_decode_test.c index 25972cc28..1a68bc9f3 100644 --- a/test/avdtp/sine_encode_decode_test.c +++ b/test/avdtp/sine_encode_decode_test.c @@ -110,7 +110,7 @@ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ (void) argc; (void) argv; - btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53); + btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 44100, 53, SBC_CHANNEL_MODE_STEREO); /* initialise sinusoidal wavetable */ int i; diff --git a/test/pts/avrcp_test.c b/test/pts/avrcp_test.c index 728b98667..5d41be9fe 100644 --- a/test/pts/avrcp_test.c +++ b/test/pts/avrcp_test.c @@ -209,16 +209,16 @@ typedef struct { typedef struct { int reconfigure; + int num_channels; int sampling_frequency; - int channel_mode; int block_length; int subbands; - int allocation_method; int min_bitpool_value; int max_bitpool_value; - int frames_per_buffer; -} avdtp_media_codec_configuration_sbc_t; + btstack_sbc_channel_mode_t channel_mode; + btstack_sbc_allocation_method_t allocation_method; +} media_codec_configuration_sbc_t; static uint8_t ertm_buffer[10000]; @@ -329,7 +329,7 @@ avrcp_track_t tracks[] = { }; int current_track_index; avrcp_play_status_info_t play_info; -static avdtp_media_codec_configuration_sbc_t sbc_configuration; +static media_codec_configuration_sbc_t sbc_configuration; static btstack_sbc_encoder_state_t sbc_encoder_state; static uint8_t media_sbc_codec_configuration[4]; @@ -398,6 +398,9 @@ static void avdtp_source_connection_establishment_packet_handler(uint8_t packet_ bd_addr_t address; uint16_t cid; + uint8_t channel_mode; + uint8_t allocation_method; + if (packet_type != HCI_EVENT_PACKET) return; switch (hci_event_packet_get_type(packet)){ case HCI_EVENT_PIN_CODE_REQUEST: @@ -450,24 +453,42 @@ static void avdtp_source_connection_establishment_packet_handler(uint8_t packet_ sbc_configuration.reconfigure = avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); sbc_configuration.num_channels = avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); sbc_configuration.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); - sbc_configuration.channel_mode = avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); sbc_configuration.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); sbc_configuration.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); - sbc_configuration.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); sbc_configuration.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); sbc_configuration.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); - sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; + allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); + channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); + + // Adapt Bluetooth spec definition to SBC Encoder expected input + sbc_configuration.allocation_method = (btstack_sbc_allocation_method_t)(allocation_method - 1); + sbc_configuration.num_channels = SBC_CHANNEL_MODE_STEREO; + switch (channel_mode){ + case AVDTP_SBC_JOINT_STEREO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO; + break; + case AVDTP_SBC_STEREO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_STEREO; + break; + case AVDTP_SBC_DUAL_CHANNEL: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL; + break; + case AVDTP_SBC_MONO: + sbc_configuration.channel_mode = SBC_CHANNEL_MODE_MONO; + sbc_configuration.num_channels = 1; + break; + default: + btstack_assert(false); + break; + } + btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, sbc_configuration.block_length, sbc_configuration.subbands, sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, sbc_configuration.max_bitpool_value, sbc_configuration.channel_mode); - // status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); - // if (status != ERROR_CODE_SUCCESS){ - // printf("Could not perform command, status 0x%2x\n", status); - // } break; }