├── .gitignore ├── LICENSE ├── decoder └── decoder.vcxproj ├── encoder └── encoder.vcxproj ├── external ├── dr_flac.h ├── dr_mp3.h ├── dr_wav.h ├── libsamplerate │ ├── COPYING │ ├── check_asm.sh │ ├── common.h │ ├── fastest_coeffs.h │ ├── high_qual_coeffs.h │ ├── mid_qual_coeffs.h │ ├── samplerate.c │ ├── samplerate.h │ ├── src_linear.c │ ├── src_sinc.c │ └── src_zoh.c ├── optionparser.h └── stb_vorbis.c ├── lfac.sln ├── lfac.vcxproj ├── readme.md ├── src ├── decoder.cpp ├── encoder.cpp └── vq.hpp └── subdiv.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.filters 2 | *.user 3 | .vs/ 4 | Debug/ 5 | Release/ 6 | encoder/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /decoder/decoder.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {a1cc2dc1-0035-42fa-8375-1178b4d57c12} 25 | decoder 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /encoder/encoder.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {1f1fee25-f637-49c2-afe5-3d811b13012b} 25 | encoder 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /external/libsamplerate/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2016, Erik de Castro Lopo 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 16 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /external/libsamplerate/check_asm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2004-2011 Erik de Castro Lopo 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 18 | 19 | #======================================================================= 20 | # This short test script compiles the file src_sinc.c into assembler 21 | # output and the greps the assembler output for the fldcw (FPU Load 22 | # Control Word) instruction which is very detrimental to the perfromance 23 | # of floating point code. 24 | 25 | echo -n " Checking assembler output for bad code : " 26 | 27 | if [ $# -ne 1 ]; then 28 | echo "Error : Need the name of the input file." 29 | exit 1 30 | fi 31 | 32 | filename=$1 33 | 34 | if [ ! -f $filename ];then 35 | echo "Error : Can't find file $filename." 36 | exit 1 37 | fi 38 | 39 | count=`grep fldcw $filename | wc -l` 40 | 41 | if [ $count -gt 0 ]; then 42 | echo -e "\n\nError : found $count bad instructions.\n\n" 43 | exit 1 44 | fi 45 | 46 | echo "ok" 47 | 48 | -------------------------------------------------------------------------------- /external/libsamplerate/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #define ENABLE_SINC_BEST_CONVERTER 10 | #define ENABLE_SINC_MEDIUM_CONVERTER 11 | #define ENABLE_SINC_FAST_CONVERTER 12 | 13 | #ifndef COMMON_H_INCLUDED 14 | #define COMMON_H_INCLUDED 15 | 16 | #include 17 | //#ifdef HAVE_STDBOOL_H 18 | #include 19 | //#endif 20 | 21 | #include 22 | 23 | #define SRC_MAX_RATIO 256 24 | #define SRC_MAX_RATIO_STR "256" 25 | 26 | #define SRC_MIN_RATIO_DIFF (1e-20) 27 | 28 | #ifndef MAX 29 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 30 | #endif 31 | 32 | #ifndef MIN 33 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 34 | #endif 35 | 36 | #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) 37 | #define OFFSETOF(type,member) ((int) (&((type*) 0)->member)) 38 | 39 | #define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20)) 40 | 41 | /* 42 | ** Inspiration : http://sourcefrog.net/weblog/software/languages/C/unused.html 43 | */ 44 | #ifdef UNUSED 45 | #elif defined (__GNUC__) 46 | # define UNUSED(x) UNUSED_ ## x __attribute__ ((unused)) 47 | #elif defined (__LCLINT__) 48 | # define UNUSED(x) /*@unused@*/ x 49 | #else 50 | # define UNUSED(x) x 51 | #endif 52 | 53 | #ifdef __GNUC__ 54 | # define WARN_UNUSED __attribute__ ((warn_unused_result)) 55 | #else 56 | # define WARN_UNUSED 57 | #endif 58 | 59 | #include "samplerate.h" 60 | 61 | enum 62 | { SRC_FALSE = 0, 63 | SRC_TRUE = 1, 64 | } ; 65 | 66 | enum SRC_MODE 67 | { 68 | SRC_MODE_PROCESS = 0, 69 | SRC_MODE_CALLBACK = 1 70 | } ; 71 | 72 | typedef enum SRC_ERROR 73 | { 74 | SRC_ERR_NO_ERROR = 0, 75 | 76 | SRC_ERR_MALLOC_FAILED, 77 | SRC_ERR_BAD_STATE, 78 | SRC_ERR_BAD_DATA, 79 | SRC_ERR_BAD_DATA_PTR, 80 | SRC_ERR_NO_PRIVATE, 81 | SRC_ERR_BAD_SRC_RATIO, 82 | SRC_ERR_BAD_PROC_PTR, 83 | SRC_ERR_SHIFT_BITS, 84 | SRC_ERR_FILTER_LEN, 85 | SRC_ERR_BAD_CONVERTER, 86 | SRC_ERR_BAD_CHANNEL_COUNT, 87 | SRC_ERR_SINC_BAD_BUFFER_LEN, 88 | SRC_ERR_SIZE_INCOMPATIBILITY, 89 | SRC_ERR_BAD_PRIV_PTR, 90 | SRC_ERR_BAD_SINC_STATE, 91 | SRC_ERR_DATA_OVERLAP, 92 | SRC_ERR_BAD_CALLBACK, 93 | SRC_ERR_BAD_MODE, 94 | SRC_ERR_NULL_CALLBACK, 95 | SRC_ERR_NO_VARIABLE_RATIO, 96 | SRC_ERR_SINC_PREPARE_DATA_BAD_LEN, 97 | SRC_ERR_BAD_INTERNAL_STATE, 98 | 99 | /* This must be the last error number. */ 100 | SRC_ERR_MAX_ERROR 101 | } SRC_ERROR ; 102 | 103 | typedef struct SRC_STATE_VT_tag 104 | { 105 | /* Varispeed process function. */ 106 | SRC_ERROR (*vari_process) (SRC_STATE *state, SRC_DATA *data) ; 107 | 108 | /* Constant speed process function. */ 109 | SRC_ERROR (*const_process) (SRC_STATE *state, SRC_DATA *data) ; 110 | 111 | /* State reset. */ 112 | void (*reset) (SRC_STATE *state) ; 113 | 114 | /* State clone. */ 115 | SRC_STATE *(*copy) (SRC_STATE *state) ; 116 | 117 | /* State close. */ 118 | void (*close) (SRC_STATE *state) ; 119 | } SRC_STATE_VT ; 120 | 121 | struct SRC_STATE_tag 122 | { 123 | SRC_STATE_VT *vt ; 124 | 125 | double last_ratio, last_position ; 126 | 127 | SRC_ERROR error ; 128 | int channels ; 129 | 130 | /* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */ 131 | enum SRC_MODE mode ; 132 | 133 | /* Data specific to SRC_MODE_CALLBACK. */ 134 | src_callback_t callback_func ; 135 | void *user_callback_data ; 136 | long saved_frames ; 137 | const float *saved_data ; 138 | 139 | /* Pointer to data to converter specific data. */ 140 | void *private_data ; 141 | } ; 142 | 143 | /* In src_sinc.c */ 144 | const char* sinc_get_name (int src_enum) ; 145 | const char* sinc_get_description (int src_enum) ; 146 | 147 | SRC_STATE *sinc_state_new (int converter_type, int channels, SRC_ERROR *error) ; 148 | 149 | /* In src_linear.c */ 150 | const char* linear_get_name (int src_enum) ; 151 | const char* linear_get_description (int src_enum) ; 152 | 153 | SRC_STATE *linear_state_new (int channels, SRC_ERROR *error) ; 154 | 155 | /* In src_zoh.c */ 156 | const char* zoh_get_name (int src_enum) ; 157 | const char* zoh_get_description (int src_enum) ; 158 | 159 | SRC_STATE *zoh_state_new (int channels, SRC_ERROR *error) ; 160 | 161 | /*---------------------------------------------------------- 162 | ** Common static inline functions. 163 | */ 164 | 165 | static inline double 166 | fmod_one (double x) 167 | { double res ; 168 | 169 | res = x - lrint (x) ; 170 | if (res < 0.0) 171 | return res + 1.0 ; 172 | 173 | return res ; 174 | } /* fmod_one */ 175 | 176 | static inline int 177 | is_bad_src_ratio (double ratio) 178 | { return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ; 179 | } /* is_bad_src_ratio */ 180 | 181 | 182 | #endif /* COMMON_H_INCLUDED */ 183 | 184 | -------------------------------------------------------------------------------- /external/libsamplerate/samplerate.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "samplerate.h" 19 | #include "common.h" 20 | 21 | static SRC_STATE *psrc_set_converter (int converter_type, int channels, int *error) ; 22 | 23 | 24 | SRC_STATE * 25 | src_new (int converter_type, int channels, int *error) 26 | { 27 | return psrc_set_converter (converter_type, channels, error) ; 28 | } /* src_new */ 29 | 30 | SRC_STATE* 31 | src_clone (SRC_STATE* orig, int *error) 32 | { 33 | if (!orig) 34 | { 35 | if (error) 36 | *error = SRC_ERR_BAD_STATE ; 37 | return NULL ; 38 | } 39 | if (error) 40 | *error = SRC_ERR_NO_ERROR ; 41 | 42 | SRC_STATE *state = orig->vt->copy (orig) ; 43 | if (!state) 44 | if (error) 45 | *error = SRC_ERR_MALLOC_FAILED ; 46 | 47 | return state ; 48 | } 49 | 50 | SRC_STATE* 51 | src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data) 52 | { SRC_STATE *state ; 53 | 54 | if (func == NULL) 55 | { if (error) 56 | *error = SRC_ERR_BAD_CALLBACK ; 57 | return NULL ; 58 | } ; 59 | 60 | if (error != NULL) 61 | *error = 0 ; 62 | 63 | if ((state = src_new (converter_type, channels, error)) == NULL) 64 | return NULL ; 65 | 66 | src_reset (state) ; 67 | 68 | state->mode = SRC_MODE_CALLBACK ; 69 | state->callback_func = func ; 70 | state->user_callback_data = cb_data ; 71 | 72 | return state ; 73 | } /* src_callback_new */ 74 | 75 | SRC_STATE * 76 | src_delete (SRC_STATE *state) 77 | { 78 | if (state) 79 | state->vt->close (state) ; 80 | 81 | return NULL ; 82 | } /* src_state */ 83 | 84 | int 85 | src_process (SRC_STATE *state, SRC_DATA *data) 86 | { 87 | int error ; 88 | 89 | if (state == NULL) 90 | return SRC_ERR_BAD_STATE ; 91 | 92 | if (state->mode != SRC_MODE_PROCESS) 93 | return SRC_ERR_BAD_MODE ; 94 | 95 | /* Check for valid SRC_DATA first. */ 96 | if (data == NULL) 97 | return SRC_ERR_BAD_DATA ; 98 | 99 | /* And that data_in and data_out are valid. */ 100 | if ((data->data_in == NULL && data->input_frames > 0) 101 | || (data->data_out == NULL && data->output_frames > 0)) 102 | return SRC_ERR_BAD_DATA_PTR ; 103 | 104 | /* Check src_ratio is in range. */ 105 | if (is_bad_src_ratio (data->src_ratio)) 106 | return SRC_ERR_BAD_SRC_RATIO ; 107 | 108 | if (data->input_frames < 0) 109 | data->input_frames = 0 ; 110 | if (data->output_frames < 0) 111 | data->output_frames = 0 ; 112 | 113 | if (data->data_in < data->data_out) 114 | { if (data->data_in + data->input_frames * state->channels > data->data_out) 115 | { /*-printf ("\n\ndata_in: %p data_out: %p\n", 116 | (void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/ 117 | return SRC_ERR_DATA_OVERLAP ; 118 | } ; 119 | } 120 | else if (data->data_out + data->output_frames * state->channels > data->data_in) 121 | { /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ; 122 | 123 | printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out, 124 | (void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/ 125 | return SRC_ERR_DATA_OVERLAP ; 126 | } ; 127 | 128 | /* Set the input and output counts to zero. */ 129 | data->input_frames_used = 0 ; 130 | data->output_frames_gen = 0 ; 131 | 132 | /* Special case for when last_ratio has not been set. */ 133 | if (state->last_ratio < (1.0 / SRC_MAX_RATIO)) 134 | state->last_ratio = data->src_ratio ; 135 | 136 | /* Now process. */ 137 | if (fabs (state->last_ratio - data->src_ratio) < 1e-15) 138 | error = state->vt->const_process (state, data) ; 139 | else 140 | error = state->vt->vari_process (state, data) ; 141 | 142 | return error ; 143 | } /* src_process */ 144 | 145 | long 146 | src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) 147 | { 148 | SRC_DATA src_data ; 149 | 150 | long output_frames_gen ; 151 | int error = 0 ; 152 | 153 | if (state == NULL) 154 | return 0 ; 155 | 156 | if (frames <= 0) 157 | return 0 ; 158 | 159 | if (state->mode != SRC_MODE_CALLBACK) 160 | { state->error = SRC_ERR_BAD_MODE ; 161 | return 0 ; 162 | } ; 163 | 164 | if (state->callback_func == NULL) 165 | { state->error = SRC_ERR_NULL_CALLBACK ; 166 | return 0 ; 167 | } ; 168 | 169 | memset (&src_data, 0, sizeof (src_data)) ; 170 | 171 | /* Check src_ratio is in range. */ 172 | if (is_bad_src_ratio (src_ratio)) 173 | { state->error = SRC_ERR_BAD_SRC_RATIO ; 174 | return 0 ; 175 | } ; 176 | 177 | /* Switch modes temporarily. */ 178 | src_data.src_ratio = src_ratio ; 179 | src_data.data_out = data ; 180 | src_data.output_frames = frames ; 181 | 182 | src_data.data_in = state->saved_data ; 183 | src_data.input_frames = state->saved_frames ; 184 | 185 | output_frames_gen = 0 ; 186 | while (output_frames_gen < frames) 187 | { /* Use a dummy array for the case where the callback function 188 | ** returns without setting the ptr. 189 | */ 190 | float dummy [1] ; 191 | 192 | if (src_data.input_frames == 0) 193 | { float *ptr = dummy ; 194 | 195 | src_data.input_frames = state->callback_func (state->user_callback_data, &ptr) ; 196 | src_data.data_in = ptr ; 197 | 198 | if (src_data.input_frames == 0) 199 | src_data.end_of_input = 1 ; 200 | } ; 201 | 202 | /* 203 | ** Now call process function. However, we need to set the mode 204 | ** to SRC_MODE_PROCESS first and when we return set it back to 205 | ** SRC_MODE_CALLBACK. 206 | */ 207 | state->mode = SRC_MODE_PROCESS ; 208 | error = src_process (state, &src_data) ; 209 | state->mode = SRC_MODE_CALLBACK ; 210 | 211 | if (error != 0) 212 | break ; 213 | 214 | src_data.data_in += src_data.input_frames_used * state->channels ; 215 | src_data.input_frames -= src_data.input_frames_used ; 216 | 217 | src_data.data_out += src_data.output_frames_gen * state->channels ; 218 | src_data.output_frames -= src_data.output_frames_gen ; 219 | 220 | output_frames_gen += src_data.output_frames_gen ; 221 | 222 | if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0) 223 | break ; 224 | } ; 225 | 226 | state->saved_data = src_data.data_in ; 227 | state->saved_frames = src_data.input_frames ; 228 | 229 | if (error != 0) 230 | { state->error = (SRC_ERROR) error ; 231 | return 0 ; 232 | } ; 233 | 234 | return output_frames_gen ; 235 | } /* src_callback_read */ 236 | 237 | /*========================================================================== 238 | */ 239 | 240 | int 241 | src_set_ratio (SRC_STATE *state, double new_ratio) 242 | { 243 | if (state == NULL) 244 | return SRC_ERR_BAD_STATE ; 245 | 246 | if (is_bad_src_ratio (new_ratio)) 247 | return SRC_ERR_BAD_SRC_RATIO ; 248 | 249 | state->last_ratio = new_ratio ; 250 | 251 | return SRC_ERR_NO_ERROR ; 252 | } /* src_set_ratio */ 253 | 254 | int 255 | src_get_channels (SRC_STATE *state) 256 | { 257 | if (state == NULL) 258 | return -SRC_ERR_BAD_STATE ; 259 | 260 | return state->channels ; 261 | } /* src_get_channels */ 262 | 263 | int 264 | src_reset (SRC_STATE *state) 265 | { 266 | if (state == NULL) 267 | return SRC_ERR_BAD_STATE ; 268 | 269 | state->vt->reset (state) ; 270 | 271 | state->last_position = 0.0 ; 272 | state->last_ratio = 0.0 ; 273 | 274 | state->saved_data = NULL ; 275 | state->saved_frames = 0 ; 276 | 277 | state->error = SRC_ERR_NO_ERROR ; 278 | 279 | return SRC_ERR_NO_ERROR ; 280 | } /* src_reset */ 281 | 282 | /*============================================================================== 283 | ** Control functions. 284 | */ 285 | 286 | const char * 287 | src_get_name (int converter_type) 288 | { const char *desc ; 289 | 290 | if ((desc = sinc_get_name (converter_type)) != NULL) 291 | return desc ; 292 | 293 | if ((desc = zoh_get_name (converter_type)) != NULL) 294 | return desc ; 295 | 296 | if ((desc = linear_get_name (converter_type)) != NULL) 297 | return desc ; 298 | 299 | return NULL ; 300 | } /* src_get_name */ 301 | 302 | const char * 303 | src_get_description (int converter_type) 304 | { const char *desc ; 305 | 306 | if ((desc = sinc_get_description (converter_type)) != NULL) 307 | return desc ; 308 | 309 | if ((desc = zoh_get_description (converter_type)) != NULL) 310 | return desc ; 311 | 312 | if ((desc = linear_get_description (converter_type)) != NULL) 313 | return desc ; 314 | 315 | return NULL ; 316 | } /* src_get_description */ 317 | 318 | const char * 319 | src_get_version (void) 320 | { return /*PACKAGE "-" VERSION*/ "libsamplerate - 0.2.1" " (c) 2002-2008 Erik de Castro Lopo" ; 321 | } /* src_get_version */ 322 | 323 | int 324 | src_is_valid_ratio (double ratio) 325 | { 326 | if (is_bad_src_ratio (ratio)) 327 | return SRC_FALSE ; 328 | 329 | return SRC_TRUE ; 330 | } /* src_is_valid_ratio */ 331 | 332 | /*============================================================================== 333 | ** Error reporting functions. 334 | */ 335 | 336 | int 337 | src_error (SRC_STATE *state) 338 | { if (state) 339 | return state->error ; 340 | return SRC_ERR_NO_ERROR ; 341 | } /* src_error */ 342 | 343 | const char* 344 | src_strerror (int error) 345 | { 346 | switch (error) 347 | { case SRC_ERR_NO_ERROR : 348 | return "No error." ; 349 | case SRC_ERR_MALLOC_FAILED : 350 | return "Malloc failed." ; 351 | case SRC_ERR_BAD_STATE : 352 | return "SRC_STATE pointer is NULL." ; 353 | case SRC_ERR_BAD_DATA : 354 | return "SRC_DATA pointer is NULL." ; 355 | case SRC_ERR_BAD_DATA_PTR : 356 | return "SRC_DATA->data_out or SRC_DATA->data_in is NULL." ; 357 | case SRC_ERR_NO_PRIVATE : 358 | return "Internal error. No private data." ; 359 | 360 | case SRC_ERR_BAD_SRC_RATIO : 361 | return "SRC ratio outside [1/" SRC_MAX_RATIO_STR ", " SRC_MAX_RATIO_STR "] range." ; 362 | 363 | case SRC_ERR_BAD_SINC_STATE : 364 | return "src_process() called without reset after end_of_input." ; 365 | case SRC_ERR_BAD_PROC_PTR : 366 | return "Internal error. No process pointer." ; 367 | case SRC_ERR_SHIFT_BITS : 368 | return "Internal error. SHIFT_BITS too large." ; 369 | case SRC_ERR_FILTER_LEN : 370 | return "Internal error. Filter length too large." ; 371 | case SRC_ERR_BAD_CONVERTER : 372 | return "Bad converter number." ; 373 | case SRC_ERR_BAD_CHANNEL_COUNT : 374 | return "Channel count must be >= 1." ; 375 | case SRC_ERR_SINC_BAD_BUFFER_LEN : 376 | return "Internal error. Bad buffer length. Please report this." ; 377 | case SRC_ERR_SIZE_INCOMPATIBILITY : 378 | return "Internal error. Input data / internal buffer size difference. Please report this." ; 379 | case SRC_ERR_BAD_PRIV_PTR : 380 | return "Internal error. Private pointer is NULL. Please report this." ; 381 | case SRC_ERR_DATA_OVERLAP : 382 | return "Input and output data arrays overlap." ; 383 | case SRC_ERR_BAD_CALLBACK : 384 | return "Supplied callback function pointer is NULL." ; 385 | case SRC_ERR_BAD_MODE : 386 | return "Calling mode differs from initialisation mode (ie process v callback)." ; 387 | case SRC_ERR_NULL_CALLBACK : 388 | return "Callback function pointer is NULL in src_callback_read ()." ; 389 | case SRC_ERR_NO_VARIABLE_RATIO : 390 | return "This converter only allows constant conversion ratios." ; 391 | case SRC_ERR_SINC_PREPARE_DATA_BAD_LEN : 392 | return "Internal error : Bad length in prepare_data ()." ; 393 | case SRC_ERR_BAD_INTERNAL_STATE : 394 | return "Error : Someone is trampling on my internal state." ; 395 | 396 | case SRC_ERR_MAX_ERROR : 397 | return "Placeholder. No error defined for this error number." ; 398 | 399 | default : break ; 400 | } 401 | 402 | return NULL ; 403 | } /* src_strerror */ 404 | 405 | /*============================================================================== 406 | ** Simple interface for performing a single conversion from input buffer to 407 | ** output buffer at a fixed conversion ratio. 408 | */ 409 | 410 | int 411 | src_simple (SRC_DATA *src_data, int converter, int channels) 412 | { SRC_STATE *src_state ; 413 | int error ; 414 | 415 | if ((src_state = src_new (converter, channels, &error)) == NULL) 416 | return error ; 417 | 418 | src_data->end_of_input = 1 ; /* Only one buffer worth of input. */ 419 | 420 | error = src_process (src_state, src_data) ; 421 | 422 | src_delete (src_state) ; 423 | 424 | return error ; 425 | } /* src_simple */ 426 | 427 | void 428 | src_short_to_float_array (const short *in, float *out, int len) 429 | { 430 | while (len) 431 | { len -- ; 432 | out [len] = (float) (in [len] / (1.0 * 0x8000)) ; 433 | } ; 434 | 435 | return ; 436 | } /* src_short_to_float_array */ 437 | 438 | void 439 | src_float_to_short_array (const float *in, short *out, int len) 440 | { 441 | while (len) 442 | { float scaled_value ; 443 | len -- ; 444 | scaled_value = in [len] * 32768.f ; 445 | if (scaled_value >= 32767.f) 446 | out [len] = 32767 ; 447 | else if (scaled_value <= -32768.f) 448 | out [len] = -32768 ; 449 | else 450 | out [len] = (short) (lrintf (scaled_value)) ; 451 | } 452 | } /* src_float_to_short_array */ 453 | 454 | void 455 | src_int_to_float_array (const int *in, float *out, int len) 456 | { 457 | while (len) 458 | { len -- ; 459 | out [len] = (float) (in [len] / (8.0 * 0x10000000)) ; 460 | } ; 461 | 462 | return ; 463 | } /* src_int_to_float_array */ 464 | 465 | void 466 | src_float_to_int_array (const float *in, int *out, int len) 467 | { double scaled_value ; 468 | 469 | while (len) 470 | { len -- ; 471 | 472 | scaled_value = in [len] * (8.0 * 0x10000000) ; 473 | #if CPU_CLIPS_POSITIVE == 0 474 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) 475 | { out [len] = 0x7fffffff ; 476 | continue ; 477 | } ; 478 | #endif 479 | #if CPU_CLIPS_NEGATIVE == 0 480 | if (scaled_value <= (-8.0 * 0x10000000)) 481 | { out [len] = -1 - 0x7fffffff ; 482 | continue ; 483 | } ; 484 | #endif 485 | out [len] = (int) lrint (scaled_value) ; 486 | } ; 487 | 488 | } /* src_float_to_int_array */ 489 | 490 | /*============================================================================== 491 | ** Private functions. 492 | */ 493 | 494 | static SRC_STATE * 495 | psrc_set_converter (int converter_type, int channels, int *error) 496 | { 497 | SRC_ERROR temp_error; 498 | SRC_STATE *state ; 499 | switch (converter_type) 500 | { 501 | #ifdef ENABLE_SINC_BEST_CONVERTER 502 | case SRC_SINC_BEST_QUALITY : 503 | state = sinc_state_new (converter_type, channels, &temp_error) ; 504 | break ; 505 | #endif 506 | #ifdef ENABLE_SINC_MEDIUM_CONVERTER 507 | case SRC_SINC_MEDIUM_QUALITY : 508 | state = sinc_state_new (converter_type, channels, &temp_error) ; 509 | break ; 510 | #endif 511 | #ifdef ENABLE_SINC_FAST_CONVERTER 512 | case SRC_SINC_FASTEST : 513 | state = sinc_state_new (converter_type, channels, &temp_error) ; 514 | break ; 515 | #endif 516 | case SRC_ZERO_ORDER_HOLD : 517 | state = zoh_state_new (channels, &temp_error) ; 518 | break ; 519 | case SRC_LINEAR : 520 | state = linear_state_new (channels, &temp_error) ; 521 | break ; 522 | default : 523 | temp_error = SRC_ERR_BAD_CONVERTER ; 524 | state = NULL ; 525 | break ; 526 | } 527 | 528 | if (error) 529 | *error = (int) temp_error ; 530 | 531 | return state ; 532 | } /* psrc_set_converter */ 533 | 534 | -------------------------------------------------------------------------------- /external/libsamplerate/samplerate.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | /* 10 | ** API documentation is available here: 11 | ** http://libsndfile.github.io/libsamplerate/api.html 12 | */ 13 | 14 | #ifndef SAMPLERATE_H 15 | #define SAMPLERATE_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif /* __cplusplus */ 20 | 21 | 22 | /* Opaque data type SRC_STATE. */ 23 | typedef struct SRC_STATE_tag SRC_STATE ; 24 | 25 | /* SRC_DATA is used to pass data to src_simple() and src_process(). */ 26 | typedef struct 27 | { const float *data_in ; 28 | float *data_out ; 29 | 30 | long input_frames, output_frames ; 31 | long input_frames_used, output_frames_gen ; 32 | 33 | int end_of_input ; 34 | 35 | double src_ratio ; 36 | } SRC_DATA ; 37 | 38 | /* 39 | ** User supplied callback function type for use with src_callback_new() 40 | ** and src_callback_read(). First parameter is the same pointer that was 41 | ** passed into src_callback_new(). Second parameter is pointer to a 42 | ** pointer. The user supplied callback function must modify *data to 43 | ** point to the start of the user supplied float array. The user supplied 44 | ** function must return the number of frames that **data points to. 45 | */ 46 | 47 | typedef long (*src_callback_t) (void *cb_data, float **data) ; 48 | 49 | /* 50 | ** Standard initialisation function : return an anonymous pointer to the 51 | ** internal state of the converter. Choose a converter from the enums below. 52 | ** Error returned in *error. 53 | */ 54 | 55 | SRC_STATE* src_new (int converter_type, int channels, int *error) ; 56 | 57 | /* 58 | ** Clone a handle : return an anonymous pointer to a new converter 59 | ** containing the same internal state as orig. Error returned in *error. 60 | */ 61 | SRC_STATE* src_clone (SRC_STATE* orig, int *error) ; 62 | 63 | /* 64 | ** Initilisation for callback based API : return an anonymous pointer to the 65 | ** internal state of the converter. Choose a converter from the enums below. 66 | ** The cb_data pointer can point to any data or be set to NULL. Whatever the 67 | ** value, when processing, user supplied function "func" gets called with 68 | ** cb_data as first parameter. 69 | */ 70 | 71 | SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels, 72 | int *error, void* cb_data) ; 73 | 74 | /* 75 | ** Cleanup all internal allocations. 76 | ** Always returns NULL. 77 | */ 78 | 79 | SRC_STATE* src_delete (SRC_STATE *state) ; 80 | 81 | /* 82 | ** Standard processing function. 83 | ** Returns non zero on error. 84 | */ 85 | 86 | int src_process (SRC_STATE *state, SRC_DATA *data) ; 87 | 88 | /* 89 | ** Callback based processing function. Read up to frames worth of data from 90 | ** the converter int *data and return frames read or -1 on error. 91 | */ 92 | long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ; 93 | 94 | /* 95 | ** Simple interface for performing a single conversion from input buffer to 96 | ** output buffer at a fixed conversion ratio. 97 | ** Simple interface does not require initialisation as it can only operate on 98 | ** a single buffer worth of audio. 99 | */ 100 | 101 | int src_simple (SRC_DATA *data, int converter_type, int channels) ; 102 | 103 | /* 104 | ** This library contains a number of different sample rate converters, 105 | ** numbered 0 through N. 106 | ** 107 | ** Return a string giving either a name or a more full description of each 108 | ** sample rate converter or NULL if no sample rate converter exists for 109 | ** the given value. The converters are sequentially numbered from 0 to N. 110 | */ 111 | 112 | const char *src_get_name (int converter_type) ; 113 | const char *src_get_description (int converter_type) ; 114 | const char *src_get_version (void) ; 115 | 116 | /* 117 | ** Set a new SRC ratio. This allows step responses 118 | ** in the conversion ratio. 119 | ** Returns non zero on error. 120 | */ 121 | 122 | int src_set_ratio (SRC_STATE *state, double new_ratio) ; 123 | 124 | /* 125 | ** Get the current channel count. 126 | ** Returns negative on error, positive channel count otherwise 127 | */ 128 | 129 | int src_get_channels (SRC_STATE *state) ; 130 | 131 | /* 132 | ** Reset the internal SRC state. 133 | ** Does not modify the quality settings. 134 | ** Does not free any memory allocations. 135 | ** Returns non zero on error. 136 | */ 137 | 138 | int src_reset (SRC_STATE *state) ; 139 | 140 | /* 141 | ** Return TRUE if ratio is a valid conversion ratio, FALSE 142 | ** otherwise. 143 | */ 144 | 145 | int src_is_valid_ratio (double ratio) ; 146 | 147 | /* 148 | ** Return an error number. 149 | */ 150 | 151 | int src_error (SRC_STATE *state) ; 152 | 153 | /* 154 | ** Convert the error number into a string. 155 | */ 156 | const char* src_strerror (int error) ; 157 | 158 | /* 159 | ** The following enums can be used to set the interpolator type 160 | ** using the function src_set_converter(). 161 | */ 162 | 163 | enum 164 | { 165 | SRC_SINC_BEST_QUALITY = 0, 166 | SRC_SINC_MEDIUM_QUALITY = 1, 167 | SRC_SINC_FASTEST = 2, 168 | SRC_ZERO_ORDER_HOLD = 3, 169 | SRC_LINEAR = 4, 170 | } ; 171 | 172 | /* 173 | ** Extra helper functions for converting from short to float and 174 | ** back again. 175 | */ 176 | 177 | void src_short_to_float_array (const short *in, float *out, int len) ; 178 | void src_float_to_short_array (const float *in, short *out, int len) ; 179 | 180 | void src_int_to_float_array (const int *in, float *out, int len) ; 181 | void src_float_to_int_array (const float *in, int *out, int len) ; 182 | 183 | 184 | #ifdef __cplusplus 185 | } /* extern "C" */ 186 | #endif /* __cplusplus */ 187 | 188 | #endif /* SAMPLERATE_H */ 189 | 190 | -------------------------------------------------------------------------------- /external/libsamplerate/src_linear.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "common.h" 20 | 21 | static SRC_ERROR linear_vari_process (SRC_STATE *state, SRC_DATA *data) ; 22 | static void linear_reset (SRC_STATE *state) ; 23 | static SRC_STATE *linear_copy (SRC_STATE *state) ; 24 | static void linear_close (SRC_STATE *state) ; 25 | 26 | /*======================================================================================== 27 | */ 28 | 29 | #define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r') 30 | 31 | #define SRC_DEBUG 0 32 | 33 | typedef struct 34 | { int linear_magic_marker ; 35 | bool dirty ; 36 | long in_count, in_used ; 37 | long out_count, out_gen ; 38 | float *last_value ; 39 | } LINEAR_DATA ; 40 | 41 | static SRC_STATE_VT linear_state_vt = 42 | { 43 | linear_vari_process, 44 | linear_vari_process, 45 | linear_reset, 46 | linear_copy, 47 | linear_close 48 | } ; 49 | 50 | /*---------------------------------------------------------------------------------------- 51 | */ 52 | 53 | static SRC_ERROR 54 | linear_vari_process (SRC_STATE *state, SRC_DATA *data) 55 | { LINEAR_DATA *priv ; 56 | double src_ratio, input_index, rem ; 57 | int ch ; 58 | 59 | if (data->input_frames <= 0) 60 | return SRC_ERR_NO_ERROR ; 61 | 62 | if (state->private_data == NULL) 63 | return SRC_ERR_NO_PRIVATE ; 64 | 65 | priv = (LINEAR_DATA*) state->private_data ; 66 | 67 | if (!priv->dirty) 68 | { /* If we have just been reset, set the last_value data. */ 69 | for (ch = 0 ; ch < state->channels ; ch++) 70 | priv->last_value [ch] = data->data_in [ch] ; 71 | priv->dirty = true ; 72 | } ; 73 | 74 | priv->in_count = data->input_frames * state->channels ; 75 | priv->out_count = data->output_frames * state->channels ; 76 | priv->in_used = priv->out_gen = 0 ; 77 | 78 | src_ratio = state->last_ratio ; 79 | 80 | if (is_bad_src_ratio (src_ratio)) 81 | return SRC_ERR_BAD_INTERNAL_STATE ; 82 | 83 | input_index = state->last_position ; 84 | 85 | /* Calculate samples before first sample in input array. */ 86 | while (input_index < 1.0 && priv->out_gen < priv->out_count) 87 | { 88 | if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count) 89 | break ; 90 | 91 | if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 92 | src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 93 | 94 | for (ch = 0 ; ch < state->channels ; ch++) 95 | { data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index * 96 | ((double) data->data_in [ch] - priv->last_value [ch])) ; 97 | priv->out_gen ++ ; 98 | } ; 99 | 100 | /* Figure out the next index. */ 101 | input_index += 1.0 / src_ratio ; 102 | } ; 103 | 104 | rem = fmod_one (input_index) ; 105 | priv->in_used += state->channels * lrint (input_index - rem) ; 106 | input_index = rem ; 107 | 108 | /* Main processing loop. */ 109 | while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count) 110 | { 111 | if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 112 | src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 113 | 114 | #if SRC_DEBUG 115 | if (priv->in_used < state->channels && input_index < 1.0) 116 | { printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, state->channels, input_index) ; 117 | exit (1) ; 118 | } ; 119 | #endif 120 | 121 | for (ch = 0 ; ch < state->channels ; ch++) 122 | { data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index * 123 | ((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ; 124 | priv->out_gen ++ ; 125 | } ; 126 | 127 | /* Figure out the next index. */ 128 | input_index += 1.0 / src_ratio ; 129 | rem = fmod_one (input_index) ; 130 | 131 | priv->in_used += state->channels * lrint (input_index - rem) ; 132 | input_index = rem ; 133 | } ; 134 | 135 | if (priv->in_used > priv->in_count) 136 | { input_index += (priv->in_used - priv->in_count) / state->channels ; 137 | priv->in_used = priv->in_count ; 138 | } ; 139 | 140 | state->last_position = input_index ; 141 | 142 | if (priv->in_used > 0) 143 | for (ch = 0 ; ch < state->channels ; ch++) 144 | priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ; 145 | 146 | /* Save current ratio rather then target ratio. */ 147 | state->last_ratio = src_ratio ; 148 | 149 | data->input_frames_used = priv->in_used / state->channels ; 150 | data->output_frames_gen = priv->out_gen / state->channels ; 151 | 152 | return SRC_ERR_NO_ERROR ; 153 | } /* linear_vari_process */ 154 | 155 | /*------------------------------------------------------------------------------ 156 | */ 157 | 158 | const char* 159 | linear_get_name (int src_enum) 160 | { 161 | if (src_enum == SRC_LINEAR) 162 | return "Linear Interpolator" ; 163 | 164 | return NULL ; 165 | } /* linear_get_name */ 166 | 167 | const char* 168 | linear_get_description (int src_enum) 169 | { 170 | if (src_enum == SRC_LINEAR) 171 | return "Linear interpolator, very fast, poor quality." ; 172 | 173 | return NULL ; 174 | } /* linear_get_descrition */ 175 | 176 | static LINEAR_DATA * 177 | linear_data_new (int channels) 178 | { 179 | assert (channels > 0) ; 180 | 181 | LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; 182 | if (priv) 183 | { 184 | priv->linear_magic_marker = LINEAR_MAGIC_MARKER ; 185 | priv->last_value = (float *) calloc (channels, sizeof (float)) ; 186 | if (!priv->last_value) 187 | { 188 | free (priv) ; 189 | priv = NULL ; 190 | } 191 | } 192 | 193 | return priv ; 194 | } 195 | 196 | SRC_STATE * 197 | linear_state_new (int channels, SRC_ERROR *error) 198 | { 199 | assert (channels > 0) ; 200 | assert (error != NULL) ; 201 | 202 | SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 203 | if (!state) 204 | { 205 | *error = SRC_ERR_MALLOC_FAILED ; 206 | return NULL ; 207 | } 208 | 209 | state->channels = channels ; 210 | state->mode = SRC_MODE_PROCESS ; 211 | 212 | state->private_data = linear_data_new (state->channels) ; 213 | if (!state->private_data) 214 | { 215 | free (state) ; 216 | *error = SRC_ERR_MALLOC_FAILED ; 217 | return NULL ; 218 | } 219 | 220 | state->vt = &linear_state_vt ; 221 | 222 | linear_reset (state) ; 223 | 224 | *error = SRC_ERR_NO_ERROR ; 225 | 226 | return state ; 227 | } 228 | 229 | /*=================================================================================== 230 | */ 231 | 232 | static void 233 | linear_reset (SRC_STATE *state) 234 | { LINEAR_DATA *priv = NULL ; 235 | 236 | priv = (LINEAR_DATA*) state->private_data ; 237 | if (priv == NULL) 238 | return ; 239 | 240 | priv->dirty = false ; 241 | memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ; 242 | 243 | return ; 244 | } /* linear_reset */ 245 | 246 | SRC_STATE * 247 | linear_copy (SRC_STATE *state) 248 | { 249 | assert (state != NULL) ; 250 | 251 | if (state->private_data == NULL) 252 | return NULL ; 253 | 254 | SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 255 | if (!state) 256 | return NULL ; 257 | memcpy (to, state, sizeof (SRC_STATE)) ; 258 | 259 | LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ; 260 | LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; 261 | if (!to_priv) 262 | { 263 | free (to) ; 264 | return NULL ; 265 | } 266 | 267 | memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ; 268 | to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ; 269 | if (!to_priv->last_value) 270 | { 271 | free (to) ; 272 | free (to_priv) ; 273 | return NULL ; 274 | } 275 | memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ; 276 | 277 | to->private_data = to_priv ; 278 | 279 | return to ; 280 | } /* linear_copy */ 281 | 282 | static void 283 | linear_close (SRC_STATE *state) 284 | { 285 | if (state) 286 | { 287 | LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ; 288 | if (linear) 289 | { 290 | if (linear->last_value) 291 | { 292 | free (linear->last_value) ; 293 | linear->last_value = NULL ; 294 | } 295 | free (linear) ; 296 | linear = NULL ; 297 | } 298 | free (state) ; 299 | state = NULL ; 300 | } 301 | } /* linear_close */ 302 | -------------------------------------------------------------------------------- /external/libsamplerate/src_sinc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "common.h" 20 | 21 | #define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ') 22 | 23 | /*======================================================================================== 24 | */ 25 | 26 | #define MAKE_INCREMENT_T(x) ((increment_t) (x)) 27 | 28 | #define SHIFT_BITS 12 29 | #define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS)) 30 | #define INV_FP_ONE (1.0 / FP_ONE) 31 | 32 | /* Customixe max channls from Kconfig. */ 33 | #ifndef CONFIG_CHAN_NR 34 | #define MAX_CHANNELS 128 35 | #else 36 | #define MAX_CHANNELS CONFIG_CHAN_NR 37 | #endif 38 | 39 | /*======================================================================================== 40 | */ 41 | 42 | typedef int32_t increment_t ; 43 | typedef float coeff_t ; 44 | typedef int _CHECK_SHIFT_BITS[2 * (SHIFT_BITS < sizeof (increment_t) * 8 - 1) - 1]; /* sanity check. */ 45 | 46 | #ifdef ENABLE_SINC_FAST_CONVERTER 47 | #include "fastest_coeffs.h" 48 | #endif 49 | #ifdef ENABLE_SINC_MEDIUM_CONVERTER 50 | #include "mid_qual_coeffs.h" 51 | #endif 52 | #ifdef ENABLE_SINC_BEST_CONVERTER 53 | #include "high_qual_coeffs.h" 54 | #endif 55 | 56 | typedef struct 57 | { int sinc_magic_marker ; 58 | 59 | long in_count, in_used ; 60 | long out_count, out_gen ; 61 | 62 | int coeff_half_len, index_inc ; 63 | 64 | double src_ratio, input_index ; 65 | 66 | coeff_t const *coeffs ; 67 | 68 | int b_current, b_end, b_real_end, b_len ; 69 | 70 | /* Sure hope noone does more than 128 channels at once. */ 71 | double left_calc [MAX_CHANNELS], right_calc [MAX_CHANNELS] ; 72 | 73 | float *buffer ; 74 | } SINC_FILTER ; 75 | 76 | static SRC_ERROR sinc_multichan_vari_process (SRC_STATE *state, SRC_DATA *data) ; 77 | static SRC_ERROR sinc_hex_vari_process (SRC_STATE *state, SRC_DATA *data) ; 78 | static SRC_ERROR sinc_quad_vari_process (SRC_STATE *state, SRC_DATA *data) ; 79 | static SRC_ERROR sinc_stereo_vari_process (SRC_STATE *state, SRC_DATA *data) ; 80 | static SRC_ERROR sinc_mono_vari_process (SRC_STATE *state, SRC_DATA *data) ; 81 | 82 | static SRC_ERROR prepare_data (SINC_FILTER *filter, int channels, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ; 83 | 84 | static void sinc_reset (SRC_STATE *state) ; 85 | static SRC_STATE *sinc_copy (SRC_STATE *state) ; 86 | static void sinc_close (SRC_STATE *state) ; 87 | 88 | static SRC_STATE_VT sinc_multichan_state_vt = 89 | { 90 | sinc_multichan_vari_process, 91 | sinc_multichan_vari_process, 92 | sinc_reset, 93 | sinc_copy, 94 | sinc_close 95 | } ; 96 | 97 | static SRC_STATE_VT sinc_hex_state_vt = 98 | { 99 | sinc_hex_vari_process, 100 | sinc_hex_vari_process, 101 | sinc_reset, 102 | sinc_copy, 103 | sinc_close 104 | } ; 105 | 106 | static SRC_STATE_VT sinc_quad_state_vt = 107 | { 108 | sinc_quad_vari_process, 109 | sinc_quad_vari_process, 110 | sinc_reset, 111 | sinc_copy, 112 | sinc_close 113 | } ; 114 | 115 | static SRC_STATE_VT sinc_stereo_state_vt = 116 | { 117 | sinc_stereo_vari_process, 118 | sinc_stereo_vari_process, 119 | sinc_reset, 120 | sinc_copy, 121 | sinc_close 122 | } ; 123 | 124 | static SRC_STATE_VT sinc_mono_state_vt = 125 | { 126 | sinc_mono_vari_process, 127 | sinc_mono_vari_process, 128 | sinc_reset, 129 | sinc_copy, 130 | sinc_close 131 | } ; 132 | 133 | static inline increment_t 134 | double_to_fp (double x) 135 | { return (increment_t) (lrint ((x) * FP_ONE)) ; 136 | } /* double_to_fp */ 137 | 138 | static inline increment_t 139 | int_to_fp (int x) 140 | { return (((increment_t) (x)) << SHIFT_BITS) ; 141 | } /* int_to_fp */ 142 | 143 | static inline int 144 | fp_to_int (increment_t x) 145 | { return (((x) >> SHIFT_BITS)) ; 146 | } /* fp_to_int */ 147 | 148 | static inline increment_t 149 | fp_fraction_part (increment_t x) 150 | { return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ; 151 | } /* fp_fraction_part */ 152 | 153 | static inline double 154 | fp_to_double (increment_t x) 155 | { return fp_fraction_part (x) * INV_FP_ONE ; 156 | } /* fp_to_double */ 157 | 158 | static inline int 159 | int_div_ceil (int divident, int divisor) /* == (int) ceil ((float) divident / divisor) */ 160 | { assert (divident >= 0 && divisor > 0) ; /* For positive numbers only */ 161 | return (divident + (divisor - 1)) / divisor ; 162 | } 163 | 164 | /*---------------------------------------------------------------------------------------- 165 | */ 166 | 167 | const char* 168 | sinc_get_name (int src_enum) 169 | { 170 | switch (src_enum) 171 | { case SRC_SINC_BEST_QUALITY : 172 | return "Best Sinc Interpolator" ; 173 | 174 | case SRC_SINC_MEDIUM_QUALITY : 175 | return "Medium Sinc Interpolator" ; 176 | 177 | case SRC_SINC_FASTEST : 178 | return "Fastest Sinc Interpolator" ; 179 | 180 | default: break ; 181 | } ; 182 | 183 | return NULL ; 184 | } /* sinc_get_descrition */ 185 | 186 | const char* 187 | sinc_get_description (int src_enum) 188 | { 189 | switch (src_enum) 190 | { case SRC_SINC_FASTEST : 191 | return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ; 192 | 193 | case SRC_SINC_MEDIUM_QUALITY : 194 | return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ; 195 | 196 | case SRC_SINC_BEST_QUALITY : 197 | return "Band limited sinc interpolation, best quality, 144dB SNR, 96% BW." ; 198 | 199 | default : 200 | break ; 201 | } ; 202 | 203 | return NULL ; 204 | } /* sinc_get_descrition */ 205 | 206 | static SINC_FILTER * 207 | sinc_filter_new (int converter_type, int channels) 208 | { 209 | assert (converter_type == SRC_SINC_FASTEST || 210 | converter_type == SRC_SINC_MEDIUM_QUALITY || 211 | converter_type == SRC_SINC_BEST_QUALITY) ; 212 | assert (channels > 0 && channels <= MAX_CHANNELS) ; 213 | 214 | SINC_FILTER *priv = (SINC_FILTER *) calloc (1, sizeof (SINC_FILTER)) ; 215 | if (priv) 216 | { 217 | priv->sinc_magic_marker = SINC_MAGIC_MARKER ; 218 | switch (converter_type) 219 | { 220 | #ifdef ENABLE_SINC_FAST_CONVERTER 221 | case SRC_SINC_FASTEST : 222 | priv->coeffs = fastest_coeffs.coeffs ; 223 | priv->coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 2 ; 224 | priv->index_inc = fastest_coeffs.increment ; 225 | break ; 226 | #endif 227 | #ifdef ENABLE_SINC_MEDIUM_CONVERTER 228 | case SRC_SINC_MEDIUM_QUALITY : 229 | priv->coeffs = slow_mid_qual_coeffs.coeffs ; 230 | priv->coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 2 ; 231 | priv->index_inc = slow_mid_qual_coeffs.increment ; 232 | break ; 233 | #endif 234 | #ifdef ENABLE_SINC_BEST_CONVERTER 235 | case SRC_SINC_BEST_QUALITY : 236 | priv->coeffs = slow_high_qual_coeffs.coeffs ; 237 | priv->coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 2 ; 238 | priv->index_inc = slow_high_qual_coeffs.increment ; 239 | break ; 240 | #endif 241 | } 242 | 243 | priv->b_len = 3 * (int) lrint ((priv->coeff_half_len + 2.0) / priv->index_inc * SRC_MAX_RATIO + 1) ; 244 | priv->b_len = MAX (priv->b_len, 4096) ; 245 | priv->b_len *= channels ; 246 | priv->b_len += 1 ; // There is a <= check against samples_in_hand requiring a buffer bigger than the calculation above 247 | 248 | 249 | priv->buffer = (float *) calloc (priv->b_len + channels, sizeof (float)) ; 250 | if (!priv->buffer) 251 | { 252 | free (priv) ; 253 | priv = NULL ; 254 | } 255 | } 256 | 257 | return priv ; 258 | } 259 | 260 | SRC_STATE * 261 | sinc_state_new (int converter_type, int channels, SRC_ERROR *error) 262 | { 263 | assert (converter_type == SRC_SINC_FASTEST || 264 | converter_type == SRC_SINC_MEDIUM_QUALITY || 265 | converter_type == SRC_SINC_BEST_QUALITY) ; 266 | assert (channels > 0) ; 267 | assert (error != NULL) ; 268 | 269 | if (channels > MAX_CHANNELS) 270 | { 271 | *error = SRC_ERR_BAD_CHANNEL_COUNT ; 272 | return NULL ; 273 | } 274 | 275 | SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 276 | if (!state) 277 | { 278 | *error = SRC_ERR_MALLOC_FAILED ; 279 | return NULL ; 280 | } 281 | 282 | state->channels = channels ; 283 | state->mode = SRC_MODE_PROCESS ; 284 | 285 | if (state->channels == 1) 286 | state->vt = &sinc_mono_state_vt ; 287 | else if (state->channels == 2) 288 | state->vt = &sinc_stereo_state_vt ; 289 | else if (state->channels == 4) 290 | state->vt = &sinc_quad_state_vt ; 291 | else if (state->channels == 6) 292 | state->vt = &sinc_hex_state_vt ; 293 | else 294 | state->vt = &sinc_multichan_state_vt ; 295 | 296 | state->private_data = sinc_filter_new (converter_type, state->channels) ; 297 | if (!state->private_data) 298 | { 299 | free (state) ; 300 | *error = SRC_ERR_MALLOC_FAILED ; 301 | return NULL ; 302 | } 303 | 304 | sinc_reset (state) ; 305 | 306 | *error = SRC_ERR_NO_ERROR ; 307 | 308 | return state ; 309 | } 310 | 311 | static void 312 | sinc_reset (SRC_STATE *state) 313 | { SINC_FILTER *filter ; 314 | 315 | filter = (SINC_FILTER*) state->private_data ; 316 | if (filter == NULL) 317 | return ; 318 | 319 | filter->b_current = filter->b_end = 0 ; 320 | filter->b_real_end = -1 ; 321 | 322 | filter->src_ratio = filter->input_index = 0.0 ; 323 | 324 | memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ; 325 | 326 | /* Set this for a sanity check */ 327 | memset (filter->buffer + filter->b_len, 0xAA, state->channels * sizeof (filter->buffer [0])) ; 328 | } /* sinc_reset */ 329 | 330 | static SRC_STATE * 331 | sinc_copy (SRC_STATE *state) 332 | { 333 | assert (state != NULL) ; 334 | 335 | if (state->private_data == NULL) 336 | return NULL ; 337 | 338 | SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 339 | if (!state) 340 | return NULL ; 341 | memcpy (to, state, sizeof (SRC_STATE)) ; 342 | 343 | 344 | SINC_FILTER* from_filter = (SINC_FILTER*) state->private_data ; 345 | SINC_FILTER *to_filter = (SINC_FILTER *) calloc (1, sizeof (SINC_FILTER)) ; 346 | if (!to_filter) 347 | { 348 | free (to) ; 349 | return NULL ; 350 | } 351 | memcpy (to_filter, from_filter, sizeof (SINC_FILTER)) ; 352 | to_filter->buffer = (float *) malloc (sizeof (float) * (from_filter->b_len + state->channels)) ; 353 | if (!to_filter->buffer) 354 | { 355 | free (to) ; 356 | free (to_filter) ; 357 | return NULL ; 358 | } 359 | memcpy (to_filter->buffer, from_filter->buffer, sizeof (float) * (from_filter->b_len + state->channels)) ; 360 | 361 | to->private_data = to_filter ; 362 | 363 | return to ; 364 | } /* sinc_copy */ 365 | 366 | /*======================================================================================== 367 | ** Beware all ye who dare pass this point. There be dragons here. 368 | */ 369 | 370 | static inline double 371 | calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index) 372 | { double fraction, left, right, icoeff ; 373 | increment_t filter_index, max_filter_index ; 374 | int data_index, coeff_count, indx ; 375 | 376 | /* Convert input parameters into fixed point. */ 377 | max_filter_index = int_to_fp (filter->coeff_half_len) ; 378 | 379 | /* First apply the left half of the filter. */ 380 | filter_index = start_filter_index ; 381 | coeff_count = (max_filter_index - filter_index) / increment ; 382 | filter_index = filter_index + coeff_count * increment ; 383 | data_index = filter->b_current - coeff_count ; 384 | 385 | if (data_index < 0) /* Avoid underflow access to filter->buffer. */ 386 | { int steps = -data_index ; 387 | /* If the assert triggers we would have to take care not to underflow/overflow */ 388 | assert (steps <= int_div_ceil (filter_index, increment)) ; 389 | filter_index -= increment * steps ; 390 | data_index += steps ; 391 | } 392 | left = 0.0 ; 393 | while (filter_index >= MAKE_INCREMENT_T (0)) 394 | { fraction = fp_to_double (filter_index) ; 395 | indx = fp_to_int (filter_index) ; 396 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 397 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 398 | assert (data_index >= 0 && data_index < filter->b_len) ; 399 | assert (data_index < filter->b_end) ; 400 | left += icoeff * filter->buffer [data_index] ; 401 | 402 | filter_index -= increment ; 403 | data_index = data_index + 1 ; 404 | } ; 405 | 406 | /* Now apply the right half of the filter. */ 407 | filter_index = increment - start_filter_index ; 408 | coeff_count = (max_filter_index - filter_index) / increment ; 409 | filter_index = filter_index + coeff_count * increment ; 410 | data_index = filter->b_current + 1 + coeff_count ; 411 | 412 | right = 0.0 ; 413 | do 414 | { fraction = fp_to_double (filter_index) ; 415 | indx = fp_to_int (filter_index) ; 416 | assert (indx < filter->coeff_half_len + 2) ; 417 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 418 | assert (data_index >= 0 && data_index < filter->b_len) ; 419 | assert (data_index < filter->b_end) ; 420 | right += icoeff * filter->buffer [data_index] ; 421 | 422 | filter_index -= increment ; 423 | data_index = data_index - 1 ; 424 | } 425 | while (filter_index > MAKE_INCREMENT_T (0)) ; 426 | 427 | return (left + right) ; 428 | } /* calc_output_single */ 429 | 430 | static SRC_ERROR 431 | sinc_mono_vari_process (SRC_STATE *state, SRC_DATA *data) 432 | { SINC_FILTER *filter ; 433 | double input_index, src_ratio, count, float_increment, terminate, rem ; 434 | increment_t increment, start_filter_index ; 435 | int half_filter_chan_len, samples_in_hand ; 436 | 437 | if (state->private_data == NULL) 438 | return SRC_ERR_NO_PRIVATE ; 439 | 440 | filter = (SINC_FILTER*) state->private_data ; 441 | 442 | /* If there is not a problem, this will be optimised out. */ 443 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) 444 | return SRC_ERR_SIZE_INCOMPATIBILITY ; 445 | 446 | filter->in_count = data->input_frames * state->channels ; 447 | filter->out_count = data->output_frames * state->channels ; 448 | filter->in_used = filter->out_gen = 0 ; 449 | 450 | src_ratio = state->last_ratio ; 451 | 452 | if (is_bad_src_ratio (src_ratio)) 453 | return SRC_ERR_BAD_INTERNAL_STATE ; 454 | 455 | /* Check the sample rate ratio wrt the buffer len. */ 456 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; 457 | if (MIN (state->last_ratio, data->src_ratio) < 1.0) 458 | count /= MIN (state->last_ratio, data->src_ratio) ; 459 | 460 | /* Maximum coefficientson either side of center point. */ 461 | half_filter_chan_len = state->channels * (int) (lrint (count) + 1) ; 462 | 463 | input_index = state->last_position ; 464 | 465 | rem = fmod_one (input_index) ; 466 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 467 | input_index = rem ; 468 | 469 | terminate = 1.0 / src_ratio + 1e-20 ; 470 | 471 | /* Main processing loop. */ 472 | while (filter->out_gen < filter->out_count) 473 | { 474 | /* Need to reload buffer? */ 475 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 476 | 477 | if (samples_in_hand <= half_filter_chan_len) 478 | { if ((state->error = prepare_data (filter, state->channels, data, half_filter_chan_len)) != 0) 479 | return state->error ; 480 | 481 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 482 | if (samples_in_hand <= half_filter_chan_len) 483 | break ; 484 | } ; 485 | 486 | /* This is the termination condition. */ 487 | if (filter->b_real_end >= 0) 488 | { if (filter->b_current + input_index + terminate > filter->b_real_end) 489 | break ; 490 | } ; 491 | 492 | if (filter->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > 1e-10) 493 | src_ratio = state->last_ratio + filter->out_gen * (data->src_ratio - state->last_ratio) / filter->out_count ; 494 | 495 | float_increment = filter->index_inc * (src_ratio < 1.0 ? src_ratio : 1.0) ; 496 | increment = double_to_fp (float_increment) ; 497 | 498 | start_filter_index = double_to_fp (input_index * float_increment) ; 499 | 500 | data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) * 501 | calc_output_single (filter, increment, start_filter_index)) ; 502 | filter->out_gen ++ ; 503 | 504 | /* Figure out the next index. */ 505 | input_index += 1.0 / src_ratio ; 506 | rem = fmod_one (input_index) ; 507 | 508 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 509 | input_index = rem ; 510 | } ; 511 | 512 | state->last_position = input_index ; 513 | 514 | /* Save current ratio rather then target ratio. */ 515 | state->last_ratio = src_ratio ; 516 | 517 | data->input_frames_used = filter->in_used / state->channels ; 518 | data->output_frames_gen = filter->out_gen / state->channels ; 519 | 520 | return SRC_ERR_NO_ERROR ; 521 | } /* sinc_mono_vari_process */ 522 | 523 | static inline void 524 | calc_output_stereo (SINC_FILTER *filter, int channels, increment_t increment, increment_t start_filter_index, double scale, float * output) 525 | { double fraction, left [2], right [2], icoeff ; 526 | increment_t filter_index, max_filter_index ; 527 | int data_index, coeff_count, indx ; 528 | 529 | /* Convert input parameters into fixed point. */ 530 | max_filter_index = int_to_fp (filter->coeff_half_len) ; 531 | 532 | /* First apply the left half of the filter. */ 533 | filter_index = start_filter_index ; 534 | coeff_count = (max_filter_index - filter_index) / increment ; 535 | filter_index = filter_index + coeff_count * increment ; 536 | data_index = filter->b_current - channels * coeff_count ; 537 | 538 | if (data_index < 0) /* Avoid underflow access to filter->buffer. */ 539 | { int steps = int_div_ceil (-data_index, 2) ; 540 | /* If the assert triggers we would have to take care not to underflow/overflow */ 541 | assert (steps <= int_div_ceil (filter_index, increment)) ; 542 | filter_index -= increment * steps ; 543 | data_index += steps * 2; 544 | } 545 | left [0] = left [1] = 0.0 ; 546 | while (filter_index >= MAKE_INCREMENT_T (0)) 547 | { fraction = fp_to_double (filter_index) ; 548 | indx = fp_to_int (filter_index) ; 549 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 550 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 551 | assert (data_index >= 0 && data_index + 1 < filter->b_len) ; 552 | assert (data_index + 1 < filter->b_end) ; 553 | for (int ch = 0; ch < 2; ch++) 554 | left [ch] += icoeff * filter->buffer [data_index + ch] ; 555 | 556 | filter_index -= increment ; 557 | data_index = data_index + 2 ; 558 | } ; 559 | 560 | /* Now apply the right half of the filter. */ 561 | filter_index = increment - start_filter_index ; 562 | coeff_count = (max_filter_index - filter_index) / increment ; 563 | filter_index = filter_index + coeff_count * increment ; 564 | data_index = filter->b_current + channels * (1 + coeff_count) ; 565 | 566 | right [0] = right [1] = 0.0 ; 567 | do 568 | { fraction = fp_to_double (filter_index) ; 569 | indx = fp_to_int (filter_index) ; 570 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 571 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 572 | assert (data_index >= 0 && data_index + 1 < filter->b_len) ; 573 | assert (data_index + 1 < filter->b_end) ; 574 | for (int ch = 0; ch < 2; ch++) 575 | right [ch] += icoeff * filter->buffer [data_index + ch] ; 576 | 577 | filter_index -= increment ; 578 | data_index = data_index - 2 ; 579 | } 580 | while (filter_index > MAKE_INCREMENT_T (0)) ; 581 | 582 | for (int ch = 0; ch < 2; ch++) 583 | output [ch] = (float) (scale * (left [ch] + right [ch])) ; 584 | } /* calc_output_stereo */ 585 | 586 | SRC_ERROR 587 | sinc_stereo_vari_process (SRC_STATE *state, SRC_DATA *data) 588 | { SINC_FILTER *filter ; 589 | double input_index, src_ratio, count, float_increment, terminate, rem ; 590 | increment_t increment, start_filter_index ; 591 | int half_filter_chan_len, samples_in_hand ; 592 | 593 | if (state->private_data == NULL) 594 | return SRC_ERR_NO_PRIVATE ; 595 | 596 | filter = (SINC_FILTER*) state->private_data ; 597 | 598 | /* If there is not a problem, this will be optimised out. */ 599 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) 600 | return SRC_ERR_SIZE_INCOMPATIBILITY ; 601 | 602 | filter->in_count = data->input_frames * state->channels ; 603 | filter->out_count = data->output_frames * state->channels ; 604 | filter->in_used = filter->out_gen = 0 ; 605 | 606 | src_ratio = state->last_ratio ; 607 | 608 | if (is_bad_src_ratio (src_ratio)) 609 | return SRC_ERR_BAD_INTERNAL_STATE ; 610 | 611 | /* Check the sample rate ratio wrt the buffer len. */ 612 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; 613 | if (MIN (state->last_ratio, data->src_ratio) < 1.0) 614 | count /= MIN (state->last_ratio, data->src_ratio) ; 615 | 616 | /* Maximum coefficientson either side of center point. */ 617 | half_filter_chan_len = state->channels * (int) (lrint (count) + 1) ; 618 | 619 | input_index = state->last_position ; 620 | 621 | rem = fmod_one (input_index) ; 622 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 623 | input_index = rem ; 624 | 625 | terminate = 1.0 / src_ratio + 1e-20 ; 626 | 627 | /* Main processing loop. */ 628 | while (filter->out_gen < filter->out_count) 629 | { 630 | /* Need to reload buffer? */ 631 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 632 | 633 | if (samples_in_hand <= half_filter_chan_len) 634 | { if ((state->error = prepare_data (filter, state->channels, data, half_filter_chan_len)) != 0) 635 | return state->error ; 636 | 637 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 638 | if (samples_in_hand <= half_filter_chan_len) 639 | break ; 640 | } ; 641 | 642 | /* This is the termination condition. */ 643 | if (filter->b_real_end >= 0) 644 | { if (filter->b_current + input_index + terminate >= filter->b_real_end) 645 | break ; 646 | } ; 647 | 648 | if (filter->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > 1e-10) 649 | src_ratio = state->last_ratio + filter->out_gen * (data->src_ratio - state->last_ratio) / filter->out_count ; 650 | 651 | float_increment = filter->index_inc * (src_ratio < 1.0 ? src_ratio : 1.0) ; 652 | increment = double_to_fp (float_increment) ; 653 | 654 | start_filter_index = double_to_fp (input_index * float_increment) ; 655 | 656 | calc_output_stereo (filter, state->channels, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ; 657 | filter->out_gen += 2 ; 658 | 659 | /* Figure out the next index. */ 660 | input_index += 1.0 / src_ratio ; 661 | rem = fmod_one (input_index) ; 662 | 663 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 664 | input_index = rem ; 665 | } ; 666 | 667 | state->last_position = input_index ; 668 | 669 | /* Save current ratio rather then target ratio. */ 670 | state->last_ratio = src_ratio ; 671 | 672 | data->input_frames_used = filter->in_used / state->channels ; 673 | data->output_frames_gen = filter->out_gen / state->channels ; 674 | 675 | return SRC_ERR_NO_ERROR ; 676 | } /* sinc_stereo_vari_process */ 677 | 678 | static inline void 679 | calc_output_quad (SINC_FILTER *filter, int channels, increment_t increment, increment_t start_filter_index, double scale, float * output) 680 | { double fraction, left [4], right [4], icoeff ; 681 | increment_t filter_index, max_filter_index ; 682 | int data_index, coeff_count, indx ; 683 | 684 | /* Convert input parameters into fixed point. */ 685 | max_filter_index = int_to_fp (filter->coeff_half_len) ; 686 | 687 | /* First apply the left half of the filter. */ 688 | filter_index = start_filter_index ; 689 | coeff_count = (max_filter_index - filter_index) / increment ; 690 | filter_index = filter_index + coeff_count * increment ; 691 | data_index = filter->b_current - channels * coeff_count ; 692 | 693 | if (data_index < 0) /* Avoid underflow access to filter->buffer. */ 694 | { int steps = int_div_ceil (-data_index, 4) ; 695 | /* If the assert triggers we would have to take care not to underflow/overflow */ 696 | assert (steps <= int_div_ceil (filter_index, increment)) ; 697 | filter_index -= increment * steps ; 698 | data_index += steps * 4; 699 | } 700 | left [0] = left [1] = left [2] = left [3] = 0.0 ; 701 | while (filter_index >= MAKE_INCREMENT_T (0)) 702 | { fraction = fp_to_double (filter_index) ; 703 | indx = fp_to_int (filter_index) ; 704 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 705 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 706 | assert (data_index >= 0 && data_index + 3 < filter->b_len) ; 707 | assert (data_index + 3 < filter->b_end) ; 708 | for (int ch = 0; ch < 4; ch++) 709 | left [ch] += icoeff * filter->buffer [data_index + ch] ; 710 | 711 | filter_index -= increment ; 712 | data_index = data_index + 4 ; 713 | } ; 714 | 715 | /* Now apply the right half of the filter. */ 716 | filter_index = increment - start_filter_index ; 717 | coeff_count = (max_filter_index - filter_index) / increment ; 718 | filter_index = filter_index + coeff_count * increment ; 719 | data_index = filter->b_current + channels * (1 + coeff_count) ; 720 | 721 | right [0] = right [1] = right [2] = right [3] = 0.0 ; 722 | do 723 | { fraction = fp_to_double (filter_index) ; 724 | indx = fp_to_int (filter_index) ; 725 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 726 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 727 | assert (data_index >= 0 && data_index + 3 < filter->b_len) ; 728 | assert (data_index + 3 < filter->b_end) ; 729 | for (int ch = 0; ch < 4; ch++) 730 | right [ch] += icoeff * filter->buffer [data_index + ch] ; 731 | 732 | 733 | filter_index -= increment ; 734 | data_index = data_index - 4 ; 735 | } 736 | while (filter_index > MAKE_INCREMENT_T (0)) ; 737 | 738 | for (int ch = 0; ch < 4; ch++) 739 | output [ch] = (float) (scale * (left [ch] + right [ch])) ; 740 | } /* calc_output_quad */ 741 | 742 | SRC_ERROR 743 | sinc_quad_vari_process (SRC_STATE *state, SRC_DATA *data) 744 | { SINC_FILTER *filter ; 745 | double input_index, src_ratio, count, float_increment, terminate, rem ; 746 | increment_t increment, start_filter_index ; 747 | int half_filter_chan_len, samples_in_hand ; 748 | 749 | if (state->private_data == NULL) 750 | return SRC_ERR_NO_PRIVATE ; 751 | 752 | filter = (SINC_FILTER*) state->private_data ; 753 | 754 | /* If there is not a problem, this will be optimised out. */ 755 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) 756 | return SRC_ERR_SIZE_INCOMPATIBILITY ; 757 | 758 | filter->in_count = data->input_frames * state->channels ; 759 | filter->out_count = data->output_frames * state->channels ; 760 | filter->in_used = filter->out_gen = 0 ; 761 | 762 | src_ratio = state->last_ratio ; 763 | 764 | if (is_bad_src_ratio (src_ratio)) 765 | return SRC_ERR_BAD_INTERNAL_STATE ; 766 | 767 | /* Check the sample rate ratio wrt the buffer len. */ 768 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; 769 | if (MIN (state->last_ratio, data->src_ratio) < 1.0) 770 | count /= MIN (state->last_ratio, data->src_ratio) ; 771 | 772 | /* Maximum coefficientson either side of center point. */ 773 | half_filter_chan_len = state->channels * (int) (lrint (count) + 1) ; 774 | 775 | input_index = state->last_position ; 776 | 777 | rem = fmod_one (input_index) ; 778 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 779 | input_index = rem ; 780 | 781 | terminate = 1.0 / src_ratio + 1e-20 ; 782 | 783 | /* Main processing loop. */ 784 | while (filter->out_gen < filter->out_count) 785 | { 786 | /* Need to reload buffer? */ 787 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 788 | 789 | if (samples_in_hand <= half_filter_chan_len) 790 | { if ((state->error = prepare_data (filter, state->channels, data, half_filter_chan_len)) != 0) 791 | return state->error ; 792 | 793 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 794 | if (samples_in_hand <= half_filter_chan_len) 795 | break ; 796 | } ; 797 | 798 | /* This is the termination condition. */ 799 | if (filter->b_real_end >= 0) 800 | { if (filter->b_current + input_index + terminate >= filter->b_real_end) 801 | break ; 802 | } ; 803 | 804 | if (filter->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > 1e-10) 805 | src_ratio = state->last_ratio + filter->out_gen * (data->src_ratio - state->last_ratio) / filter->out_count ; 806 | 807 | float_increment = filter->index_inc * (src_ratio < 1.0 ? src_ratio : 1.0) ; 808 | increment = double_to_fp (float_increment) ; 809 | 810 | start_filter_index = double_to_fp (input_index * float_increment) ; 811 | 812 | calc_output_quad (filter, state->channels, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ; 813 | filter->out_gen += 4 ; 814 | 815 | /* Figure out the next index. */ 816 | input_index += 1.0 / src_ratio ; 817 | rem = fmod_one (input_index) ; 818 | 819 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 820 | input_index = rem ; 821 | } ; 822 | 823 | state->last_position = input_index ; 824 | 825 | /* Save current ratio rather then target ratio. */ 826 | state->last_ratio = src_ratio ; 827 | 828 | data->input_frames_used = filter->in_used / state->channels ; 829 | data->output_frames_gen = filter->out_gen / state->channels ; 830 | 831 | return SRC_ERR_NO_ERROR ; 832 | } /* sinc_quad_vari_process */ 833 | 834 | static inline void 835 | calc_output_hex (SINC_FILTER *filter, int channels, increment_t increment, increment_t start_filter_index, double scale, float * output) 836 | { double fraction, left [6], right [6], icoeff ; 837 | increment_t filter_index, max_filter_index ; 838 | int data_index, coeff_count, indx ; 839 | 840 | /* Convert input parameters into fixed point. */ 841 | max_filter_index = int_to_fp (filter->coeff_half_len) ; 842 | 843 | /* First apply the left half of the filter. */ 844 | filter_index = start_filter_index ; 845 | coeff_count = (max_filter_index - filter_index) / increment ; 846 | filter_index = filter_index + coeff_count * increment ; 847 | data_index = filter->b_current - channels * coeff_count ; 848 | 849 | if (data_index < 0) /* Avoid underflow access to filter->buffer. */ 850 | { int steps = int_div_ceil (-data_index, 6) ; 851 | /* If the assert triggers we would have to take care not to underflow/overflow */ 852 | assert (steps <= int_div_ceil (filter_index, increment)) ; 853 | filter_index -= increment * steps ; 854 | data_index += steps * 6; 855 | } 856 | left [0] = left [1] = left [2] = left [3] = left [4] = left [5] = 0.0 ; 857 | while (filter_index >= MAKE_INCREMENT_T (0)) 858 | { fraction = fp_to_double (filter_index) ; 859 | indx = fp_to_int (filter_index) ; 860 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 861 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 862 | assert (data_index >= 0 && data_index + 5 < filter->b_len) ; 863 | assert (data_index + 5 < filter->b_end) ; 864 | for (int ch = 0; ch < 6; ch++) 865 | left [ch] += icoeff * filter->buffer [data_index + ch] ; 866 | 867 | filter_index -= increment ; 868 | data_index = data_index + 6 ; 869 | } ; 870 | 871 | /* Now apply the right half of the filter. */ 872 | filter_index = increment - start_filter_index ; 873 | coeff_count = (max_filter_index - filter_index) / increment ; 874 | filter_index = filter_index + coeff_count * increment ; 875 | data_index = filter->b_current + channels * (1 + coeff_count) ; 876 | 877 | right [0] = right [1] = right [2] = right [3] = right [4] = right [5] = 0.0 ; 878 | do 879 | { fraction = fp_to_double (filter_index) ; 880 | indx = fp_to_int (filter_index) ; 881 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 882 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 883 | assert (data_index >= 0 && data_index + 5 < filter->b_len) ; 884 | assert (data_index + 5 < filter->b_end) ; 885 | for (int ch = 0; ch < 6; ch++) 886 | right [ch] += icoeff * filter->buffer [data_index + ch] ; 887 | 888 | filter_index -= increment ; 889 | data_index = data_index - 6 ; 890 | } 891 | while (filter_index > MAKE_INCREMENT_T (0)) ; 892 | 893 | for (int ch = 0; ch < 6; ch++) 894 | output [ch] = (float) (scale * (left [ch] + right [ch])) ; 895 | } /* calc_output_hex */ 896 | 897 | SRC_ERROR 898 | sinc_hex_vari_process (SRC_STATE *state, SRC_DATA *data) 899 | { SINC_FILTER *filter ; 900 | double input_index, src_ratio, count, float_increment, terminate, rem ; 901 | increment_t increment, start_filter_index ; 902 | int half_filter_chan_len, samples_in_hand ; 903 | 904 | if (state->private_data == NULL) 905 | return SRC_ERR_NO_PRIVATE ; 906 | 907 | filter = (SINC_FILTER*) state->private_data ; 908 | 909 | /* If there is not a problem, this will be optimised out. */ 910 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) 911 | return SRC_ERR_SIZE_INCOMPATIBILITY ; 912 | 913 | filter->in_count = data->input_frames * state->channels ; 914 | filter->out_count = data->output_frames * state->channels ; 915 | filter->in_used = filter->out_gen = 0 ; 916 | 917 | src_ratio = state->last_ratio ; 918 | 919 | if (is_bad_src_ratio (src_ratio)) 920 | return SRC_ERR_BAD_INTERNAL_STATE ; 921 | 922 | /* Check the sample rate ratio wrt the buffer len. */ 923 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; 924 | if (MIN (state->last_ratio, data->src_ratio) < 1.0) 925 | count /= MIN (state->last_ratio, data->src_ratio) ; 926 | 927 | /* Maximum coefficientson either side of center point. */ 928 | half_filter_chan_len = state->channels * (int) (lrint (count) + 1) ; 929 | 930 | input_index = state->last_position ; 931 | 932 | rem = fmod_one (input_index) ; 933 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 934 | input_index = rem ; 935 | 936 | terminate = 1.0 / src_ratio + 1e-20 ; 937 | 938 | /* Main processing loop. */ 939 | while (filter->out_gen < filter->out_count) 940 | { 941 | /* Need to reload buffer? */ 942 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 943 | 944 | if (samples_in_hand <= half_filter_chan_len) 945 | { if ((state->error = prepare_data (filter, state->channels, data, half_filter_chan_len)) != 0) 946 | return state->error ; 947 | 948 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 949 | if (samples_in_hand <= half_filter_chan_len) 950 | break ; 951 | } ; 952 | 953 | /* This is the termination condition. */ 954 | if (filter->b_real_end >= 0) 955 | { if (filter->b_current + input_index + terminate >= filter->b_real_end) 956 | break ; 957 | } ; 958 | 959 | if (filter->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > 1e-10) 960 | src_ratio = state->last_ratio + filter->out_gen * (data->src_ratio - state->last_ratio) / filter->out_count ; 961 | 962 | float_increment = filter->index_inc * (src_ratio < 1.0 ? src_ratio : 1.0) ; 963 | increment = double_to_fp (float_increment) ; 964 | 965 | start_filter_index = double_to_fp (input_index * float_increment) ; 966 | 967 | calc_output_hex (filter, state->channels, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ; 968 | filter->out_gen += 6 ; 969 | 970 | /* Figure out the next index. */ 971 | input_index += 1.0 / src_ratio ; 972 | rem = fmod_one (input_index) ; 973 | 974 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 975 | input_index = rem ; 976 | } ; 977 | 978 | state->last_position = input_index ; 979 | 980 | /* Save current ratio rather then target ratio. */ 981 | state->last_ratio = src_ratio ; 982 | 983 | data->input_frames_used = filter->in_used / state->channels ; 984 | data->output_frames_gen = filter->out_gen / state->channels ; 985 | 986 | return SRC_ERR_NO_ERROR ; 987 | } /* sinc_hex_vari_process */ 988 | 989 | static inline void 990 | calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output) 991 | { double fraction, icoeff ; 992 | /* The following line is 1999 ISO Standard C. If your compiler complains, get a better compiler. */ 993 | double *left, *right ; 994 | increment_t filter_index, max_filter_index ; 995 | int data_index, coeff_count, indx ; 996 | 997 | left = filter->left_calc ; 998 | right = filter->right_calc ; 999 | 1000 | /* Convert input parameters into fixed point. */ 1001 | max_filter_index = int_to_fp (filter->coeff_half_len) ; 1002 | 1003 | /* First apply the left half of the filter. */ 1004 | filter_index = start_filter_index ; 1005 | coeff_count = (max_filter_index - filter_index) / increment ; 1006 | filter_index = filter_index + coeff_count * increment ; 1007 | data_index = filter->b_current - channels * coeff_count ; 1008 | 1009 | if (data_index < 0) /* Avoid underflow access to filter->buffer. */ 1010 | { int steps = int_div_ceil (-data_index, channels) ; 1011 | /* If the assert triggers we would have to take care not to underflow/overflow */ 1012 | assert (steps <= int_div_ceil (filter_index, increment)) ; 1013 | filter_index -= increment * steps ; 1014 | data_index += steps * channels ; 1015 | } 1016 | 1017 | memset (left, 0, sizeof (left [0]) * channels) ; 1018 | 1019 | while (filter_index >= MAKE_INCREMENT_T (0)) 1020 | { fraction = fp_to_double (filter_index) ; 1021 | indx = fp_to_int (filter_index) ; 1022 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 1023 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 1024 | 1025 | assert (data_index >= 0 && data_index + channels - 1 < filter->b_len) ; 1026 | assert (data_index + channels - 1 < filter->b_end) ; 1027 | for (int ch = 0; ch < channels; ch++) 1028 | left [ch] += icoeff * filter->buffer [data_index + ch] ; 1029 | 1030 | filter_index -= increment ; 1031 | data_index = data_index + channels ; 1032 | } ; 1033 | 1034 | /* Now apply the right half of the filter. */ 1035 | filter_index = increment - start_filter_index ; 1036 | coeff_count = (max_filter_index - filter_index) / increment ; 1037 | filter_index = filter_index + coeff_count * increment ; 1038 | data_index = filter->b_current + channels * (1 + coeff_count) ; 1039 | 1040 | memset (right, 0, sizeof (right [0]) * channels) ; 1041 | do 1042 | { fraction = fp_to_double (filter_index) ; 1043 | indx = fp_to_int (filter_index) ; 1044 | assert (indx >= 0 && indx + 1 < filter->coeff_half_len + 2) ; 1045 | icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ; 1046 | assert (data_index >= 0 && data_index + channels - 1 < filter->b_len) ; 1047 | assert (data_index + channels - 1 < filter->b_end) ; 1048 | for (int ch = 0; ch < channels; ch++) 1049 | right [ch] += icoeff * filter->buffer [data_index + ch] ; 1050 | 1051 | filter_index -= increment ; 1052 | data_index = data_index - channels ; 1053 | } 1054 | while (filter_index > MAKE_INCREMENT_T (0)) ; 1055 | 1056 | for(int ch = 0; ch < channels; ch++) 1057 | output [ch] = (float) (scale * (left [ch] + right [ch])) ; 1058 | 1059 | return ; 1060 | } /* calc_output_multi */ 1061 | 1062 | static SRC_ERROR 1063 | sinc_multichan_vari_process (SRC_STATE *state, SRC_DATA *data) 1064 | { SINC_FILTER *filter ; 1065 | double input_index, src_ratio, count, float_increment, terminate, rem ; 1066 | increment_t increment, start_filter_index ; 1067 | int half_filter_chan_len, samples_in_hand ; 1068 | 1069 | if (state->private_data == NULL) 1070 | return SRC_ERR_NO_PRIVATE ; 1071 | 1072 | filter = (SINC_FILTER*) state->private_data ; 1073 | 1074 | /* If there is not a problem, this will be optimised out. */ 1075 | if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0])) 1076 | return SRC_ERR_SIZE_INCOMPATIBILITY ; 1077 | 1078 | filter->in_count = data->input_frames * state->channels ; 1079 | filter->out_count = data->output_frames * state->channels ; 1080 | filter->in_used = filter->out_gen = 0 ; 1081 | 1082 | src_ratio = state->last_ratio ; 1083 | 1084 | if (is_bad_src_ratio (src_ratio)) 1085 | return SRC_ERR_BAD_INTERNAL_STATE ; 1086 | 1087 | /* Check the sample rate ratio wrt the buffer len. */ 1088 | count = (filter->coeff_half_len + 2.0) / filter->index_inc ; 1089 | if (MIN (state->last_ratio, data->src_ratio) < 1.0) 1090 | count /= MIN (state->last_ratio, data->src_ratio) ; 1091 | 1092 | /* Maximum coefficientson either side of center point. */ 1093 | half_filter_chan_len = state->channels * (int) (lrint (count) + 1) ; 1094 | 1095 | input_index = state->last_position ; 1096 | 1097 | rem = fmod_one (input_index) ; 1098 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 1099 | input_index = rem ; 1100 | 1101 | terminate = 1.0 / src_ratio + 1e-20 ; 1102 | 1103 | /* Main processing loop. */ 1104 | while (filter->out_gen < filter->out_count) 1105 | { 1106 | /* Need to reload buffer? */ 1107 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 1108 | 1109 | if (samples_in_hand <= half_filter_chan_len) 1110 | { if ((state->error = prepare_data (filter, state->channels, data, half_filter_chan_len)) != 0) 1111 | return state->error ; 1112 | 1113 | samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; 1114 | if (samples_in_hand <= half_filter_chan_len) 1115 | break ; 1116 | } ; 1117 | 1118 | /* This is the termination condition. */ 1119 | if (filter->b_real_end >= 0) 1120 | { if (filter->b_current + input_index + terminate >= filter->b_real_end) 1121 | break ; 1122 | } ; 1123 | 1124 | if (filter->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > 1e-10) 1125 | src_ratio = state->last_ratio + filter->out_gen * (data->src_ratio - state->last_ratio) / filter->out_count ; 1126 | 1127 | float_increment = filter->index_inc * (src_ratio < 1.0 ? src_ratio : 1.0) ; 1128 | increment = double_to_fp (float_increment) ; 1129 | 1130 | start_filter_index = double_to_fp (input_index * float_increment) ; 1131 | 1132 | calc_output_multi (filter, increment, start_filter_index, state->channels, float_increment / filter->index_inc, data->data_out + filter->out_gen) ; 1133 | filter->out_gen += state->channels ; 1134 | 1135 | /* Figure out the next index. */ 1136 | input_index += 1.0 / src_ratio ; 1137 | rem = fmod_one (input_index) ; 1138 | 1139 | filter->b_current = (filter->b_current + state->channels * lrint (input_index - rem)) % filter->b_len ; 1140 | input_index = rem ; 1141 | } ; 1142 | 1143 | state->last_position = input_index ; 1144 | 1145 | /* Save current ratio rather then target ratio. */ 1146 | state->last_ratio = src_ratio ; 1147 | 1148 | data->input_frames_used = filter->in_used / state->channels ; 1149 | data->output_frames_gen = filter->out_gen / state->channels ; 1150 | 1151 | return SRC_ERR_NO_ERROR ; 1152 | } /* sinc_multichan_vari_process */ 1153 | 1154 | /*---------------------------------------------------------------------------------------- 1155 | */ 1156 | 1157 | static SRC_ERROR 1158 | prepare_data (SINC_FILTER *filter, int channels, SRC_DATA *data, int half_filter_chan_len) 1159 | { int len = 0 ; 1160 | 1161 | if (filter->b_real_end >= 0) 1162 | return SRC_ERR_NO_ERROR ; /* Should be terminating. Just return. */ 1163 | 1164 | if (data->data_in == NULL) 1165 | return SRC_ERR_NO_ERROR ; 1166 | 1167 | if (filter->b_current == 0) 1168 | { /* Initial state. Set up zeros at the start of the buffer and 1169 | ** then load new data after that. 1170 | */ 1171 | len = filter->b_len - 2 * half_filter_chan_len ; 1172 | 1173 | filter->b_current = filter->b_end = half_filter_chan_len ; 1174 | } 1175 | else if (filter->b_end + half_filter_chan_len + channels < filter->b_len) 1176 | { /* Load data at current end position. */ 1177 | len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ; 1178 | } 1179 | else 1180 | { /* Move data at end of buffer back to the start of the buffer. */ 1181 | len = filter->b_end - filter->b_current ; 1182 | memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len, 1183 | (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ; 1184 | 1185 | filter->b_current = half_filter_chan_len ; 1186 | filter->b_end = filter->b_current + len ; 1187 | 1188 | /* Now load data at current end of buffer. */ 1189 | len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ; 1190 | } ; 1191 | 1192 | len = MIN ((int) (filter->in_count - filter->in_used), len) ; 1193 | len -= (len % channels) ; 1194 | 1195 | if (len < 0 || filter->b_end + len > filter->b_len) 1196 | return SRC_ERR_SINC_PREPARE_DATA_BAD_LEN ; 1197 | 1198 | memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used, 1199 | len * sizeof (filter->buffer [0])) ; 1200 | 1201 | filter->b_end += len ; 1202 | filter->in_used += len ; 1203 | 1204 | if (filter->in_used == filter->in_count && 1205 | filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input) 1206 | { /* Handle the case where all data in the current buffer has been 1207 | ** consumed and this is the last buffer. 1208 | */ 1209 | 1210 | if (filter->b_len - filter->b_end < half_filter_chan_len + 5) 1211 | { /* If necessary, move data down to the start of the buffer. */ 1212 | len = filter->b_end - filter->b_current ; 1213 | memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len, 1214 | (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ; 1215 | 1216 | filter->b_current = half_filter_chan_len ; 1217 | filter->b_end = filter->b_current + len ; 1218 | } ; 1219 | 1220 | filter->b_real_end = filter->b_end ; 1221 | len = half_filter_chan_len + 5 ; 1222 | 1223 | if (len < 0 || filter->b_end + len > filter->b_len) 1224 | len = filter->b_len - filter->b_end ; 1225 | 1226 | memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ; 1227 | filter->b_end += len ; 1228 | } ; 1229 | 1230 | return SRC_ERR_NO_ERROR ; 1231 | } /* prepare_data */ 1232 | 1233 | static void 1234 | sinc_close (SRC_STATE *state) 1235 | { 1236 | if (state) 1237 | { 1238 | SINC_FILTER *sinc = (SINC_FILTER *) state->private_data ; 1239 | if (sinc) 1240 | { 1241 | if (sinc->buffer) 1242 | { 1243 | free (sinc->buffer) ; 1244 | sinc->buffer = NULL ; 1245 | } 1246 | free (sinc) ; 1247 | sinc = NULL ; 1248 | } 1249 | free (state) ; 1250 | state = NULL ; 1251 | } 1252 | } /* sinc_close */ 1253 | -------------------------------------------------------------------------------- /external/libsamplerate/src_zoh.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo 3 | ** All rights reserved. 4 | ** 5 | ** This code is released under 2-clause BSD license. Please see the 6 | ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "common.h" 20 | 21 | static SRC_ERROR zoh_vari_process (SRC_STATE *state, SRC_DATA *data) ; 22 | static void zoh_reset (SRC_STATE *state) ; 23 | static SRC_STATE *zoh_copy (SRC_STATE *state) ; 24 | static void zoh_close (SRC_STATE *state) ; 25 | 26 | /*======================================================================================== 27 | */ 28 | 29 | #define ZOH_MAGIC_MARKER MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h') 30 | 31 | typedef struct 32 | { int zoh_magic_marker ; 33 | bool dirty ; 34 | long in_count, in_used ; 35 | long out_count, out_gen ; 36 | float *last_value ; 37 | } ZOH_DATA ; 38 | 39 | static SRC_STATE_VT zoh_state_vt = 40 | { 41 | zoh_vari_process, 42 | zoh_vari_process, 43 | zoh_reset, 44 | zoh_copy, 45 | zoh_close 46 | } ; 47 | 48 | /*---------------------------------------------------------------------------------------- 49 | */ 50 | 51 | static SRC_ERROR 52 | zoh_vari_process (SRC_STATE *state, SRC_DATA *data) 53 | { ZOH_DATA *priv ; 54 | double src_ratio, input_index, rem ; 55 | int ch ; 56 | 57 | if (data->input_frames <= 0) 58 | return SRC_ERR_NO_ERROR ; 59 | 60 | if (state->private_data == NULL) 61 | return SRC_ERR_NO_PRIVATE ; 62 | 63 | priv = (ZOH_DATA*) state->private_data ; 64 | 65 | if (!priv->dirty) 66 | { /* If we have just been reset, set the last_value data. */ 67 | for (ch = 0 ; ch < state->channels ; ch++) 68 | priv->last_value [ch] = data->data_in [ch] ; 69 | priv->dirty = true ; 70 | } ; 71 | 72 | priv->in_count = data->input_frames * state->channels ; 73 | priv->out_count = data->output_frames * state->channels ; 74 | priv->in_used = priv->out_gen = 0 ; 75 | 76 | src_ratio = state->last_ratio ; 77 | 78 | if (is_bad_src_ratio (src_ratio)) 79 | return SRC_ERR_BAD_INTERNAL_STATE ; 80 | 81 | input_index = state->last_position ; 82 | 83 | /* Calculate samples before first sample in input array. */ 84 | while (input_index < 1.0 && priv->out_gen < priv->out_count) 85 | { 86 | if (priv->in_used + state->channels * input_index >= priv->in_count) 87 | break ; 88 | 89 | if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 90 | src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 91 | 92 | for (ch = 0 ; ch < state->channels ; ch++) 93 | { data->data_out [priv->out_gen] = priv->last_value [ch] ; 94 | priv->out_gen ++ ; 95 | } ; 96 | 97 | /* Figure out the next index. */ 98 | input_index += 1.0 / src_ratio ; 99 | } ; 100 | 101 | rem = fmod_one (input_index) ; 102 | priv->in_used += state->channels * lrint (input_index - rem) ; 103 | input_index = rem ; 104 | 105 | /* Main processing loop. */ 106 | while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index <= priv->in_count) 107 | { 108 | if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 109 | src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 110 | 111 | for (ch = 0 ; ch < state->channels ; ch++) 112 | { data->data_out [priv->out_gen] = data->data_in [priv->in_used - state->channels + ch] ; 113 | priv->out_gen ++ ; 114 | } ; 115 | 116 | /* Figure out the next index. */ 117 | input_index += 1.0 / src_ratio ; 118 | rem = fmod_one (input_index) ; 119 | 120 | priv->in_used += state->channels * lrint (input_index - rem) ; 121 | input_index = rem ; 122 | } ; 123 | 124 | if (priv->in_used > priv->in_count) 125 | { input_index += (priv->in_used - priv->in_count) / state->channels ; 126 | priv->in_used = priv->in_count ; 127 | } ; 128 | 129 | state->last_position = input_index ; 130 | 131 | if (priv->in_used > 0) 132 | for (ch = 0 ; ch < state->channels ; ch++) 133 | priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ; 134 | 135 | /* Save current ratio rather then target ratio. */ 136 | state->last_ratio = src_ratio ; 137 | 138 | data->input_frames_used = priv->in_used / state->channels ; 139 | data->output_frames_gen = priv->out_gen / state->channels ; 140 | 141 | return SRC_ERR_NO_ERROR ; 142 | } /* zoh_vari_process */ 143 | 144 | /*------------------------------------------------------------------------------ 145 | */ 146 | 147 | const char* 148 | zoh_get_name (int src_enum) 149 | { 150 | if (src_enum == SRC_ZERO_ORDER_HOLD) 151 | return "ZOH Interpolator" ; 152 | 153 | return NULL ; 154 | } /* zoh_get_name */ 155 | 156 | const char* 157 | zoh_get_description (int src_enum) 158 | { 159 | if (src_enum == SRC_ZERO_ORDER_HOLD) 160 | return "Zero order hold interpolator, very fast, poor quality." ; 161 | 162 | return NULL ; 163 | } /* zoh_get_descrition */ 164 | 165 | static ZOH_DATA * 166 | zoh_data_new (int channels) 167 | { 168 | assert (channels > 0) ; 169 | 170 | ZOH_DATA *priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ; 171 | if (priv) 172 | { 173 | priv->zoh_magic_marker = ZOH_MAGIC_MARKER ; 174 | priv->last_value = (float *) calloc (channels, sizeof (float)) ; 175 | if (!priv->last_value) 176 | { 177 | free (priv) ; 178 | priv = NULL ; 179 | } 180 | } 181 | 182 | return priv ; 183 | } 184 | 185 | SRC_STATE * 186 | zoh_state_new (int channels, SRC_ERROR *error) 187 | { 188 | assert (channels > 0) ; 189 | assert (error != NULL) ; 190 | 191 | SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 192 | if (!state) 193 | { 194 | *error = SRC_ERR_MALLOC_FAILED ; 195 | return NULL ; 196 | } 197 | 198 | state->channels = channels ; 199 | state->mode = SRC_MODE_PROCESS ; 200 | 201 | state->private_data = zoh_data_new (state->channels) ; 202 | if (!state->private_data) 203 | { 204 | free (state) ; 205 | *error = SRC_ERR_MALLOC_FAILED ; 206 | return NULL ; 207 | } 208 | 209 | state->vt = &zoh_state_vt ; 210 | 211 | zoh_reset (state) ; 212 | 213 | *error = SRC_ERR_NO_ERROR ; 214 | 215 | return state ; 216 | } 217 | 218 | /*=================================================================================== 219 | */ 220 | 221 | static void 222 | zoh_reset (SRC_STATE *state) 223 | { ZOH_DATA *priv ; 224 | 225 | priv = (ZOH_DATA*) state->private_data ; 226 | if (priv == NULL) 227 | return ; 228 | 229 | priv->dirty = false ; 230 | memset (priv->last_value, 0, sizeof (float) * state->channels) ; 231 | 232 | return ; 233 | } /* zoh_reset */ 234 | 235 | static SRC_STATE * 236 | zoh_copy (SRC_STATE *state) 237 | { 238 | assert (state != NULL) ; 239 | 240 | if (state->private_data == NULL) 241 | return NULL ; 242 | 243 | SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 244 | if (!state) 245 | return NULL ; 246 | memcpy (to, state, sizeof (SRC_STATE)) ; 247 | 248 | ZOH_DATA* from_priv = (ZOH_DATA*) state->private_data ; 249 | ZOH_DATA *to_priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ; 250 | if (!to_priv) 251 | { 252 | free (to) ; 253 | return NULL ; 254 | } 255 | 256 | memcpy (to_priv, from_priv, sizeof (ZOH_DATA)) ; 257 | to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ; 258 | if (!to_priv->last_value) 259 | { 260 | free (to) ; 261 | free (to_priv) ; 262 | return NULL ; 263 | } 264 | memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ; 265 | 266 | to->private_data = to_priv ; 267 | 268 | return to ; 269 | } /* zoh_copy */ 270 | 271 | static void 272 | zoh_close (SRC_STATE *state) 273 | { 274 | if (state) 275 | { 276 | ZOH_DATA *zoh = (ZOH_DATA *) state->private_data ; 277 | if (zoh) 278 | { 279 | if (zoh->last_value) 280 | { 281 | free (zoh->last_value) ; 282 | zoh->last_value = NULL ; 283 | } 284 | free (zoh) ; 285 | zoh = NULL ; 286 | } 287 | free (state) ; 288 | state = NULL ; 289 | } 290 | } /* zoh_close */ 291 | -------------------------------------------------------------------------------- /lfac.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31402.337 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encoder", "encoder\encoder.vcxproj", "{1F1FEE25-F637-49C2-AFE5-3D811B13012B}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decoder", "decoder\decoder.vcxproj", "{A1CC2DC1-0035-42FA-8375-1178B4D57C12}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Debug|x64.ActiveCfg = Debug|x64 19 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Debug|x64.Build.0 = Debug|x64 20 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Debug|x86.ActiveCfg = Debug|Win32 21 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Debug|x86.Build.0 = Debug|Win32 22 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Release|x64.ActiveCfg = Release|x64 23 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Release|x64.Build.0 = Release|x64 24 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Release|x86.ActiveCfg = Release|Win32 25 | {1F1FEE25-F637-49C2-AFE5-3D811B13012B}.Release|x86.Build.0 = Release|Win32 26 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Debug|x64.ActiveCfg = Debug|x64 27 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Debug|x64.Build.0 = Debug|x64 28 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Debug|x86.ActiveCfg = Debug|Win32 29 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Debug|x86.Build.0 = Debug|Win32 30 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Release|x64.ActiveCfg = Release|x64 31 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Release|x64.Build.0 = Release|x64 32 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Release|x86.ActiveCfg = Release|Win32 33 | {A1CC2DC1-0035-42FA-8375-1178B4D57C12}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {AA128E6C-492A-40B0-BEE0-ADD6CD8D09A8} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /lfac.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 16.0 24 | Win32Proj 25 | {6d866b1a-b6ef-4f63-b564-1652fcf60704} 26 | lfac 27 | 10.0 28 | 29 | 30 | 31 | Application 32 | true 33 | v142 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v142 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v142 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | true 84 | 85 | 86 | false 87 | 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Console 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | 110 | 111 | Console 112 | true 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | 128 | 129 | 130 | 131 | Level3 132 | true 133 | true 134 | true 135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 136 | true 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # LFAC - Low-Fidelity Audio Codec 2 | 3 | Copyright 2021 Jari Komppa, http://iki.fi/sol 4 | Licensed under Unlicense. 5 | 6 | Not to be confused with FLAC. 7 | 8 | ## What is this? 9 | 10 | Do you have a 8 bit micro and want to fit some digital audio in it? 11 | 12 | Are you working on a toy and hate parents *so* much that you want to have even worse audio quality, and maybe save a few pennies? 13 | 14 | Are you looking for audio compression for 8 bit PCM samples? 15 | 16 | If you answered yes, look no further! LFAC promises pretty good compression ratios with unsurpassed audio quality*! 17 | 18 | *) as in, worse than you can find elsewhere. 19 | 20 | ## Honestly though... 21 | 22 | I was looking for some way to have really cheap audio compression for 8 bit PCM samples. The best I could find were (A)DPCM compression, implementations of which really targets 16 bit samples or higher, and the compression ratio isn't really great. 23 | 24 | Also, decompression of ADPCM isn't trivial on a 8 bit CPU. 25 | 26 | ## License 27 | 28 | LFAC, its source code and technology is licensed under Unlicense, meaning that it's practically public domain. 29 | 30 | The encoder includes third party libraries for sample format processing and resampling, and those libraries come with their own licenses. 31 | 32 | But really, if you do use this for anything, (especially that hardware use case), do let me know. 33 | 34 | If you get into trouble, you're on your own, though. 35 | 36 | ## Operation principle 37 | 38 | LFAC works by defining "grains" of audio to represent the original audio. (As in "granular synthesis", but with worse results). Since everything here is 8 bit, 256 grains are defined. The compressed format contains dictionary of grains and a list of indices to the dictionary. Thus, the compression ratio depends on the size of the grains and the size of the source data. 39 | 40 | For slightly better quality, especially if the source material is not uniform, a window can be defined after which new grains are defined - which practically means compressing every N samples separately. 41 | 42 | The compression ratio can be calculated as: 43 | 44 | outsize = (grainsize * 256) + (inputsize / grainsize) 45 | 46 | This means that for 64k samples and grain size of 4 samples, the compression ratio becomes: 47 | 48 | outsize = 4 * 256 + 65536 / 4 = 17408 49 | 50 | .. or 26.5625%. Increase the grain size or number of samples and the compression improves, but audio quality naturally also goes down. 51 | 52 | |source|gs = 2|gs = 4|gs = 8|gs = 16| 53 | |-:|-:|-:|-:|-:| 54 | |16384|8704|5120|4096|5120 55 | |32768|16896|9216|6144|6144 56 | |65536|33280|17408|10240|8192 57 | |131072|66048|33792|18432|12288 58 | |262144|131584|66560|34816|20480 59 | |524288|262656|132096|67584|36864 60 | |1048576|524800|263168|133120|69632 61 | 62 | As an extreme example, compressing an 1MB source with 16 sample grains compresses down to 6.64% (or 68kB). The result will sound rather horrible, but assuming the original sample rate to be 8000Hz, the size is equivalent to resampling the data down to 531Hz. 63 | 64 | Decompression becomes trivial; simply look up the grains from the dictionary based on the indices in the compressed data. Since everything is 8 bit, this can be done on slow 8 bit CPUs like the Zilog z80. Don't ask me how the sample is actually planed on a z80, though. 65 | 66 | ## Finding the grains 67 | 68 | To find the most promising grains, we define the audio as N-dimensional space where N is the number of samples in a grain. Then we start subdividing the space. Consider this 2d example: 69 | 70 | ![the splits](subdiv.png "subdivision example graph") 71 | 72 | After defining our space, we find the dimension by which we want to split the space, decide on some point and split it into two subspaces (by Y axis in this case). 73 | 74 | Next, we go through all our subspaces to find the subspace and dimension by which we want to split the subspace. In this case we split the red subspace by the X dimension. 75 | 76 | This process is continued until we reach the desired number of subspaces, i.e. the number of grains we wish to generate. 77 | 78 | Do note that the splits may occur by any dimension depending on the splitting rules and the input data. So it's possible that we get data where we only ever want to split by the X axis, for example. 79 | 80 | After the subspaces are defined, we average the values for each subspace to get our grains. The result works surprisingly well. 81 | 82 | And by surprisingly well, I mean I was totally surprised the result was somewhat recognizable and not just random noise. 83 | 84 | To improve the quality, it's easy to see that since we split the subspaces with linear cuts, the grains in the "corners" of our subspaces may actually be closer to another subspace's center. Moving them to the closest subspace actually does improve the audio quality audibly. 85 | 86 | This changes the average grain position for each dictionary index, so we recalculate the average. This in turn means that the closest average grain may change, so we reiterate the process until the system stabilizes or we reach a maximum number of iterations. 87 | 88 | Another trick is to rotate the samples in a grain so that the smallest sample always comes first. This reduces the average error, but also totally wrecks the audio quality, so it's a great idea, it just doesn't work. 89 | 90 | ## File format 91 | 92 | LFAC files have the extension .sad, and have the following format (all over 1 byte values are little endian, x86 style): 93 | 94 | |Offset|Size|Description| 95 | |-:|-:|:-| 96 | |0|4|Tag "LFAC"| 97 | |4|4|Version, currently 0| 98 | |8|4|Sample rate, in Hz| 99 | |12|4|Number of channels, 1 = mono| 100 | |16|4|Dimensions, or bytes per grain| 101 | |20|4|Window size in number of indices, or 0 for infinite| 102 | |24|4|Uncompressed data size in bytes| 103 | |28|4|Reserved| 104 | |32|256*N|Dictionary, N is number of bytes per grain| 105 | |*|*|Indices, up to "window" bytes 106 | |*|*|Dictionary for second window 107 | |*|*|Indices for second window 108 | |||etc| 109 | 110 | ## VQ 111 | 112 | It has been pointed out to me that what I have re-invented here is called vector quantization or VQ. The VQ described in wikipedia appears to differ primarily by finding the initial center point using multidimensional voronoi graph instead of the direct subdivision I'm using. 113 | 114 | And of course the terminology is different (dictionary / codebook, etc). 115 | -------------------------------------------------------------------------------- /src/decoder.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define DR_WAV_IMPLEMENTATION 7 | #include "../external/dr_wav.h" 8 | 9 | char outfilename[1024]; 10 | unsigned char* rawdata; 11 | int rawlen; 12 | unsigned char* outdata; 13 | 14 | void load_data(const char* fn) 15 | { 16 | FILE* f = fopen(fn, "rb"); 17 | if (!f) 18 | { 19 | printf("Can't open source file\n"); 20 | exit(0); 21 | } 22 | fseek(f, 0, SEEK_END); 23 | rawlen = ftell(f); 24 | fseek(f, 0, SEEK_SET); 25 | rawdata = new unsigned char[rawlen]; 26 | fread(rawdata, rawlen, 1, f); 27 | fclose(f); 28 | } 29 | 30 | int samplerate, channels, dimensions, window, datasize; 31 | 32 | void decode() 33 | { 34 | int* hd = (int*)rawdata; 35 | if (hd[0] != 'CAFL' || hd[1] != 0) 36 | { 37 | printf("Source data header not recognized. Aborting.\n"); 38 | exit(0); 39 | } 40 | 41 | samplerate = hd[2]; 42 | channels = hd[3]; 43 | dimensions = hd[4]; 44 | window = hd[5]; 45 | datasize = hd[6]; 46 | 47 | printf( 48 | "Samplerate: %d\n" 49 | "Channels: %d\n" 50 | "Dimensions: %d\n" 51 | "Window: %d\n" 52 | "Data size: %d\n", 53 | samplerate, channels, dimensions, window, datasize); 54 | 55 | unsigned char* dictionary = rawdata + 8 * sizeof(int); 56 | unsigned char* data = dictionary + dimensions * 256; 57 | 58 | outdata = new unsigned char[datasize]; 59 | 60 | unsigned char* out = outdata; 61 | int i = 0; 62 | int ws = window; 63 | int dataleft = datasize; 64 | while (dataleft > 0) 65 | { 66 | for (int j = 0; j < dimensions; j++) 67 | { 68 | *out = dictionary[data[i] * dimensions + j]; 69 | out++; 70 | dataleft--; 71 | } 72 | i++; 73 | ws--; 74 | if (ws == 0) 75 | { 76 | ws = window; 77 | dictionary = data + window; 78 | data = dictionary + dimensions * 256; 79 | i = 0; 80 | } 81 | } 82 | } 83 | 84 | void save_data() 85 | { 86 | drwav_data_format format; 87 | format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64. 88 | format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes. 89 | format.channels = channels; 90 | format.sampleRate = samplerate; 91 | format.bitsPerSample = 8; 92 | drwav wav; 93 | if (!drwav_init_file_write(&wav, outfilename, &format, NULL)) 94 | { 95 | printf("Unable to open output file\n"); 96 | exit(0); 97 | } 98 | drwav_write_pcm_frames(&wav, datasize / channels, outdata); 99 | drwav_uninit(&wav); 100 | } 101 | 102 | int main(int parc, char** pars) 103 | { 104 | printf("LFAC decoder by Jari Komppa 2021 http://iki.fi/sol\n"); 105 | if (parc < 2) 106 | { 107 | printf("Usage: %s infilename [outfilename]\n", pars[0]); 108 | return 0; 109 | } 110 | if (parc < 3) 111 | { 112 | sprintf(outfilename, "%s.wav", pars[1]); 113 | } 114 | else 115 | sprintf(outfilename, "%s", pars[2]); 116 | 117 | printf("Decoding %s to %s\n", pars[1], outfilename); 118 | 119 | load_data(pars[1]); 120 | 121 | decode(); 122 | save_data(); 123 | printf("Done.\n"); 124 | return 0; 125 | } -------------------------------------------------------------------------------- /src/encoder.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include // needed by optionparser 7 | #define DR_WAV_IMPLEMENTATION 8 | #include "../external/dr_wav.h" 9 | #define DR_MP3_IMPLEMENTATION 10 | #include "../external/dr_mp3.h" 11 | #define DR_FLAC_IMPLEMENTATION 12 | #include "../external/dr_flac.h" 13 | #include "../external/stb_vorbis.c" 14 | #include "../external/optionparser.h" 15 | #include "../external/libsamplerate/samplerate.h" 16 | 17 | #include "vq.hpp" 18 | 19 | #define MAX_DIMENSIONS 64 20 | #define MAX_GROUPS 256 21 | unsigned char* gChunkData; 22 | unsigned char* gOutData; 23 | unsigned char* gUnpackedData; 24 | unsigned int* gIndex; 25 | unsigned int gGroup[MAX_GROUPS]; 26 | unsigned int gGroupofs[MAX_GROUPS]; 27 | unsigned int gGroupCount = 1; 28 | unsigned int gAnalysis[MAX_GROUPS * MAX_DIMENSIONS]; 29 | unsigned int gChunks = 0; 30 | unsigned int gDimensions = 4; 31 | unsigned int gDatalen = 0; 32 | unsigned char gDictionary[MAX_GROUPS * MAX_DIMENSIONS]; 33 | int gWindowOffset = 0; 34 | int gWindowSize = 0; 35 | FILE* gOutFile; 36 | unsigned int gChannels; 37 | unsigned int gSampleRate; 38 | unsigned int gWindow; 39 | float* gSampleData = NULL; 40 | 41 | 42 | // It may seem a bit weird to store the data this way (as a linear 43 | // pass would work just as well), but this way we can do weird things 44 | // with chunks if we want to. 45 | void insert_chunk(unsigned char* p) 46 | { 47 | memcpy(gChunkData + gChunks * gDimensions, p, gDimensions); 48 | gChunks++; 49 | } 50 | 51 | void analyze_group(int g) 52 | { 53 | unsigned char* chunkdata = gChunkData + gWindowOffset; 54 | int minval[MAX_DIMENSIONS]; 55 | int maxval[MAX_DIMENSIONS]; 56 | for (unsigned int i = 0; i < gDimensions; i++) 57 | { 58 | int v = chunkdata[gIndex[gGroupofs[g]] * gDimensions + i]; 59 | minval[i] = v; 60 | maxval[i] = v; 61 | } 62 | for (unsigned int i = 0; i < gGroup[g]; i++) 63 | { 64 | for (unsigned int j = 0; j < gDimensions; j++) 65 | { 66 | int v = chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + j]; 67 | if (minval[j] > v) minval[j] = v; 68 | if (maxval[j] < v) maxval[j] = v; 69 | } 70 | } 71 | for (unsigned int i = 0; i < gDimensions; i++) 72 | gAnalysis[g * gDimensions + i] = maxval[i] - minval[i]; 73 | } 74 | 75 | int find_largest() 76 | { 77 | unsigned int v = 0, d = 0, gs = gGroup[0]; 78 | for (unsigned int i = 0; i < gDimensions * gGroupCount; i++) 79 | { 80 | if (gAnalysis[i] > v) 81 | { 82 | d = i; 83 | v = gAnalysis[i]; 84 | gs = gGroup[i / gDimensions]; 85 | } else 86 | if (gAnalysis[i] == v && gs < gGroup[i/gDimensions]) 87 | { 88 | d = i; 89 | v = gAnalysis[i]; 90 | gs = gGroup[i / gDimensions]; 91 | } 92 | 93 | } 94 | return d; 95 | } 96 | 97 | int gSortDimension = 0; 98 | 99 | int cmpfunc(const void* a, const void* b) 100 | { 101 | unsigned char* chunkdata = gChunkData + gWindowOffset; 102 | int av = *(int*)a; 103 | int bv = *(int*)b; 104 | return (int)chunkdata[av * gDimensions + gSortDimension] - 105 | (int)chunkdata[bv * gDimensions + gSortDimension]; 106 | } 107 | 108 | void sort_group(int g, int d) 109 | { 110 | gSortDimension = d; 111 | qsort(gIndex + gGroupofs[g], gGroup[g], sizeof(int), cmpfunc); 112 | } 113 | 114 | void load_data(const char* fn) 115 | { 116 | // Let's assume wav. 117 | drwav_uint64 totalPCMFrameCount; 118 | gSampleData = drwav_open_file_and_read_pcm_frames_f32(fn, &gChannels, &gSampleRate, &totalPCMFrameCount, NULL); 119 | 120 | if (!gSampleData) 121 | { 122 | // not a wav, what about mp3? 123 | drmp3_config conf; 124 | gSampleData = drmp3_open_file_and_read_pcm_frames_f32(fn, &conf, &totalPCMFrameCount, NULL); 125 | if (gSampleData) 126 | { 127 | gSampleRate = conf.sampleRate; 128 | gChannels = conf.channels; 129 | } 130 | } 131 | 132 | if (!gSampleData) 133 | { 134 | // flac, maybe? 135 | gSampleData = drflac_open_file_and_read_pcm_frames_f32(fn, &gChannels, &gSampleRate, &totalPCMFrameCount, NULL); 136 | } 137 | 138 | if (!gSampleData) 139 | { 140 | // it must be an ogg then. 141 | short* output; 142 | int frames = stb_vorbis_decode_filename(fn, (int*)&gChannels, (int*)&gSampleRate, &output); 143 | if (frames > 0) 144 | { 145 | gDatalen = frames * gChannels; 146 | gSampleData = new float[gDatalen]; 147 | for (unsigned int i = 0; i < gDatalen; i++) 148 | gSampleData[i] = output[i] * (1.0f / 0x7fff); 149 | free(output); 150 | totalPCMFrameCount = frames; 151 | } 152 | } 153 | 154 | if (!gSampleData) 155 | { 156 | // okay, keep your secrets. 157 | printf("Failed to load data\n"); 158 | exit(0); 159 | } 160 | 161 | gDatalen = ((int)(totalPCMFrameCount * gChannels) / gDimensions) * gDimensions; // rounded to "gDimensions" 162 | } 163 | 164 | void resample(int targetsamplerate, int mono, int fast) 165 | { 166 | if (mono && gChannels != 1) 167 | { 168 | printf("Mixing %d channels to mono.\n", gChannels); 169 | // Mix down to mono by adding all gChannels together. 170 | float* t = new float[gDatalen / gChannels]; 171 | float mag = 0; 172 | float srcmag = 0; 173 | for (unsigned int i = 0; i < (gDatalen / gChannels); i++) 174 | { 175 | t[i] = 0; 176 | for (unsigned int j = 0; j < gChannels; j++) 177 | { 178 | float src = gSampleData[i * gChannels + j]; 179 | t[i] += src; 180 | if (abs(src) > srcmag) srcmag = abs(src); 181 | } 182 | if (abs(t[i]) > mag) mag = abs(t[i]); 183 | } 184 | delete[] gSampleData; 185 | gSampleData = t; 186 | gDatalen /= gChannels; 187 | gChannels = 1; 188 | 189 | // re-scale magnitude to original levels 190 | if (srcmag != 0) 191 | for (unsigned int i = 0; i < gDatalen; i++) 192 | { 193 | gSampleData[i] *= srcmag / mag; 194 | } 195 | } 196 | 197 | if (targetsamplerate != gSampleRate) 198 | { 199 | printf("Resampling from %d to %d (libsamplerate %s).\n", gSampleRate, targetsamplerate, fast ? "SRC_SINC_FASTEST" : "SINC_BEST_QUALITY"); 200 | SRC_DATA d; 201 | d.data_in = gSampleData; 202 | d.input_frames = gDatalen / gChannels; 203 | d.src_ratio = targetsamplerate / (float)gSampleRate; 204 | d.output_frames = (int)((gDatalen / gChannels) * d.src_ratio); 205 | d.data_out = new float[d.output_frames * gChannels]; 206 | 207 | if (src_simple(&d, fast ? SRC_SINC_FASTEST : SRC_SINC_BEST_QUALITY, gChannels)) 208 | { 209 | printf("Resampling failed.\n"); 210 | exit(0); 211 | } 212 | 213 | delete[] gSampleData; 214 | gSampleData = d.data_out; 215 | gDatalen = d.output_frames_gen * gChannels; 216 | gSampleRate = targetsamplerate; 217 | } 218 | 219 | gChunkData = new unsigned char[gDatalen]; 220 | gIndex = new unsigned int[gDatalen / gDimensions]; 221 | unsigned char tp[MAX_DIMENSIONS]; 222 | for (unsigned int i = 0; i < gDatalen / gDimensions; i++) 223 | { 224 | for (unsigned int j = 0; j < gDimensions; j++) 225 | tp[j] = (unsigned char)((gSampleData[gDimensions * i + j] + 1.0) * 127); 226 | insert_chunk(tp); 227 | } 228 | } 229 | 230 | void prep_output(const char* fn) 231 | { 232 | gOutFile = fopen(fn, "wb"); 233 | int tag = 'CAFL'; // gets reversed 234 | fwrite(&tag, 1, 4, gOutFile); 235 | int version = 0; 236 | fwrite(&version, 1, 4, gOutFile); 237 | fwrite(&gSampleRate, 1, 4, gOutFile); 238 | fwrite(&gChannels, 1, 4, gOutFile); 239 | fwrite(&gDimensions, 1, 4, gOutFile); 240 | fwrite(&gWindow, 1, 4, gOutFile); 241 | fwrite(&gDatalen, 1, 4, gOutFile); 242 | int reserved = 0; 243 | fwrite(&reserved, 1, 4, gOutFile); 244 | } 245 | 246 | void init_encode() 247 | { 248 | for (int i = 0; i < MAX_GROUPS; i++) 249 | { 250 | gGroup[i] = 0; 251 | gGroupofs[i] = 0; 252 | } 253 | 254 | gGroupCount = 1; 255 | 256 | gChunks = gWindowSize / gDimensions; 257 | 258 | for (unsigned int i = 0; i < gChunks; i++) 259 | gIndex[i] = i; 260 | 261 | for (unsigned int i = 0; i < MAX_GROUPS * MAX_DIMENSIONS; i++) 262 | gAnalysis[i] = -1; 263 | 264 | gGroup[0] = gChunks; // first group contains all chunks 265 | } 266 | 267 | enum { 268 | CUT_MEDIAN, 269 | CUT_AVERAGE, 270 | CUT_MEAN, 271 | CUT_EVEN 272 | }; 273 | 274 | void split_group(int g, int d, int cut_type) 275 | { 276 | unsigned char* chunkdata = gChunkData + gWindowOffset; 277 | //printf("Splitting group %3d, dimension %d, delta %3d (%d items)\n", g, d, gAnalysis[g*gDimensions+d], gGroup[g]); 278 | sort_group(g, d); 279 | int total = 0; 280 | int minval = 255, maxval = 0; 281 | for (unsigned int i = 0; i < gGroup[g]; i++) 282 | { 283 | total += chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 284 | if (chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d] > maxval) maxval = chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 285 | if (chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d] < minval) minval = chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 286 | } 287 | if (total < 0) 288 | { 289 | printf("borked\n"); 290 | exit(0); 291 | } 292 | unsigned int i = 0; 293 | if (cut_type == CUT_MEAN) 294 | { 295 | // average cut 296 | int midval = minval + (maxval - minval) / 2; 297 | while (chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d] < midval) i++; 298 | } 299 | if (cut_type == CUT_AVERAGE) 300 | { 301 | int split = total / 2; 302 | total = 0; 303 | // median cut 304 | while (total < split) 305 | { 306 | total += chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 307 | i++; 308 | } 309 | } 310 | if (cut_type == CUT_EVEN) 311 | { 312 | i = gGroup[g] / 2; // halve space 313 | } 314 | if (cut_type == CUT_MEDIAN) 315 | { 316 | i = gGroup[g] / 2; 317 | int v = chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 318 | while (i > 0 && v == chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]) i--; 319 | if (i == 0) 320 | { 321 | i = gGroup[g] / 2; 322 | v = chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 323 | while (i < gGroup[g] && v == chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]) i++; 324 | if (i == gGroup[g]) 325 | i /= 2; 326 | } 327 | } 328 | 329 | if (i == gGroup[g]) 330 | i--; // avoid splitting to empty groups 331 | if (i < 1) return; 332 | gGroup[gGroupCount] = gGroup[g] - i; 333 | gGroupofs[gGroupCount] = gGroupofs[g] + i; 334 | gGroup[g] = i; 335 | analyze_group(g); 336 | analyze_group(gGroupCount); 337 | gGroupCount++; 338 | } 339 | 340 | double dist(const unsigned char* a, const unsigned char* b) 341 | { 342 | double s = 0; 343 | for (unsigned int i = 0; i < gDimensions; i++) 344 | s += ((double)a[i] - (double)b[i]) * ((double)a[i] - (double)b[i]); 345 | return sqrt(s); 346 | } 347 | 348 | void average_groups() 349 | { 350 | unsigned char* chunkdata = gChunkData + gWindowOffset; 351 | for (unsigned int i = 0; i < gGroupCount * gDimensions; i++) 352 | gDictionary[i] = 0; 353 | 354 | // Calculate average chunk 355 | for (unsigned int g = 0; g < gGroupCount; g++) 356 | { 357 | for (unsigned int d = 0; d < gDimensions; d++) 358 | { 359 | if (gGroup[g]) 360 | { 361 | unsigned int total = 0; 362 | for (unsigned int i = 0; i < gGroup[g]; i++) 363 | total += chunkdata[gIndex[gGroupofs[g] + i] * gDimensions + d]; 364 | gDictionary[g * gDimensions + d] = total / gGroup[g]; 365 | } 366 | } 367 | } 368 | } 369 | 370 | double verify() 371 | { 372 | unsigned char* chunkdata = gChunkData + gWindowOffset; 373 | // decompress the data and calculate error compared to source. 374 | for (unsigned int i = 0; i < gChunks; i++) 375 | { 376 | for (unsigned int j = 0; j < gDimensions; j++) 377 | { 378 | gUnpackedData[i * gDimensions + j + gWindowOffset] = gDictionary[gOutData[i] * gDimensions + j]; 379 | } 380 | } 381 | long long errsum = 0; 382 | for (unsigned int i = 0; i < gChunks * gDimensions; i++) 383 | { 384 | int d = abs(gUnpackedData[i + gWindowOffset] - chunkdata[i]); 385 | errsum += d; 386 | } 387 | 388 | return errsum / (double)(gChunks * gDimensions); 389 | } 390 | 391 | 392 | void map_indices() 393 | { 394 | unsigned char* chunkdata = gChunkData + gWindowOffset; 395 | gOutData = new unsigned char[gChunks]; 396 | for (unsigned int i = 0; i < gChunks; i++) 397 | { 398 | int idx = 0; 399 | double distance = dist(gDictionary, chunkdata + i * gDimensions); 400 | 401 | for (unsigned int g = 1; g < gGroupCount; g++) 402 | { 403 | double d = dist(gDictionary + g * gDimensions, chunkdata + i * gDimensions); 404 | if (d < distance) 405 | { 406 | distance = d; 407 | idx = g; 408 | } 409 | } 410 | gOutData[i] = idx; 411 | } 412 | double err = verify(); 413 | printf("avg error %3.3f\n", err); 414 | fwrite(gDictionary, gDimensions * 256, 1, gOutFile); 415 | fwrite(gOutData, gChunks, 1, gOutFile); 416 | } 417 | 418 | void map_indices(int maxiter) 419 | { 420 | unsigned char* chunkdata = gChunkData + gWindowOffset; 421 | gOutData = new unsigned char[gChunks]; 422 | int changed = 1; 423 | int timeout = 0; 424 | double err = 1000000; 425 | double preverr = err; 426 | while (changed && timeout < maxiter && err <= preverr) 427 | { 428 | preverr = err; 429 | printf("%c\r", "\\-/|"[timeout % 4]); 430 | timeout++; 431 | changed = 0; 432 | for (unsigned int i = 0; i < gChunks; i++) 433 | { 434 | int idx = 0; 435 | double distance = dist(gDictionary, chunkdata + i * gDimensions); 436 | 437 | for (unsigned int g = 1; g < gGroupCount; g++) 438 | { 439 | double d = dist(gDictionary + g * gDimensions, chunkdata + i * gDimensions); 440 | if (d < distance) 441 | { 442 | distance = d; 443 | idx = g; 444 | } 445 | } 446 | if (gOutData[i] != idx) 447 | { 448 | gOutData[i] = idx; 449 | changed = 1; 450 | } 451 | } 452 | 453 | // Recalculate averages 454 | 455 | for (unsigned int g = 0; g < 256; g++) 456 | { 457 | for (unsigned int d = 0; d < gDimensions; d++) 458 | { 459 | int total = 0; 460 | int count = 0; 461 | for (unsigned int i = 0; i < gChunks; i++) 462 | { 463 | if (gOutData[i] == g) 464 | { 465 | total += *(chunkdata + i * gDimensions + d); 466 | count++; 467 | } 468 | } 469 | if (count != 0) 470 | gDictionary[g * gDimensions + d] = total / count; 471 | else 472 | gDictionary[g * gDimensions + d] = 0; 473 | } 474 | } 475 | 476 | //average_groups(); 477 | err = verify(); 478 | } 479 | printf("%d iterations, avg error %3.3f\n", timeout, err); 480 | fwrite(gDictionary, gDimensions * 256, 1, gOutFile); 481 | fwrite(gOutData, gChunks, 1, gOutFile); 482 | } 483 | 484 | void finish() 485 | { 486 | fclose(gOutFile); 487 | } 488 | 489 | void reduce(int cut_type, int part, int parts) 490 | { 491 | printf("Compressing part %d/%d with %d dimensions at %dHz, %d byte / %d grain window.\n", part, parts, gDimensions, gSampleRate, gWindowSize, gWindowSize / gDimensions); 492 | analyze_group(0); 493 | for (int i = 1; i < MAX_GROUPS; i++) 494 | { 495 | int t = find_largest(); 496 | int g = t / gDimensions; 497 | int d = t % gDimensions; 498 | split_group(g, d, cut_type); 499 | } 500 | } 501 | 502 | 503 | void save_data(const char* fn, unsigned char*data) 504 | { 505 | drwav_data_format format; 506 | format.container = drwav_container_riff; 507 | format.format = DR_WAVE_FORMAT_PCM; 508 | format.channels = gChannels; 509 | format.sampleRate = gSampleRate; 510 | format.bitsPerSample = 8; 511 | drwav wav; 512 | if (!drwav_init_file_write(&wav, fn, &format, NULL)) 513 | { 514 | printf("Failed to open \"%s\" for writing\n", fn); 515 | return; 516 | } 517 | drwav_write_pcm_frames(&wav, gDatalen / gChannels, data); 518 | drwav_uninit(&wav); 519 | } 520 | 521 | void save_compare_data(const char* fn, int fast) 522 | { 523 | int windowing_extra_data = gWindow ? (gDatalen / (gDimensions * gWindow)) * 256 * gDimensions : 0; 524 | int compress_size = gDatalen / gDimensions + 256 * gDimensions + windowing_extra_data; 525 | float compressionratio = compress_size / (float)gDatalen; 526 | int targetsamplerate = (int)(gSampleRate * compressionratio); 527 | 528 | printf("Saving compare file \"%s\" at sample rate %dHz\n", fn, targetsamplerate); 529 | 530 | SRC_DATA d; 531 | d.data_in = gSampleData; 532 | d.input_frames = gDatalen / gChannels; 533 | d.src_ratio = targetsamplerate / (float)gSampleRate; 534 | d.output_frames = (int)((gDatalen / gChannels) * d.src_ratio); 535 | d.data_out = new float[d.output_frames * gChannels]; 536 | 537 | if (src_simple(&d, fast ? SRC_SINC_FASTEST : SRC_SINC_BEST_QUALITY, gChannels)) 538 | { 539 | printf("Resampling failed.\n"); 540 | exit(0); 541 | } 542 | 543 | unsigned char* data = new unsigned char[d.output_frames_gen * gChannels]; 544 | for (unsigned int i = 0; i < d.output_frames_gen * gChannels; i++) 545 | data[i] = (unsigned char)((d.data_out[i] * 0.5 + 0.5) * 255); 546 | 547 | drwav_data_format format; 548 | format.container = drwav_container_riff; 549 | format.format = DR_WAVE_FORMAT_PCM; 550 | format.channels = gChannels; 551 | format.sampleRate = targetsamplerate; 552 | format.bitsPerSample = 8; 553 | drwav wav; 554 | if (!drwav_init_file_write(&wav, fn, &format, NULL)) 555 | { 556 | printf("Failed to open \"%s\" for writing\n", fn); 557 | return; 558 | } 559 | drwav_write_pcm_frames(&wav, d.output_frames_gen, data); 560 | drwav_uninit(&wav); 561 | 562 | delete[] data; 563 | delete[] d.data_out; 564 | } 565 | 566 | enum optionIndex { UNKNOWN, HELP, SAMPLERATE, DIMENSIONS, MONO, WINDOW, SAVE, SAVESRC, SAVECMP, FASTRS, CUTTYPE, MAXITER, CUTS, OLDENC }; 567 | const option::Descriptor usage[] = 568 | { 569 | { UNKNOWN, 0, "", "", option::Arg::None, "USAGE: encoder inputfilename outputfilename [options]\n\nOptions:"}, 570 | { HELP, 0, "h", "help", option::Arg::None, " -h --help\t Print usage and exit"}, 571 | { SAMPLERATE, 0, "r", "samplerate", option::Arg::Optional, " -r --samplerate=sr\t Set target samplerate (default: use source)"}, 572 | { DIMENSIONS, 0, "d", "dimensions", option::Arg::Optional, " -d --dimensions=dim\t Set number of dimensions (default 4)"}, 573 | { MONO, 0, "m", "mono", option::Arg::None, " -m --mono\t Mix to mono (default: use source)"}, 574 | { WINDOW, 0, "w", "window", option::Arg::Optional, " -w --window=winsize\t Set window size in grains (default: infinite)"}, 575 | { CUTS, 0, "z", "cuts", option::Arg::Optional, " -z --cuts=n\t Cut source in N windows (default: one)"}, 576 | { SAVE, 0, "o", "saveout", option::Arg::Optional, " -o --saveout=filename\t Save re-decompressed file (default: don't)"}, 577 | { SAVESRC, 0, "s", "savesrc", option::Arg::Optional, " -s --savesrc=filename\t Save raw soure data (after resampling) (default: don't)"}, 578 | { SAVECMP, 0, "c", "savecmp", option::Arg::Optional, " -c --savecmp=filename\t Save size-comparable low-freq wav (default: don't)"}, 579 | { FASTRS, 0, "f", "fastresample", option::Arg::None, " -f --fastresample\t Use fast resampler (default: SINC_BEST)"}, 580 | { CUTTYPE, 0, "x", "cuttype", option::Arg::Optional, " -x --cuttype=type\t Subspace cut type: even, mean, average, median. (default: median)"}, 581 | { MAXITER, 0, "i", "maxiter", option::Arg::Optional, " -i --maxiter=iters\t Maximum iterations for re-centering grains (default:10)"}, 582 | { OLDENC, 0, "l", "oldenc", option::Arg::None, " -l --oldenc\t Use old encoder (default: use new)"}, 583 | { UNKNOWN, 0, "", "", option::Arg::None, "Example:\n encoder dasboot.mp3 theshoe.sad -m --gWindow=65536 -d16"}, 584 | { 0,0,0,0,0,0 } 585 | }; 586 | 587 | int main(int parc, char** pars) 588 | { 589 | printf("LFAC encoder by Jari Komppa 2021-2023 http://iki.fi/sol\n"); 590 | 591 | option::Stats stats(usage, parc - 1, pars + 1); 592 | assert(stats.buffer_max < 16 && stats.options_max < 16); 593 | option::Option options[16], buffer[16]; 594 | option::Parser parse(true, usage, parc - 1, pars + 1, options, buffer); 595 | 596 | if (options[UNKNOWN]) 597 | { 598 | for (option::Option* opt = options[UNKNOWN]; opt; opt = opt->next()) 599 | printf("Unknown option: %s\n", opt->name); 600 | printf("Run without parameters for help.\n"); 601 | exit(0); 602 | } 603 | 604 | if (parse.error() || parc < 3 || options[HELP] || parse.nonOptionsCount() != 2) 605 | { 606 | option::printUsage(std::cout, usage); 607 | return 0; 608 | } 609 | 610 | if (options[DIMENSIONS] && options[DIMENSIONS].arg) 611 | { 612 | gDimensions = atoi(options[DIMENSIONS].arg); 613 | if (gDimensions < 2 || gDimensions > 64) 614 | { 615 | printf("Bad value for dimensions. Try something like 2 or 16.\n"); 616 | return 0; 617 | } 618 | if (gDimensions > 16) 619 | { 620 | printf("Note: dimensions set quite high. Quality will likely be horrible.\n"); 621 | } 622 | } 623 | 624 | if (options[WINDOW] && options[WINDOW].arg) 625 | { 626 | gWindow = atoi(options[WINDOW].arg); 627 | if (gWindow == 0) 628 | { 629 | // fine 630 | } 631 | else 632 | if (gWindow < gDimensions * gDimensions * 256 / (gDimensions - 1)) 633 | { 634 | printf("Given window size (%d) would cause resulting file to be bigger than original. (break even at %d)\n", gWindow, gDimensions * gDimensions * 256 / (gDimensions - 1)); 635 | return 0; 636 | } 637 | } 638 | 639 | load_data(parse.nonOption(0)); 640 | 641 | int sr = gSampleRate; 642 | if (options[SAMPLERATE] && options[SAMPLERATE].arg) 643 | sr = atoi(options[SAMPLERATE].arg); 644 | if (sr < 1 || sr > 256000) 645 | { 646 | printf("Bad value for sample rate.\n"); 647 | return 0; 648 | } 649 | 650 | int cut_type = CUT_MEDIAN; 651 | if (options[CUTTYPE] && options[CUTTYPE].arg) 652 | { 653 | if (_stricmp(options[CUTTYPE].arg, "even")) cut_type = CUT_EVEN; else 654 | if (_stricmp(options[CUTTYPE].arg, "average")) cut_type = CUT_AVERAGE; else 655 | if (_stricmp(options[CUTTYPE].arg, "median")) cut_type = CUT_MEDIAN; else 656 | if (_stricmp(options[CUTTYPE].arg, "mean")) cut_type = CUT_MEAN; else 657 | { 658 | printf("Unknown cut type: %s\n", options[CUTTYPE].arg); 659 | exit(0); 660 | } 661 | } 662 | 663 | int maxiters = 10; 664 | if (options[MAXITER] && options[MAXITER].arg) 665 | maxiters = atoi(options[MAXITER].arg); 666 | if (maxiters < 1 || maxiters > 10000) 667 | { 668 | printf("Invalid number of max iterations specified\n"); 669 | exit(0); 670 | } 671 | 672 | resample(sr, !!options[MONO], !!options[FASTRS]); 673 | 674 | if (options[CUTS] && options[CUTS].arg) 675 | { 676 | int cuts = atoi(options[CUTS].arg); 677 | if (cuts <= 0) 678 | { 679 | printf("Invalid number of cuts (%d) specified\n", cuts); 680 | return 0; 681 | } 682 | int w = (gDatalen / gDimensions) / cuts; 683 | // make sure last window doesn't end up being really tiny.. 684 | if (w * cuts * gDimensions < gDatalen) w++; 685 | gWindow = w; 686 | printf("Cutting source to %d pieces, yielding %d grain window.\n", cuts, w); 687 | } 688 | 689 | 690 | if (gWindow > gDatalen / gDimensions) 691 | gWindow = gDatalen / gDimensions; 692 | 693 | gUnpackedData = new unsigned char[gDatalen]; 694 | 695 | 696 | if (options[SAVESRC] && options[SAVESRC].arg && strlen(options[SAVESRC].arg) > 0) 697 | { 698 | printf("Saving source data as \"%s\"\n", options[SAVESRC].arg); 699 | save_data(options[SAVESRC].arg, gChunkData); 700 | } 701 | 702 | if (options[SAVECMP] && options[SAVECMP].arg && strlen(options[SAVECMP].arg) > 0) 703 | save_compare_data(options[SAVECMP].arg, !!options[FASTRS]); 704 | 705 | bool oldenc = options[OLDENC]; 706 | 707 | unsigned int total_left = gDatalen; 708 | prep_output(parse.nonOption(1)); 709 | int part = 0; 710 | int parts = 1; 711 | if (gWindow) 712 | parts += gDatalen / (gWindow * gDimensions); 713 | while (total_left > 0) 714 | { 715 | part++; 716 | printf("Total bytes left: %d\n", total_left); 717 | if (total_left > gWindow * gDimensions) 718 | gWindowSize = gWindow * gDimensions; 719 | else 720 | gWindowSize = total_left; 721 | if (gWindow == 0) gWindowSize = gDatalen; 722 | if (oldenc) 723 | { 724 | // old encoder 725 | init_encode(); 726 | reduce(cut_type, part, parts); 727 | average_groups(); 728 | map_indices(maxiters); 729 | verify(); 730 | } 731 | else 732 | { 733 | init_encode(); 734 | reduce(cut_type, part, parts); 735 | gGroupCount = 256; 736 | average_groups(); 737 | // new encoder 738 | vq::reduce( 739 | gChunkData + gWindowOffset, 740 | gDimensions, 741 | gChunks, 742 | gDictionary); 743 | map_indices(); 744 | verify(); 745 | } 746 | gWindowOffset += gWindowSize; 747 | if (gWindow != 0 && gWindow * gDimensions < total_left) 748 | total_left -= gWindow * gDimensions; 749 | else 750 | total_left = 0; 751 | } 752 | finish(); 753 | if (options[SAVE] && options[SAVE].arg && strlen(options[SAVE].arg) > 0) 754 | { 755 | printf("Saving uncompressed data as \"%s\"\n", options[SAVE].arg); 756 | save_data(options[SAVE].arg, gUnpackedData); 757 | } 758 | return 0; 759 | } -------------------------------------------------------------------------------- /src/vq.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace vq 4 | { 5 | // Calculate distance between two nodes 6 | template 7 | double distance(T* a, T* b, int aNodeSize) 8 | { 9 | double d = 0; 10 | for (int i = 0; i < aNodeSize; i++) 11 | d += (static_cast(a[i]) - static_cast(b[i])) * (static_cast(a[i]) - static_cast(b[i])); 12 | return sqrt(d); 13 | } 14 | 15 | // Select initial bins (center nodes) 16 | template 17 | void select(T* aNode, int aNodeSize, int aNodeCount, T* aBin, int bins) 18 | { 19 | return; 20 | } 21 | 22 | // Average bin to get to a new center 23 | template 24 | void average(T* aNode, int aNodeSize, int* index, int indices, T* out) 25 | { 26 | if (!indices) 27 | { 28 | for (int i = 0; i < aNodeSize; i++) 29 | out[i] = 0; 30 | return; 31 | } 32 | 33 | for (int i = 0; i < aNodeSize; i++) 34 | { 35 | long long sum = 0; 36 | for (int j = 0; j < indices; j++) 37 | { 38 | sum += static_cast(aNode[index[j] * aNodeSize + i]); 39 | } 40 | sum /= indices; 41 | out[i] = (T)(sum); 42 | } 43 | } 44 | 45 | // Nudge node to split a bin 46 | template 47 | void nudge(T* aNode, int aNodeSize) 48 | { 49 | int i = rand() % aNodeSize; 50 | if (aNode[i] >= 1) 51 | { 52 | if (rand() & 1) 53 | aNode[i]--; 54 | else 55 | aNode[i]++; 56 | } 57 | else 58 | aNode[i]++; 59 | } 60 | 61 | template 62 | void reduce(T* aNode, int aNodeSize, int aNodeCount, T* aBin) 63 | { 64 | int* bin; 65 | int binc[bins]; 66 | for (auto& x : binc) x = 0; 67 | bin = new int[bins * aNodeCount]; 68 | 69 | // 1. initial selection 70 | 71 | select(aNode, aNodeSize, aNodeCount, aBin, bins); 72 | 73 | double lastError = 1e100; 74 | double error = 1e100; 75 | int iter = 0; 76 | int force = 0; 77 | 78 | do 79 | { 80 | force = 0; 81 | iter++; 82 | 83 | // 2. move to closest group 84 | 85 | for (auto& x : binc) x = 0; 86 | 87 | for (int ni = 0; ni < aNodeCount; ni++) 88 | { 89 | int closest = 0; 90 | double mindist = distance(aNode + ni * aNodeSize, aBin, aNodeSize); 91 | for (int bi = 0; bi < bins; bi++) 92 | { 93 | double d = distance( 94 | aNode + ni * aNodeSize, 95 | aBin + bi * aNodeSize, 96 | aNodeSize); 97 | if (d < mindist) 98 | { 99 | mindist = d; 100 | closest = bi; 101 | } 102 | } 103 | bin[closest * aNodeCount + binc[closest]] = ni; 104 | binc[closest]++; 105 | } 106 | 107 | // 3. calculate new centers 108 | 109 | for (int i = 0; i < bins; i++) 110 | if (binc[i]) 111 | average( 112 | aNode, 113 | aNodeSize, 114 | bin + i * aNodeCount, 115 | binc[i], 116 | aBin + i * aNodeSize); 117 | 118 | // 4. measure error 119 | 120 | lastError = error; 121 | error = 0; 122 | for (int i = 0; i < bins; i++) 123 | { 124 | for (int j = 0; j < binc[i]; j++) 125 | error += distance( 126 | aBin + i * aNodeSize, 127 | aNode + bin[i * aNodeCount + j] * aNodeSize, 128 | aNodeSize); 129 | } 130 | 131 | printf("%c\r", "\\-/|"[iter % 4]); 132 | 133 | int emptybin = -1; 134 | for (int i = 0; i < bins; i++) 135 | { 136 | if (binc[i] == 0) 137 | emptybin = i; 138 | } 139 | 140 | if (emptybin != -1) 141 | { 142 | force = aNodeCount > bins; 143 | // there's an empty bin (or more, but let's fill one at a time) 144 | // - find biggest (not the most populated) group 145 | int biggest = 0; 146 | double bigsize = 0; 147 | for (int i = 0; i < bins; i++) 148 | for (int j = 0; j < binc[i]; j++) 149 | { 150 | double l = distance(aBin + i * aNodeSize, aNode + bin[i * aNodeCount + j] * aNodeSize, aNodeSize); 151 | if (l > bigsize) 152 | { 153 | biggest = i; 154 | bigsize = l; 155 | } 156 | } 157 | // - compete with its center 158 | for (int i = 0; i < aNodeSize; i++) 159 | aBin[emptybin * aNodeSize + i] = aBin[biggest * aNodeSize + i]; 160 | nudge(aBin + emptybin * aNodeSize, aNodeSize); 161 | } 162 | 163 | // 5. repeat 164 | 165 | } 166 | while (iter < maxiter && ((force && error) || (error - lastError) < errorTreshold)); 167 | delete[] bin; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /subdiv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jarikomppa/lfac/ca8d56f5ac4b56fdc265b7918133a824c41932a4/subdiv.png --------------------------------------------------------------------------------