(automatically generated log message)
Showing the changes to src/src_linear.c (1 of 79 files). Show all
Unified · Split
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | ** Copyright (C) 2002,2003 Erik de Castro Lopo <erikd@mega-nerd.com> | ||
| 3 | ** | ||
| 4 | ** This program is free software; you can redistribute it and/or modify | ||
| 5 | ** it under the terms of the GNU General Public License as published by | ||
| 6 | ** the Free Software Foundation; either version 2 of the License, or | ||
| 7 | ** (at your option) any later version. | ||
| 8 | ** | ||
| 9 | ** This program is distributed in the hope that it will be useful, | ||
| 10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | ** GNU General Public License for more details. | ||
| 13 | ** | ||
| 14 | ** You should have received a copy of the GNU General Public License | ||
| 15 | ** along with this program; if not, write to the Free Software | ||
| 16 | ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <stdio.h> | ||
| 20 | #include <stdlib.h> | ||
| 21 | #include <string.h> | ||
| 22 | |||
| 23 | #include "config.h" | ||
| 24 | #include "float_cast.h" | ||
| 25 | #include "common.h" | ||
| 26 | |||
| 27 | static void linear_reset (SRC_PRIVATE *psrc) ; | ||
| 28 | |||
| 29 | /*======================================================================================== | ||
| 30 | */ | ||
| 31 | |||
| 32 | #define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r') | ||
| 33 | |||
| 34 | #define SRC_DEBUG 0 | ||
| 35 | |||
| 36 | typedef struct | ||
| 37 | { int linear_magic_marker ; | ||
| 38 | int channels ; | ||
| 39 | long in_count, in_used ; | ||
| 40 | long out_count, out_gen ; | ||
| 41 | float last_value [1] ; | ||
| 42 | } LINEAR_DATA ; | ||
| 43 | |||
| 44 | /*---------------------------------------------------------------------------------------- | ||
| 45 | */ | ||
| 46 | int | ||
| 47 | linear_process (SRC_PRIVATE *psrc, SRC_DATA *data) | ||
| 48 | { LINEAR_DATA *linear ; | ||
| 49 | double src_ratio, input_index ; | ||
| 50 | int ch ; | ||
| 51 | |||
| 52 | if (psrc->private_data == NULL) | ||
| 53 | return SRC_ERR_NO_PRIVATE ; | ||
| 54 | |||
| 55 | linear = (LINEAR_DATA*) psrc->private_data ; | ||
| 56 | |||
| 57 | linear->in_count = data->input_frames * linear->channels ; | ||
| 58 | linear->out_count = data->output_frames * linear->channels ; | ||
| 59 | linear->in_used = linear->out_gen = 0 ; | ||
| 60 | |||
| 61 | src_ratio = psrc->last_ratio ; | ||
| 62 | input_index = psrc->last_position ; | ||
| 63 | |||
| 64 | /* Calculate samples before first sample in input array. */ | ||
| 65 | while (input_index < 1.0 && linear->out_gen < linear->out_count) | ||
| 66 | { | ||
| 67 | if (linear->in_used + linear->channels * input_index > linear->in_count) | ||
| 68 | break ; | ||
| 69 | |||
| 70 | if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | ||
| 71 | src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ; | ||
| 72 | |||
| 73 | for (ch = 0 ; ch < linear->channels ; ch++) | ||
| 74 | { data->data_out [linear->out_gen] = linear->last_value [ch] + input_index * | ||
| 75 | (data->data_in [ch] - linear->last_value [ch]) ; | ||
| 76 | linear->out_gen ++ ; | ||
| 77 | } ; | ||
| 78 | |||
| 79 | /* Figure out the next index. */ | ||
| 80 | input_index += 1.0 / src_ratio ; | ||
| 81 | } ; | ||
| 82 | |||
| 83 | linear->in_used += linear->channels * lrint (floor (input_index)) ; | ||
| 84 | input_index -= floor (input_index) ; | ||
| 85 | |||
| 86 | /* Main processing loop. */ | ||
| 87 | while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count) | ||
| 88 | { | ||
| 89 | if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) | ||
| 90 | src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ; | ||
| 91 | |||
| 92 | if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0) | ||
| 93 | { printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ; | ||
| 94 | exit (1) ; | ||
| 95 | } ; | ||
| 96 | |||
| 97 | for (ch = 0 ; ch < linear->channels ; ch++) | ||
| 98 | { data->data_out [linear->out_gen] = data->data_in [linear->in_used - linear->channels + ch] + input_index * | ||
| 99 | (data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch]) ; | ||
| 100 | linear->out_gen ++ ; | ||
| 101 | } ; | ||
| 102 | |||
| 103 | /* Figure out the next index. */ | ||
| 104 | input_index += 1.0 / src_ratio ; | ||
| 105 | |||
| 106 | linear->in_used += linear->channels * lrint (floor (input_index)) ; | ||
| 107 | input_index -= floor (input_index) ; | ||
| 108 | } ; | ||
| 109 | |||
| 110 | if (linear->in_used > linear->in_count) | ||
| 111 | { input_index += linear->in_used - linear->in_count ; | ||
| 112 | linear->in_used = linear->in_count ; | ||
| 113 | } ; | ||
| 114 | |||
| 115 | psrc->last_position = input_index ; | ||
| 116 | |||
| 117 | if (linear->in_used > 0) | ||
| 118 | for (ch = 0 ; ch < linear->channels ; ch++) | ||
| 119 | linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ; | ||
| 120 | |||
| 121 | /* Save current ratio rather then target ratio. */ | ||
| 122 | psrc->last_ratio = src_ratio ; | ||
| 123 | |||
| 124 | data->input_frames_used = linear->in_used / linear->channels ; | ||
| 125 | data->output_frames_gen = linear->out_gen / linear->channels ; | ||
| 126 | |||
| 127 | return SRC_ERR_NO_ERROR ; | ||
| 128 | } /* linear_process */ | ||
| 129 | |||
| 130 | /*------------------------------------------------------------------------------ | ||
| 131 | */ | ||
| 132 | |||
| 133 | const char* | ||
| 134 | linear_get_name (int src_enum) | ||
| 135 | { | ||
| 136 | if (src_enum == SRC_LINEAR) | ||
| 137 | return "Linear Interpolator" ; | ||
| 138 | |||
| 139 | return NULL ; | ||
| 140 | } /* linear_get_name */ | ||
| 141 | |||
| 142 | const char* | ||
| 143 | linear_get_description (int src_enum) | ||
| 144 | { | ||
| 145 | if (src_enum == SRC_LINEAR) | ||
| 146 | return "Linear interpolator, very fast, poor quality." ; | ||
| 147 | |||
| 148 | return NULL ; | ||
| 149 | } /* linear_get_descrition */ | ||
| 150 | |||
| 151 | int | ||
| 152 | linear_set_converter (SRC_PRIVATE *psrc, int src_enum) | ||
| 153 | { LINEAR_DATA *linear = NULL ; | ||
| 154 | |||
| 155 | if (src_enum != SRC_LINEAR) | ||
| 156 | return SRC_ERR_BAD_CONVERTER ; | ||
| 157 | |||
| 158 | if (psrc->private_data != NULL) | ||
| 159 | { linear = (LINEAR_DATA*) psrc->private_data ; | ||
| 160 | if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER) | ||
| 161 | { free (psrc->private_data) ; | ||
| 162 | psrc->private_data = NULL ; | ||
| 163 | } ; | ||
| 164 | } ; | ||
| 165 | |||
| 166 | if (psrc->private_data == NULL) | ||
| 167 | { linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ; | ||
| 168 | if (linear == NULL) | ||
| 169 | return SRC_ERR_MALLOC_FAILED ; | ||
| 170 | psrc->private_data = linear ; | ||
| 171 | } ; | ||
| 172 | |||
| 173 | linear->linear_magic_marker = LINEAR_MAGIC_MARKER ; | ||
| 174 | linear->channels = psrc->channels ; | ||
| 175 | |||
| 176 | psrc->process = linear_process ; | ||
| 177 | psrc->reset = linear_reset ; | ||
| 178 | |||
| 179 | linear_reset (psrc) ; | ||
| 180 | |||
| 181 | return SRC_ERR_NO_ERROR ; | ||
| 182 | } /* linear_set_converter */ | ||
| 183 | |||
| 184 | /*=================================================================================== | ||
| 185 | */ | ||
| 186 | |||
| 187 | static void | ||
| 188 | linear_reset (SRC_PRIVATE *psrc) | ||
| 189 | { LINEAR_DATA *linear = NULL ; | ||
| 190 | |||
| 191 | linear = (LINEAR_DATA*) psrc->private_data ; | ||
| 192 | if (linear == NULL) | ||
| 193 | return ; | ||
| 194 | |||
| 195 | memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ; | ||
| 196 | } /* linear_reset */ | ||
| 197 | /* | ||
| 198 | ** Do not edit or modify anything in this comment block. | ||
| 199 | ** The arch-tag line is a file identity tag for the GNU Arch | ||
| 200 | ** revision control system. | ||
| 201 | ** | ||
| 202 | ** arch-tag: 7eac3103-3d84-45d3-8bbd-f409c2b2d1a9 | ||
| 203 | */ | ||
| 204 | |||