1c21cc0ebSMatthias Ringwald /* 2c21cc0ebSMatthias Ringwald * Copyright (C) 2018 BlueKitchen GmbH 3c21cc0ebSMatthias Ringwald * 4c21cc0ebSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5c21cc0ebSMatthias Ringwald * modification, are permitted provided that the following conditions 6c21cc0ebSMatthias Ringwald * are met: 7c21cc0ebSMatthias Ringwald * 8c21cc0ebSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9c21cc0ebSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10c21cc0ebSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11c21cc0ebSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12c21cc0ebSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13c21cc0ebSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14c21cc0ebSMatthias Ringwald * contributors may be used to endorse or promote products derived 15c21cc0ebSMatthias Ringwald * from this software without specific prior written permission. 16c21cc0ebSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17c21cc0ebSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18c21cc0ebSMatthias Ringwald * monetary gain. 19c21cc0ebSMatthias Ringwald * 20c21cc0ebSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21c21cc0ebSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22c21cc0ebSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25c21cc0ebSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26c21cc0ebSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27c21cc0ebSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28c21cc0ebSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29c21cc0ebSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30c21cc0ebSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c21cc0ebSMatthias Ringwald * SUCH DAMAGE. 32c21cc0ebSMatthias Ringwald * 33c21cc0ebSMatthias Ringwald * Please inquire about commercial licensing options at 34c21cc0ebSMatthias Ringwald * [email protected] 35c21cc0ebSMatthias Ringwald * 36c21cc0ebSMatthias Ringwald */ 37c21cc0ebSMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_resample.c" 39bb2a7656SMatthias Ringwald 4001899c8bSMatthias Ringwald #include "btstack_bool.h" 416e821f1cSMatthias Ringwald #include "btstack_debug.h" 42c21cc0ebSMatthias Ringwald #include "btstack_resample.h" 43c21cc0ebSMatthias Ringwald 44c21cc0ebSMatthias Ringwald void btstack_resample_init(btstack_resample_t * context, int num_channels){ 45c21cc0ebSMatthias Ringwald context->src_pos = 0; 46c21cc0ebSMatthias Ringwald context->src_step = 0x10000; // default resampling 1.0 47c21cc0ebSMatthias Ringwald context->last_sample[0] = 0; 48c21cc0ebSMatthias Ringwald context->last_sample[1] = 0; 49c21cc0ebSMatthias Ringwald context->num_channels = num_channels; 50c21cc0ebSMatthias Ringwald } 51c21cc0ebSMatthias Ringwald 52c21cc0ebSMatthias Ringwald void btstack_resample_set_factor(btstack_resample_t * context, uint32_t src_step){ 53c21cc0ebSMatthias Ringwald context->src_step = src_step; 54c21cc0ebSMatthias Ringwald } 55c21cc0ebSMatthias Ringwald 56c21cc0ebSMatthias Ringwald uint16_t btstack_resample_block(btstack_resample_t * context, const int16_t * input_buffer, uint32_t num_frames, int16_t * output_buffer){ 576e821f1cSMatthias Ringwald btstack_assert(context->num_channels > 0); 586e821f1cSMatthias Ringwald 59c21cc0ebSMatthias Ringwald uint16_t dest_frames = 0; 60c21cc0ebSMatthias Ringwald uint16_t dest_samples = 0; 61c21cc0ebSMatthias Ringwald // samples between last sample of previous block and first sample in current block 62c21cc0ebSMatthias Ringwald while (context->src_pos >= 0xffff0000){ 634ea43905SMatthias Ringwald const uint16_t t = context->src_pos & 0xffffu; 64c21cc0ebSMatthias Ringwald int i; 65c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 66c21cc0ebSMatthias Ringwald int s1 = context->last_sample[i]; 67c21cc0ebSMatthias Ringwald int s2 = input_buffer[i]; 684ea43905SMatthias Ringwald int os = ((s1*(0x10000u - t)) + (s2*t)) >> 16u; 69c21cc0ebSMatthias Ringwald output_buffer[dest_samples++] = os; 70c21cc0ebSMatthias Ringwald } 71c21cc0ebSMatthias Ringwald dest_frames++; 72c21cc0ebSMatthias Ringwald context->src_pos += context->src_step; 73c21cc0ebSMatthias Ringwald } 74c21cc0ebSMatthias Ringwald // process current block 75ff3cc4a5SMatthias Ringwald while (true){ 76c21cc0ebSMatthias Ringwald const uint16_t src_pos = context->src_pos >> 16; 774ea43905SMatthias Ringwald const uint16_t t = context->src_pos & 0xffffu; 78c21cc0ebSMatthias Ringwald int index = src_pos * context->num_channels; 79c21cc0ebSMatthias Ringwald int i; 804ea43905SMatthias Ringwald if (src_pos >= (num_frames - 1u)){ 81c21cc0ebSMatthias Ringwald // store last sample 82*0532fef7SMatthias Ringwald index = (num_frames-1u) * context->num_channels; 83c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 84c21cc0ebSMatthias Ringwald context->last_sample[i] = input_buffer[index++]; 85c21cc0ebSMatthias Ringwald } 86c21cc0ebSMatthias Ringwald // samples processed 87c21cc0ebSMatthias Ringwald context->src_pos -= num_frames << 16; 88c21cc0ebSMatthias Ringwald break; 89c21cc0ebSMatthias Ringwald } 90c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 91c21cc0ebSMatthias Ringwald int s1 = input_buffer[index]; 92c21cc0ebSMatthias Ringwald int s2 = input_buffer[index+context->num_channels]; 934ea43905SMatthias Ringwald int os = ((s1*(0x10000u - t)) + (s2*t)) >> 16u; 94c21cc0ebSMatthias Ringwald output_buffer[dest_samples++] = os; 95c21cc0ebSMatthias Ringwald index++; 96c21cc0ebSMatthias Ringwald } 97c21cc0ebSMatthias Ringwald dest_frames++; 98c21cc0ebSMatthias Ringwald context->src_pos += context->src_step; 99c21cc0ebSMatthias Ringwald } 100c21cc0ebSMatthias Ringwald return dest_frames; 101c21cc0ebSMatthias Ringwald } 102