1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "hfp_msbc.c" 39 40 // ***************************************************************************** 41 // 42 // HFP mSBC encoder wrapper 43 // 44 // ***************************************************************************** 45 46 #include "btstack_config.h" 47 48 #include <string.h> 49 50 #include "btstack_debug.h" 51 #include "btstack_sbc.h" 52 #include "hfp_msbc.h" 53 54 #define MSBC_FRAME_SIZE 57 55 #define MSBC_HEADER_H2_SIZE 2 56 #define MSBC_PADDING_SIZE 1 57 #define MSBC_EXTRA_SIZE (MSBC_HEADER_H2_SIZE + MSBC_PADDING_SIZE) 58 59 // const 60 static const uint8_t msbc_header_h2_byte_0 = 1; 61 static const uint8_t msbc_header_h2_byte_1_table[] = { 0x08, 0x38, 0xc8, 0xf8 }; 62 63 static btstack_sbc_encoder_state_t state; 64 static int msbc_sequence_number; 65 66 static uint8_t msbc_buffer[2*(MSBC_FRAME_SIZE + MSBC_EXTRA_SIZE)]; 67 static int msbc_buffer_offset = 0; 68 69 void hfp_msbc_init(void){ 70 btstack_sbc_encoder_init(&state, SBC_MODE_mSBC, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 16000, 26, SBC_CHANNEL_MODE_MONO); 71 msbc_buffer_offset = 0; 72 msbc_sequence_number = 0; 73 } 74 75 void hfp_msbc_deinit(void){ 76 (void) memset(&state, 0, sizeof(btstack_sbc_encoder_state_t)); 77 } 78 79 int hfp_msbc_can_encode_audio_frame_now(void){ 80 return (sizeof(msbc_buffer) - msbc_buffer_offset) >= (MSBC_FRAME_SIZE + MSBC_EXTRA_SIZE); 81 } 82 83 void hfp_msbc_encode_audio_frame(int16_t * pcm_samples){ 84 if (!hfp_msbc_can_encode_audio_frame_now()) return; 85 86 // Synchronization Header H2 87 msbc_buffer[msbc_buffer_offset++] = msbc_header_h2_byte_0; 88 msbc_buffer[msbc_buffer_offset++] = msbc_header_h2_byte_1_table[msbc_sequence_number]; 89 msbc_sequence_number = (msbc_sequence_number + 1) & 3; 90 91 // SBC Frame 92 btstack_sbc_encoder_process_data(pcm_samples); 93 (void)memcpy(msbc_buffer + msbc_buffer_offset, 94 btstack_sbc_encoder_sbc_buffer(), MSBC_FRAME_SIZE); 95 msbc_buffer_offset += MSBC_FRAME_SIZE; 96 97 // Final padding to use 60 bytes for 120 audio samples 98 msbc_buffer[msbc_buffer_offset++] = 0; 99 } 100 101 void hfp_msbc_read_from_stream(uint8_t * buf, int size){ 102 int bytes_to_copy = size; 103 if (size > msbc_buffer_offset){ 104 bytes_to_copy = msbc_buffer_offset; 105 log_error("sbc frame storage is smaller then the output buffer"); 106 return; 107 } 108 109 (void)memcpy(buf, msbc_buffer, bytes_to_copy); 110 memmove(msbc_buffer, msbc_buffer + bytes_to_copy, sizeof(msbc_buffer) - bytes_to_copy); 111 msbc_buffer_offset -= bytes_to_copy; 112 } 113 114 int hfp_msbc_num_bytes_in_stream(void){ 115 return msbc_buffer_offset; 116 } 117 118 int hfp_msbc_num_audio_samples_per_frame(void){ 119 return btstack_sbc_encoder_num_audio_frames(); 120 } 121 122 123