~ubuntu-branches/ubuntu/trusty/roaraudio/trusty

1.1.2 by Patrick Matthäi
Import upstream version 0.3
1
//resampler_poly3.c:
2
3
/*
1.1.16 by Patrick Matthäi
Import upstream version 1.0~beta11
4
 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2014
1.1.2 by Patrick Matthäi
Import upstream version 0.3
5
 *      Copyright (C) Hans-Kristian 'maister' Arntzen - 2010
6
 *
7
 *  This file is part of libroar a part of RoarAudio,
8
 *  a cross-platform sound system for both, home and professional use.
9
 *  See README for details.
10
 *
11
 *  This file is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License version 3
13
 *  as published by the Free Software Foundation.
14
 *
15
 *  libroar is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this software; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23
 *  Boston, MA 02110-1301, USA.
24
 *
25
 *  NOTE for everyone want's to change something and send patches:
26
 *  read README and HACKING! There a addition information on
27
 *  the license of this document you need to read before you send
28
 *  any patches.
29
 *
30
 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
31
 *  or libpulse*:
32
 *  The libs libroaresd, libroararts and libroarpulse link this lib
33
 *  and are therefore GPL. Because of this it may be illigal to use
34
 *  them with any software that uses libesd, libartsc or libpulse*.
35
 */
