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 23c21cc0ebSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24c21cc0ebSMatthias Ringwald * RINGWALD 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" 41c21cc0ebSMatthias Ringwald #include "btstack_resample.h" 42c21cc0ebSMatthias Ringwald 43c21cc0ebSMatthias Ringwald void btstack_resample_init(btstack_resample_t * context, int num_channels){ 44c21cc0ebSMatthias Ringwald context->src_pos = 0; 45c21cc0ebSMatthias Ringwald context->src_step = 0x10000; // default resampling 1.0 46c21cc0ebSMatthias Ringwald context->last_sample[0] = 0; 47c21cc0ebSMatthias Ringwald context->last_sample[1] = 0; 48c21cc0ebSMatthias Ringwald context->num_channels = num_channels; 49c21cc0ebSMatthias Ringwald } 50c21cc0ebSMatthias Ringwald 51c21cc0ebSMatthias Ringwald void btstack_resample_set_factor(btstack_resample_t * context, uint32_t src_step){ 52c21cc0ebSMatthias Ringwald context->src_step = src_step; 53c21cc0ebSMatthias Ringwald } 54c21cc0ebSMatthias Ringwald 55c21cc0ebSMatthias Ringwald uint16_t btstack_resample_block(btstack_resample_t * context, const int16_t * input_buffer, uint32_t num_frames, int16_t * output_buffer){ 56c21cc0ebSMatthias Ringwald uint16_t dest_frames = 0; 57c21cc0ebSMatthias Ringwald uint16_t dest_samples = 0; 58c21cc0ebSMatthias Ringwald // samples between last sample of previous block and first sample in current block 59c21cc0ebSMatthias Ringwald while (context->src_pos >= 0xffff0000){ 60*4ea43905SMatthias Ringwald const uint16_t t = context->src_pos & 0xffffu; 61c21cc0ebSMatthias Ringwald int i; 62c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 63c21cc0ebSMatthias Ringwald int s1 = context->last_sample[i]; 64c21cc0ebSMatthias Ringwald int s2 = input_buffer[i]; 65*4ea43905SMatthias Ringwald int os = ((s1*(0x10000u - t)) + (s2*t)) >> 16u; 66c21cc0ebSMatthias Ringwald output_buffer[dest_samples++] = os; 67c21cc0ebSMatthias Ringwald } 68c21cc0ebSMatthias Ringwald dest_frames++; 69c21cc0ebSMatthias Ringwald context->src_pos += context->src_step; 70c21cc0ebSMatthias Ringwald } 71c21cc0ebSMatthias Ringwald // process current block 72ff3cc4a5SMatthias Ringwald while (true){ 73c21cc0ebSMatthias Ringwald const uint16_t src_pos = context->src_pos >> 16; 74*4ea43905SMatthias Ringwald const uint16_t t = context->src_pos & 0xffffu; 75c21cc0ebSMatthias Ringwald int index = src_pos * context->num_channels; 76c21cc0ebSMatthias Ringwald int i; 77*4ea43905SMatthias Ringwald if (src_pos >= (num_frames - 1u)){ 78c21cc0ebSMatthias Ringwald // store last sample 79c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 80c21cc0ebSMatthias Ringwald context->last_sample[i] = input_buffer[index++]; 81c21cc0ebSMatthias Ringwald } 82c21cc0ebSMatthias Ringwald // samples processed 83c21cc0ebSMatthias Ringwald context->src_pos -= num_frames << 16; 84c21cc0ebSMatthias Ringwald break; 85c21cc0ebSMatthias Ringwald } 86c21cc0ebSMatthias Ringwald for (i=0;i<context->num_channels;i++){ 87c21cc0ebSMatthias Ringwald int s1 = input_buffer[index]; 88c21cc0ebSMatthias Ringwald int s2 = input_buffer[index+context->num_channels]; 89*4ea43905SMatthias Ringwald int os = ((s1*(0x10000u - t)) + (s2*t)) >> 16u; 90c21cc0ebSMatthias Ringwald output_buffer[dest_samples++] = os; 91c21cc0ebSMatthias Ringwald index++; 92c21cc0ebSMatthias Ringwald } 93c21cc0ebSMatthias Ringwald dest_frames++; 94c21cc0ebSMatthias Ringwald context->src_pos += context->src_step; 95c21cc0ebSMatthias Ringwald } 96c21cc0ebSMatthias Ringwald return dest_frames; 97c21cc0ebSMatthias Ringwald } 98