diff options
author | Thomas Tsou <tom@tsou.cc> | 2013-10-30 21:24:40 -0400 |
---|---|---|
committer | Thomas Tsou <tom@tsou.cc> | 2013-11-04 09:15:55 -0800 |
commit | 17bbb9b755b2b91c15114bc2dfb6f29fc7a66377 (patch) | |
tree | 90d90d343f54037ed5cd8472d63fb1f4c2a7f1e1 /Transceiver52M/common | |
parent | a1a3ab4babf591cf9c0d233d93b1188f747f5259 (diff) |
Transceiver52M: Separate architecture specific files
Move x86 specific files into their own directory as this
area is about to get crowded with the addition of ARM
support.
Signed-off-by: Thomas Tsou <tom@tsou.cc>
Diffstat (limited to 'Transceiver52M/common')
-rw-r--r-- | Transceiver52M/common/convert.h | 7 | ||||
-rw-r--r-- | Transceiver52M/common/convolve.h | 30 | ||||
-rw-r--r-- | Transceiver52M/common/convolve_base.c | 156 |
3 files changed, 193 insertions, 0 deletions
diff --git a/Transceiver52M/common/convert.h b/Transceiver52M/common/convert.h new file mode 100644 index 0000000..5b557bf --- /dev/null +++ b/Transceiver52M/common/convert.h @@ -0,0 +1,7 @@ +#ifndef _CONVERT_H_ +#define _CONVERT_H_ + +void convert_float_short(short *out, float *in, float scale, int len); +void convert_short_float(float *out, short *in, int len); + +#endif /* _CONVERT_H_ */ diff --git a/Transceiver52M/common/convolve.h b/Transceiver52M/common/convolve.h new file mode 100644 index 0000000..aef9953 --- /dev/null +++ b/Transceiver52M/common/convolve.h @@ -0,0 +1,30 @@ +#ifndef _CONVOLVE_H_ +#define _CONVOLVE_H_ + +void *convolve_h_alloc(int num); + +int convolve_real(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset); + +int convolve_complex(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset); + +int base_convolve_real(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset); + +int base_convolve_complex(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset); + +#endif /* _CONVOLVE_H_ */ diff --git a/Transceiver52M/common/convolve_base.c b/Transceiver52M/common/convolve_base.c new file mode 100644 index 0000000..41dba1c --- /dev/null +++ b/Transceiver52M/common/convolve_base.c @@ -0,0 +1,156 @@ +/* + * Convolution + * Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <malloc.h> +#include <string.h> +#include <stdio.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Base multiply and accumulate complex-real */ +static void mac_real(float *x, float *h, float *y) +{ + y[0] += x[0] * h[0]; + y[1] += x[1] * h[0]; +} + +/* Base multiply and accumulate complex-complex */ +static void mac_cmplx(float *x, float *h, float *y) +{ + y[0] += x[0] * h[0] - x[1] * h[1]; + y[1] += x[0] * h[1] + x[1] * h[0]; +} + +/* Base vector complex-complex multiply and accumulate */ +static void mac_real_vec_n(float *x, float *h, float *y, + int len, int step, int offset) +{ + for (int i = offset; i < len; i += step) + mac_real(&x[2 * i], &h[2 * i], y); +} + +/* Base vector complex-complex multiply and accumulate */ +static void mac_cmplx_vec_n(float *x, float *h, float *y, + int len, int step, int offset) +{ + for (int i = offset; i < len; i += step) + mac_cmplx(&x[2 * i], &h[2 * i], y); +} + +/* Base complex-real convolution */ +int _base_convolve_real(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset) +{ + for (int i = 0; i < len; i++) { + mac_real_vec_n(&x[2 * (i - (h_len - 1) + start)], + h, + &y[2 * i], h_len, + step, offset); + } + + return len; +} + +/* Base complex-complex convolution */ +int _base_convolve_complex(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset) +{ + for (int i = 0; i < len; i++) { + mac_cmplx_vec_n(&x[2 * (i - (h_len - 1) + start)], + h, + &y[2 * i], + h_len, step, offset); + } + + return len; +} + +/* Buffer validity checks */ +int bounds_check(int x_len, int h_len, int y_len, + int start, int len, int step) +{ + if ((x_len < 1) || (h_len < 1) || + (y_len < 1) || (len < 1) || (step < 1)) { + fprintf(stderr, "Convolve: Invalid input\n"); + return -1; + } + + if ((start + len > x_len) || (len > y_len) || (x_len < h_len)) { + fprintf(stderr, "Convolve: Boundary exception\n"); + fprintf(stderr, "start: %i, len: %i, x: %i, h: %i, y: %i\n", + start, len, x_len, h_len, y_len); + return -1; + } + + return 0; +} + +/* API: Non-aligned (no SSE) complex-real */ +int base_convolve_real(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset) +{ + if (bounds_check(x_len, h_len, y_len, start, len, step) < 0) + return -1; + + memset(y, 0, len * 2 * sizeof(float)); + + return _base_convolve_real(x, x_len, + h, h_len, + y, y_len, + start, len, step, offset); +} + +/* API: Non-aligned (no SSE) complex-complex */ +int base_convolve_complex(float *x, int x_len, + float *h, int h_len, + float *y, int y_len, + int start, int len, + int step, int offset) +{ + if (bounds_check(x_len, h_len, y_len, start, len, step) < 0) + return -1; + + memset(y, 0, len * 2 * sizeof(float)); + + return _base_convolve_complex(x, x_len, + h, h_len, + y, y_len, + start, len, step, offset); +} + +/* Aligned filter tap allocation */ +void *convolve_h_alloc(int len) +{ +#ifdef HAVE_SSE3 + return memalign(16, len * 2 * sizeof(float)); +#else + return malloc(len * 2 * sizeof(float)); +#endif +} |