Mercurial > hg > audiostuff
diff spandsp-0.0.3/user/tfir.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.3/user/tfir.c Fri Jun 25 16:00:21 2010 +0200 @@ -0,0 +1,154 @@ +/* + tfir.c + David Rowe + Created 30 May 2007 + + Test program for Spandsp fir2 function, used for developing optimised + Blackfin assembler. +*/ + +/* + Copyright (C) 2007 David Rowe + + All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2, as + published by the Free Software Foundation. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +#include "fir.h" + +#define TAPS 256 +#define N 100 + +/* C-callable function to return value of CYCLES register */ + +int cycles() { + int ret; + + __asm__ __volatile__ + ( + "%0 = CYCLES;\n\t" + : "=&d" (ret) + : + : "R1" + ); + + return ret; +} + +static int32_t dot(int16_t *x, int16_t *y, int n) { + int32_t acc = 0; + int i; + + for(i=0; i<n; i++) + acc += *x++ * *y++; + + return acc; +} + +#ifdef FIRST_TRY +static int16_t fir16_asm(fir16_state_t *fir, int16_t sample) +{ + int i; + int32_t y, y_dot; + int offset1; + int offset2; + + fir->history[fir->curr_pos] = sample; + + offset2 = fir->curr_pos; + offset1 = fir->taps - offset2; + y = 0; + for (i = fir->taps - 1; i >= offset1; i--) + y += fir->coeffs[i]*fir->history[i - offset1]; + y_dot = 0; + y_dot += dot_asm((int16_t*)&fir->coeffs[offset1], fir->history, fir->curr_pos); + printf("offset1 %d offset2: %d y = %d y_dot = %d\n", offset1, offset2, y, y_dot); + assert(y_dot == y); + + for ( ; i >= 0; i--) + y += fir->coeffs[i]*fir->history[i + offset2]; + y_dot += dot((int16_t*)fir->coeffs, &fir->history[offset2], offset1); + assert(y_dot == y); + + if (fir->curr_pos <= 0) + fir->curr_pos = fir->taps; + fir->curr_pos--; + return (int16_t) (y >> 15); +} +#endif + +static int16_t fir16_asm(fir16_state_t *fir, int16_t sample) +{ + int i; + int32_t y, y_dot; + + fir->history[fir->curr_pos] = sample; + fir->history[fir->curr_pos + fir->taps] = sample; + + /* + y = 0; + for (i=0; i<fir->taps; i++) + y += fir->coeffs[i]*fir->history[fir->curr_pos+i]; + */ + y_dot = dot_asm((int16_t*)fir->coeffs, &fir->history[fir->curr_pos], fir->taps); + //assert(y_dot == y); + + if (fir->curr_pos <= 0) + fir->curr_pos = fir->taps; + fir->curr_pos--; + return (int16_t) (y_dot >> 15); +} + +int main() { + int16_t taps[TAPS]; + fir16_state_t fir, fir_asm; + int16_t out, out_asm, in; + int i, before; + + for(i=0; i<TAPS; i++) + taps[i] = 0x8000; + + fir16_create(&fir, taps, TAPS); + fir16_create(&fir_asm, taps, TAPS); + + /* first check the results are the same for C and asm */ + + for(i=0; i<N; i++) { + in = i; + out = fir16(&fir, in); + out_asm = fir16_asm(&fir_asm, in); + //printf("[%d] out = %d out_asm = %d\n", i, out, out_asm); + assert(out == out_asm); + } + + printf("OK\n"); + + /* now measure the speed */ + + before = cycles(); + out = fir16(&fir, in); + printf("C version: %d cycles\n", cycles() - before); + before = cycles(); + out_asm = fir16_asm(&fir_asm, in); + printf("ASM version: %d cycles\n", cycles() - before); + + return 0; +}