36
37
#include "libroardsp.h"
38
39
int roar_conv_poly3_8 (int8_t * out, int8_t * in, size_t olen, size_t ilen, int channels) {
40
 float ratio = (float)olen / (float)ilen;
41
 int8_t *ip;
42
 int c, x;
43
 float pos_in;
44
 float poly[3];
45
 float y[3];
46
 float x_val;
47
 int_least16_t temp;
48
49
 /* Can't create poly out of less than 3 samples in each channel. */
50
 if ( ilen < 3 * channels )
51
  return -1;
52
53
 ip = roar_mm_malloc(ilen * sizeof(int8_t));
54
 if ( ip == NULL )
55
  return -1;
56
57
 memcpy(ip, in, ilen * sizeof(int8_t));
58
59
 olen /= channels;
60
61
 for (x = 0; x < olen; x++) {
62
  for (c = 0; c < channels; c++) {
63
   pos_in = (float)x / ratio;
64
65
   if ( (int)pos_in == 0 ) {
66
    y[0] = ip[0 * channels + c];
67
    y[1] = ip[1 * channels + c];
68
    y[2] = ip[2 * channels + c];
69
    x_val = pos_in;
70
    roar_math_mkpoly_3x3(poly, y);
71
   } else if ( (int)pos_in + 1 >= ilen/channels ) {
72
    /* If we're at the end of the block, we will need to interpolate against a value that is not yet known.
73
     * We will assume this value, by linearly extrapolating the two preceding values. From causual testing, this is not audible. */
74
    y[0] = ip[((int)pos_in - 1) * channels + c];
75
    y[1] = ip[((int)pos_in    ) * channels + c];
76
77
    // we create a 2x2 poly here and set the 3rd coefficient to zero to build a 3x3 poly
78
    roar_math_mkpoly_2x2(poly, y);
79
    poly[2] = 0;
80
    x_val = pos_in - (int)pos_in + 1.0;
81
   } else {
82
    y[0] = ip[((int)pos_in - 1) * channels + c];
83
    y[1] = ip[((int)pos_in    ) * channels + c];
84
    y[2] = ip[((int)pos_in + 1) * channels + c];
85
    x_val = pos_in - (int)pos_in + 1.0;
86
    roar_math_mkpoly_3x3(poly, y);
87
   }
88
89
90
   temp = (float)(poly[2]*x_val*x_val + poly[1]*x_val + poly[0] + 0.5);
91
   /* temp could be out of bounds, so need to check this */
92
   if ( temp > 0x7E ) {
93
    out[x * channels + c] =  0x7E;
94
   } else if (temp < -0x7F) {
95
    out[x * channels + c] = -0x7F;
96
   } else {
97
    out[x * channels + c] = (int8_t)temp;
98
   }
99
  }
100
 }
101
102
 roar_mm_free(ip);
103
 return 0;
104
}
105
106
int roar_conv_poly3_16 (int16_t * out, int16_t * in, size_t olen, size_t ilen, int channels) {
107
 float ratio = (float)olen / (float)ilen;
108
 int16_t *ip;
109
 int c, x;
110
 float pos_in;
111
 float poly[3];
112
 float y[3];
113
 float x_val;
114
 int_least32_t temp;
115
116
 /* Can't create poly out of less than 3 samples in each channel. */
117
 if ( ilen < 3 * channels )
118
  return -1;
119
120
 ip = roar_mm_malloc(ilen * sizeof(int16_t));
121
 if ( ip == NULL )
122
  return -1;
123
124
 memcpy(ip, in, ilen * sizeof(int16_t));
125
126
 olen /= channels;
127
128
 for (x = 0; x < olen; x++) {
129
  for (c = 0; c < channels; c++) {
130
   pos_in = (float)x / ratio;
131
132
   if ( (int)pos_in == 0 ) {
133
    y[0] = ip[0 * channels + c];
134
    y[1] = ip[1 * channels + c];
135
    y[2] = ip[2 * channels + c];
136
    x_val = pos_in;
137
    roar_math_mkpoly_3x3(poly, y);
138
   } else if ( (int)pos_in + 1 >= ilen/channels ) {
139
    /* If we're at the end of the block, we will need to interpolate against a value that is not yet known.
140
     * We will assume this value, by linearly extrapolating the two preceding values. From causual testing, this is not audible. */
141
    y[0] = ip[((int)pos_in - 1) * channels + c];
142
    y[1] = ip[((int)pos_in    ) * channels + c];
143
144
    // we create a 2x2 poly here and set the 3rd coefficient to zero to build a 3x3 poly
145
    roar_math_mkpoly_2x2(poly, y);
146
    poly[2] = 0;
147
    x_val = pos_in - (int)pos_in + 1.0;
148
   } else {
149
    y[0] = ip[((int)pos_in - 1) * channels + c];
150
    y[1] = ip[((int)pos_in    ) * channels + c];
151
    y[2] = ip[((int)pos_in + 1) * channels + c];
152
    x_val = pos_in - (int)pos_in + 1.0;
153
    roar_math_mkpoly_3x3(poly, y);
154
   }
155
156
157
   temp = (float)(poly[2]*x_val*x_val + poly[1]*x_val + poly[0] + 0.5);
158
   /* temp could be out of bounds, so need to check this */
159
   if (temp > 0x7FFE ) {
160
    out[x * channels + c] =  0x7FFE;
161
   } else if (temp < -0x7FFF) {
162
    out[x * channels + c] = -0x7FFF;
163
   } else {
164
    out[x * channels + c] = (int16_t)temp;
165
   }
166
  }
167
 }
168
169
 roar_mm_free(ip);
170
 return 0;
171
}
172
173
int roar_conv_poly3_32 (int32_t * out, int32_t * in, size_t olen, size_t ilen, int channels) {
174
 float ratio = (float)olen / (float)ilen;
175
 int32_t *ip;
176
 int c, x;
177
 float pos_in;
178
 float poly[3];
179
 float y[3];
180
 float x_val;
181
 int_least64_t temp;
182
183
 /* Can't create poly out of less than 3 samples in each channel. */
184
 if ( ilen < 3 * channels )
185
  return -1;
186
187
 ip = roar_mm_malloc(ilen * sizeof(int32_t));
188
 if ( ip == NULL )
189
  return -1;
190
191
 memcpy(ip, in, ilen * sizeof(int32_t));
192
193
 olen /= channels;
194
195
 for (x = 0; x < olen; x++) {
196
  for (c = 0; c < channels; c++) {
197
   pos_in = (float)x / ratio;
198
199
   if ( (int)pos_in == 0 ) {
200
    y[0] = ip[0 * channels + c];
201
    y[1] = ip[1 * channels + c];
202
    y[2] = ip[2 * channels + c];
203
    x_val = pos_in;
204
    roar_math_mkpoly_3x3(poly, y);
205
   } else if ( (int)pos_in + 1 >= ilen/channels ) {
206
    /* If we're at the end of the block, we will need to interpolate against a value that is not yet known.
207
     * We will assume this value, by linearly extrapolating the two preceding values. From causual testing, this is not audible. */
208
    y[0] = ip[((int)pos_in - 1) * channels + c];
209
    y[1] = ip[((int)pos_in    ) * channels + c];
210
211
    // we create a 2x2 poly here and set the 3rd coefficient to zero to build a 3x3 poly
212
    roar_math_mkpoly_2x2(poly, y);
213
    poly[2] = 0;
214
    x_val = pos_in - (int)pos_in + 1.0;
215
   } else {
216
    y[0] = ip[((int)pos_in - 1) * channels + c];
217
    y[1] = ip[((int)pos_in    ) * channels + c];
218
    y[2] = ip[((int)pos_in + 1) * channels + c];
219
    x_val = pos_in - (int)pos_in + 1.0;
220
    roar_math_mkpoly_3x3(poly, y);
221
   }
222
223
224
   temp = (float)(poly[2]*x_val*x_val + poly[1]*x_val + poly[0] + 0.5);
225
   /* temp could be out of bounds, so need to check this */
226
   if ( temp > 0x7FFFFFFE ) {
227
    out[x * channels + c] =  0x7FFFFFFE;
228
   } else if (temp < -0x7FFFFFFF) {
229
    out[x * channels + c] = -0x7FFFFFFF;
230
   } else {
231
    out[x * channels + c] = (int32_t)temp;
232
   }
233
  }
234
 }
235
236
 roar_mm_free(ip);
237
 return 0;
238
}
239